OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/render_thread_impl.h" | 5 #include "content/renderer/render_thread_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <map> | 9 #include <map> |
10 #include <vector> | 10 #include <vector> |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 } | 259 } |
260 | 260 |
261 private: | 261 private: |
262 const std::string scheme_; | 262 const std::string scheme_; |
263 const std::string host_; | 263 const std::string host_; |
264 const double zoom_level_; | 264 const double zoom_level_; |
265 | 265 |
266 DISALLOW_COPY_AND_ASSIGN(RenderViewZoomer); | 266 DISALLOW_COPY_AND_ASSIGN(RenderViewZoomer); |
267 }; | 267 }; |
268 | 268 |
269 class CompositorRasterThread : public base::SimpleThread { | |
270 public: | |
271 CompositorRasterThread(cc::TaskGraphRunner* task_graph_runner, | |
272 const std::string& name_prefix, | |
273 base::SimpleThread::Options options) | |
274 : base::SimpleThread(name_prefix, options), | |
275 task_graph_runner_(task_graph_runner) {} | |
276 | |
277 // Overridden from base::SimpleThread: | |
278 void Run() override { task_graph_runner_->Run(); } | |
279 | |
280 private: | |
281 cc::TaskGraphRunner* task_graph_runner_; | |
282 | |
283 DISALLOW_COPY_AND_ASSIGN(CompositorRasterThread); | |
284 }; | |
285 | |
286 std::string HostToCustomHistogramSuffix(const std::string& host) { | 269 std::string HostToCustomHistogramSuffix(const std::string& host) { |
287 if (host == "mail.google.com") | 270 if (host == "mail.google.com") |
288 return ".gmail"; | 271 return ".gmail"; |
289 if (host == "docs.google.com" || host == "drive.google.com") | 272 if (host == "docs.google.com" || host == "drive.google.com") |
290 return ".docs"; | 273 return ".docs"; |
291 if (host == "plus.google.com") | 274 if (host == "plus.google.com") |
292 return ".plus"; | 275 return ".plus"; |
293 if (host == "inbox.google.com") | 276 if (host == "inbox.google.com") |
294 return ".inbox"; | 277 return ".inbox"; |
295 return std::string(); | 278 return std::string(); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 attributes.shareResources = true; | 372 attributes.shareResources = true; |
390 attributes.depth = false; | 373 attributes.depth = false; |
391 attributes.stencil = false; | 374 attributes.stencil = false; |
392 attributes.antialias = false; | 375 attributes.antialias = false; |
393 attributes.noAutomaticFlushes = true; | 376 attributes.noAutomaticFlushes = true; |
394 return attributes; | 377 return attributes; |
395 } | 378 } |
396 | 379 |
397 } // namespace | 380 } // namespace |
398 | 381 |
| 382 class RasterWorkerPool : public base::SequencedTaskRunner, |
| 383 public base::DelegateSimpleThread::Delegate { |
| 384 public: |
| 385 RasterWorkerPool() |
| 386 : namespace_token_(task_graph_runner_.GetNamespaceToken()) {} |
| 387 |
| 388 void Start(int num_threads, |
| 389 const base::SimpleThread::Options& thread_options) { |
| 390 DCHECK(threads_.empty()); |
| 391 while (threads_.size() < static_cast<size_t>(num_threads)) { |
| 392 scoped_ptr<base::DelegateSimpleThread> thread( |
| 393 new base::DelegateSimpleThread( |
| 394 this, base::StringPrintf( |
| 395 "CompositorTileWorker%u", |
| 396 static_cast<unsigned>(threads_.size() + 1)).c_str(), |
| 397 thread_options)); |
| 398 thread->Start(); |
| 399 threads_.push_back(thread.Pass()); |
| 400 } |
| 401 } |
| 402 |
| 403 void Shutdown() { |
| 404 // Shutdown raster threads. |
| 405 task_graph_runner_.Shutdown(); |
| 406 while (!threads_.empty()) { |
| 407 threads_.back()->Join(); |
| 408 threads_.pop_back(); |
| 409 } |
| 410 } |
| 411 |
| 412 // Overridden from base::TaskRunner: |
| 413 bool PostDelayedTask(const tracked_objects::Location& from_here, |
| 414 const base::Closure& task, |
| 415 base::TimeDelta delay) override { |
| 416 return PostNonNestableDelayedTask(from_here, task, delay); |
| 417 } |
| 418 |
| 419 bool RunsTasksOnCurrentThread() const override { return true; } |
| 420 |
| 421 // Overridden from base::SequencedTaskRunner: |
| 422 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
| 423 const base::Closure& task, |
| 424 base::TimeDelta delay) override { |
| 425 base::AutoLock lock(lock_); |
| 426 DCHECK(!threads_.empty()); |
| 427 |
| 428 // Remove completed tasks. |
| 429 DCHECK(completed_tasks_.empty()); |
| 430 task_graph_runner_.CollectCompletedTasks(namespace_token_, |
| 431 &completed_tasks_); |
| 432 DCHECK_LE(completed_tasks_.size(), tasks_.size()); |
| 433 DCHECK(std::equal(completed_tasks_.begin(), completed_tasks_.end(), |
| 434 tasks_.begin())); |
| 435 tasks_.erase(tasks_.begin(), tasks_.begin() + completed_tasks_.size()); |
| 436 completed_tasks_.clear(); |
| 437 |
| 438 tasks_.push_back(make_scoped_refptr(new ClosureTask(task))); |
| 439 |
| 440 graph_.Reset(); |
| 441 for (const auto& task : tasks_) { |
| 442 cc::TaskGraph::Node node(task.get(), 0, graph_.nodes.size()); |
| 443 if (graph_.nodes.size()) { |
| 444 graph_.edges.push_back( |
| 445 cc::TaskGraph::Edge(graph_.nodes.back().task, node.task)); |
| 446 } |
| 447 graph_.nodes.push_back(node); |
| 448 } |
| 449 |
| 450 task_graph_runner_.ScheduleTasks(namespace_token_, &graph_); |
| 451 return true; |
| 452 } |
| 453 |
| 454 // Overridden from base::DelegateSimpleThread::Delegate: |
| 455 void Run() override { task_graph_runner_.Run(); } |
| 456 |
| 457 cc::TaskGraphRunner* GetTaskGraphRunner() { return &task_graph_runner_; } |
| 458 |
| 459 protected: |
| 460 ~RasterWorkerPool() override {} |
| 461 |
| 462 private: |
| 463 // Simple Task for the TaskGraphRunner that wraps a closure. |
| 464 class ClosureTask : public cc::Task { |
| 465 public: |
| 466 ClosureTask(const base::Closure& closure) : closure_(closure) {} |
| 467 |
| 468 // Overridden from cc::Task: |
| 469 void RunOnWorkerThread() override { |
| 470 closure_.Run(); |
| 471 closure_.Reset(); |
| 472 }; |
| 473 |
| 474 protected: |
| 475 ~ClosureTask() override {} |
| 476 |
| 477 private: |
| 478 base::Closure closure_; |
| 479 |
| 480 DISALLOW_COPY_AND_ASSIGN(ClosureTask); |
| 481 }; |
| 482 |
| 483 // The actual threads where work is done. |
| 484 ScopedVector<base::DelegateSimpleThread> threads_; |
| 485 cc::TaskGraphRunner task_graph_runner_; |
| 486 |
| 487 // Namespace where the SequencedTaskRunner tasks run. |
| 488 const cc::NamespaceToken namespace_token_; |
| 489 |
| 490 // Lock to exclusively access all the following members that are used to |
| 491 // implement the SequencedTaskRunner interface. |
| 492 base::Lock lock_; |
| 493 // List of tasks currently queued up for execution. |
| 494 ClosureTask::Vector tasks_; |
| 495 // Cached vector to avoid allocation when getting the list of complete tasks. |
| 496 ClosureTask::Vector completed_tasks_; |
| 497 // Graph object used for scheduling tasks. |
| 498 cc::TaskGraph graph_; |
| 499 }; |
| 500 |
399 // For measuring memory usage after each task. Behind a command line flag. | 501 // For measuring memory usage after each task. Behind a command line flag. |
400 class MemoryObserver : public base::MessageLoop::TaskObserver { | 502 class MemoryObserver : public base::MessageLoop::TaskObserver { |
401 public: | 503 public: |
402 MemoryObserver() {} | 504 MemoryObserver() {} |
403 ~MemoryObserver() override {} | 505 ~MemoryObserver() override {} |
404 | 506 |
405 void WillProcessTask(const base::PendingTask& pending_task) override {} | 507 void WillProcessTask(const base::PendingTask& pending_task) override {} |
406 | 508 |
407 void DidProcessTask(const base::PendingTask& pending_task) override { | 509 void DidProcessTask(const base::PendingTask& pending_task) override { |
408 LOCAL_HISTOGRAM_MEMORY_KB("Memory.RendererUsed", GetMemoryUsageKB()); | 510 LOCAL_HISTOGRAM_MEMORY_KB("Memory.RendererUsed", GetMemoryUsageKB()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 } | 558 } |
457 | 559 |
458 RenderThreadImpl* RenderThreadImpl::current() { | 560 RenderThreadImpl* RenderThreadImpl::current() { |
459 return lazy_tls.Pointer()->Get(); | 561 return lazy_tls.Pointer()->Get(); |
460 } | 562 } |
461 | 563 |
462 RenderThreadImpl::RenderThreadImpl(const InProcessChildThreadParams& params) | 564 RenderThreadImpl::RenderThreadImpl(const InProcessChildThreadParams& params) |
463 : ChildThreadImpl(Options::Builder() | 565 : ChildThreadImpl(Options::Builder() |
464 .InBrowserProcess(params) | 566 .InBrowserProcess(params) |
465 .UseMojoChannel(ShouldUseMojoChannel()) | 567 .UseMojoChannel(ShouldUseMojoChannel()) |
466 .Build()) { | 568 .Build()), |
| 569 raster_worker_pool_(new RasterWorkerPool()) { |
467 Init(); | 570 Init(); |
468 } | 571 } |
469 | 572 |
470 // When we run plugins in process, we actually run them on the render thread, | 573 // When we run plugins in process, we actually run them on the render thread, |
471 // which means that we need to make the render thread pump UI events. | 574 // which means that we need to make the render thread pump UI events. |
472 RenderThreadImpl::RenderThreadImpl( | 575 RenderThreadImpl::RenderThreadImpl( |
473 scoped_ptr<base::MessageLoop> main_message_loop) | 576 scoped_ptr<base::MessageLoop> main_message_loop) |
474 : ChildThreadImpl(Options::Builder() | 577 : ChildThreadImpl(Options::Builder() |
475 .UseMojoChannel(ShouldUseMojoChannel()) | 578 .UseMojoChannel(ShouldUseMojoChannel()) |
476 .Build()), | 579 .Build()), |
477 main_message_loop_(main_message_loop.Pass()) { | 580 main_message_loop_(main_message_loop.Pass()), |
| 581 raster_worker_pool_(new RasterWorkerPool()) { |
478 Init(); | 582 Init(); |
479 } | 583 } |
480 | 584 |
481 void RenderThreadImpl::Init() { | 585 void RenderThreadImpl::Init() { |
482 TRACE_EVENT_BEGIN_ETW("RenderThreadImpl::Init", 0, ""); | 586 TRACE_EVENT_BEGIN_ETW("RenderThreadImpl::Init", 0, ""); |
483 | 587 |
484 base::trace_event::TraceLog::GetInstance()->SetThreadSortIndex( | 588 base::trace_event::TraceLog::GetInstance()->SetThreadSortIndex( |
485 base::PlatformThread::CurrentId(), | 589 base::PlatformThread::CurrentId(), |
486 kTraceEventRendererMainThreadSortIndex); | 590 kTraceEventRendererMainThreadSortIndex); |
487 | 591 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 is_distance_field_text_enabled_ = false; | 744 is_distance_field_text_enabled_ = false; |
641 } | 745 } |
642 | 746 |
643 // Note that under Linux, the media library will normally already have | 747 // Note that under Linux, the media library will normally already have |
644 // been initialized by the Zygote before this instance became a Renderer. | 748 // been initialized by the Zygote before this instance became a Renderer. |
645 media::InitializeMediaLibrary(); | 749 media::InitializeMediaLibrary(); |
646 | 750 |
647 memory_pressure_listener_.reset(new base::MemoryPressureListener( | 751 memory_pressure_listener_.reset(new base::MemoryPressureListener( |
648 base::Bind(&RenderThreadImpl::OnMemoryPressure, base::Unretained(this)))); | 752 base::Bind(&RenderThreadImpl::OnMemoryPressure, base::Unretained(this)))); |
649 | 753 |
650 compositor_task_graph_runner_.reset(new cc::TaskGraphRunner); | |
651 | |
652 is_gather_pixel_refs_enabled_ = false; | 754 is_gather_pixel_refs_enabled_ = false; |
653 | 755 |
654 int num_raster_threads = 0; | 756 int num_raster_threads = 0; |
655 std::string string_value = | 757 std::string string_value = |
656 command_line.GetSwitchValueASCII(switches::kNumRasterThreads); | 758 command_line.GetSwitchValueASCII(switches::kNumRasterThreads); |
657 bool parsed_num_raster_threads = | 759 bool parsed_num_raster_threads = |
658 base::StringToInt(string_value, &num_raster_threads); | 760 base::StringToInt(string_value, &num_raster_threads); |
659 DCHECK(parsed_num_raster_threads) << string_value; | 761 DCHECK(parsed_num_raster_threads) << string_value; |
660 DCHECK_GT(num_raster_threads, 0); | 762 DCHECK_GT(num_raster_threads, 0); |
661 | 763 |
662 // Note: Currently, gathering of pixel refs when using a single | 764 // Note: Currently, gathering of pixel refs when using a single |
663 // raster thread doesn't provide any benefit. This might change | 765 // raster thread doesn't provide any benefit. This might change |
664 // in the future but we avoid it for now to reduce the cost of | 766 // in the future but we avoid it for now to reduce the cost of |
665 // Picture::Create. | 767 // Picture::Create. |
666 is_gather_pixel_refs_enabled_ = num_raster_threads > 1; | 768 is_gather_pixel_refs_enabled_ = num_raster_threads > 1; |
667 | 769 |
668 base::SimpleThread::Options thread_options; | 770 base::SimpleThread::Options thread_options; |
669 #if defined(OS_ANDROID) || defined(OS_LINUX) | 771 #if defined(OS_ANDROID) || defined(OS_LINUX) |
670 if (!command_line.HasSwitch( | 772 if (!command_line.HasSwitch( |
671 switches::kUseNormalPriorityForTileTaskWorkerThreads)) { | 773 switches::kUseNormalPriorityForTileTaskWorkerThreads)) { |
672 thread_options.set_priority(base::ThreadPriority::BACKGROUND); | 774 thread_options.set_priority(base::ThreadPriority::BACKGROUND); |
673 } | 775 } |
674 #endif | 776 #endif |
675 while (compositor_raster_threads_.size() < | 777 |
676 static_cast<size_t>(num_raster_threads)) { | 778 raster_worker_pool_->Start(num_raster_threads, thread_options); |
677 scoped_ptr<CompositorRasterThread> raster_thread(new CompositorRasterThread( | |
678 compositor_task_graph_runner_.get(), | |
679 base::StringPrintf("CompositorTileWorker%u", | |
680 static_cast<unsigned>( | |
681 compositor_raster_threads_.size() + 1)).c_str(), | |
682 thread_options)); | |
683 raster_thread->Start(); | |
684 compositor_raster_threads_.push_back(raster_thread.Pass()); | |
685 } | |
686 | 779 |
687 // TODO(boliu): In single process, browser main loop should set up the | 780 // TODO(boliu): In single process, browser main loop should set up the |
688 // discardable memory manager, and should skip this if kSingleProcess. | 781 // discardable memory manager, and should skip this if kSingleProcess. |
689 // See crbug.com/503724. | 782 // See crbug.com/503724. |
690 base::DiscardableMemoryAllocator::SetInstance( | 783 base::DiscardableMemoryAllocator::SetInstance( |
691 ChildThreadImpl::discardable_shared_memory_manager()); | 784 ChildThreadImpl::discardable_shared_memory_manager()); |
692 | 785 |
693 service_registry()->AddService<RenderFrameSetup>( | 786 service_registry()->AddService<RenderFrameSetup>( |
694 base::Bind(CreateRenderFrameSetup)); | 787 base::Bind(CreateRenderFrameSetup)); |
695 | 788 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 } | 847 } |
755 | 848 |
756 media_thread_.reset(); | 849 media_thread_.reset(); |
757 | 850 |
758 // AudioMessageFilter may be accessed on |media_thread_|, so shutdown after. | 851 // AudioMessageFilter may be accessed on |media_thread_|, so shutdown after. |
759 RemoveFilter(audio_message_filter_.get()); | 852 RemoveFilter(audio_message_filter_.get()); |
760 audio_message_filter_ = NULL; | 853 audio_message_filter_ = NULL; |
761 | 854 |
762 compositor_thread_.reset(); | 855 compositor_thread_.reset(); |
763 | 856 |
764 // Shutdown raster threads. | 857 raster_worker_pool_->Shutdown(); |
765 compositor_task_graph_runner_->Shutdown(); | |
766 while (!compositor_raster_threads_.empty()) { | |
767 compositor_raster_threads_.back()->Join(); | |
768 compositor_raster_threads_.pop_back(); | |
769 } | |
770 compositor_task_graph_runner_.reset(); | |
771 | 858 |
772 main_input_callback_.Cancel(); | 859 main_input_callback_.Cancel(); |
773 input_handler_manager_.reset(); | 860 input_handler_manager_.reset(); |
774 if (input_event_filter_.get()) { | 861 if (input_event_filter_.get()) { |
775 RemoveFilter(input_event_filter_.get()); | 862 RemoveFilter(input_event_filter_.get()); |
776 input_event_filter_ = NULL; | 863 input_event_filter_ = NULL; |
777 } | 864 } |
778 | 865 |
779 // RemoveEmbeddedWorkerRoute may be called while deleting | 866 // RemoveEmbeddedWorkerRoute may be called while deleting |
780 // EmbeddedWorkerDispatcher. So it must be deleted before deleting | 867 // EmbeddedWorkerDispatcher. So it must be deleted before deleting |
(...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1453 if (SynchronousCompositorFactory* factory = | 1540 if (SynchronousCompositorFactory* factory = |
1454 SynchronousCompositorFactory::GetInstance()) { | 1541 SynchronousCompositorFactory::GetInstance()) { |
1455 return factory->CreateExternalBeginFrameSource(routing_id); | 1542 return factory->CreateExternalBeginFrameSource(routing_id); |
1456 } | 1543 } |
1457 #endif | 1544 #endif |
1458 return make_scoped_ptr(new CompositorExternalBeginFrameSource( | 1545 return make_scoped_ptr(new CompositorExternalBeginFrameSource( |
1459 compositor_message_filter_.get(), sync_message_filter(), routing_id)); | 1546 compositor_message_filter_.get(), sync_message_filter(), routing_id)); |
1460 } | 1547 } |
1461 | 1548 |
1462 cc::TaskGraphRunner* RenderThreadImpl::GetTaskGraphRunner() { | 1549 cc::TaskGraphRunner* RenderThreadImpl::GetTaskGraphRunner() { |
1463 return compositor_task_graph_runner_.get(); | 1550 return raster_worker_pool_->GetTaskGraphRunner(); |
1464 } | 1551 } |
1465 | 1552 |
1466 bool RenderThreadImpl::IsGatherPixelRefsEnabled() { | 1553 bool RenderThreadImpl::IsGatherPixelRefsEnabled() { |
1467 return is_gather_pixel_refs_enabled_; | 1554 return is_gather_pixel_refs_enabled_; |
1468 } | 1555 } |
1469 | 1556 |
1470 bool RenderThreadImpl::IsMainThread() { | 1557 bool RenderThreadImpl::IsMainThread() { |
1471 return !!current(); | 1558 return !!current(); |
1472 } | 1559 } |
1473 | 1560 |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1790 media_thread_->Start(); | 1877 media_thread_->Start(); |
1791 | 1878 |
1792 #if defined(OS_ANDROID) | 1879 #if defined(OS_ANDROID) |
1793 renderer_demuxer_ = new RendererDemuxerAndroid(); | 1880 renderer_demuxer_ = new RendererDemuxerAndroid(); |
1794 AddFilter(renderer_demuxer_.get()); | 1881 AddFilter(renderer_demuxer_.get()); |
1795 #endif | 1882 #endif |
1796 } | 1883 } |
1797 return media_thread_->task_runner(); | 1884 return media_thread_->task_runner(); |
1798 } | 1885 } |
1799 | 1886 |
| 1887 base::SequencedTaskRunner* RenderThreadImpl::GetWorkerSequencedTaskRunner() { |
| 1888 return raster_worker_pool_.get(); |
| 1889 } |
| 1890 |
1800 void RenderThreadImpl::SampleGamepads(blink::WebGamepads* data) { | 1891 void RenderThreadImpl::SampleGamepads(blink::WebGamepads* data) { |
1801 blink_platform_impl_->sampleGamepads(*data); | 1892 blink_platform_impl_->sampleGamepads(*data); |
1802 } | 1893 } |
1803 | 1894 |
1804 bool RenderThreadImpl::RendererIsHidden() const { | 1895 bool RenderThreadImpl::RendererIsHidden() const { |
1805 return widget_count_ > 0 && hidden_widget_count_ == widget_count_; | 1896 return widget_count_ > 0 && hidden_widget_count_ == widget_count_; |
1806 } | 1897 } |
1807 | 1898 |
1808 void RenderThreadImpl::WidgetCreated() { | 1899 void RenderThreadImpl::WidgetCreated() { |
1809 bool renderer_was_hidden = RendererIsHidden(); | 1900 bool renderer_was_hidden = RendererIsHidden(); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1880 } | 1971 } |
1881 | 1972 |
1882 void RenderThreadImpl::PendingRenderFrameConnect::OnConnectionError() { | 1973 void RenderThreadImpl::PendingRenderFrameConnect::OnConnectionError() { |
1883 size_t erased = | 1974 size_t erased = |
1884 RenderThreadImpl::current()->pending_render_frame_connects_.erase( | 1975 RenderThreadImpl::current()->pending_render_frame_connects_.erase( |
1885 routing_id_); | 1976 routing_id_); |
1886 DCHECK_EQ(1u, erased); | 1977 DCHECK_EQ(1u, erased); |
1887 } | 1978 } |
1888 | 1979 |
1889 } // namespace content | 1980 } // namespace content |
OLD | NEW |