Chromium Code Reviews| Index: content/browser/renderer_host/compositor_impl_android.cc |
| diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc |
| index 49abcb2ce93af4880932990c093b24aec42ed6a5..cdd1c9524e776b844f41e7dced61df2fc806538d 100644 |
| --- a/content/browser/renderer_host/compositor_impl_android.cc |
| +++ b/content/browser/renderer_host/compositor_impl_android.cc |
| @@ -47,9 +47,9 @@ |
| #include "cc/trees/layer_tree_settings.h" |
| #include "components/display_compositor/compositor_overlay_candidate_validator_android.h" |
| #include "components/display_compositor/gl_helper.h" |
| +#include "content/browser/gpu/browser_gpu_channel_host_factory.h" |
| #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h" |
| #include "content/browser/gpu/compositor_util.h" |
| -#include "content/browser/renderer_host/context_provider_factory_impl_android.h" |
| #include "content/browser/renderer_host/render_widget_host_impl.h" |
| #include "content/common/host_shared_bitmap_manager.h" |
| #include "content/public/browser/android/compositor.h" |
| @@ -78,8 +78,44 @@ namespace content { |
| namespace { |
| +class SingleThreadTaskGraphRunner : public cc::SingleThreadTaskGraphRunner { |
| + public: |
| + SingleThreadTaskGraphRunner() { |
| + Start("CompositorTileWorker1", base::SimpleThread::Options()); |
| + } |
| + |
| + ~SingleThreadTaskGraphRunner() override { Shutdown(); } |
| +}; |
| + |
| +struct CompositorDependencies { |
| + SingleThreadTaskGraphRunner task_graph_runner; |
| + cc::SurfaceManager surface_manager; |
| + uint32_t next_sink_id = 1u; |
| + |
| +#if defined(ENABLE_VULKAN) |
| + scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider; |
| +#endif |
| +}; |
| + |
| +base::LazyInstance<CompositorDependencies> g_compositor_dependencies = |
| + LAZY_INSTANCE_INITIALIZER; |
| + |
| const unsigned int kMaxDisplaySwapBuffers = 1U; |
| +#if defined(ENABLE_VULKAN) |
| +scoped_refptr<cc::VulkanContextProvider> GetSharedVulkanContextProvider() { |
| + if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kEnableVulkan)) { |
| + scoped_refptr<cc::VulkanContextProvider> context_provider = |
| + g_compositor_dependencies.Get().vulkan_context_provider; |
| + if (!*context_provider) |
| + *context_provider = cc::VulkanInProcessContextProvider::Create(); |
| + return *context_provider; |
| + } |
| + return nullptr; |
| +} |
| +#endif |
| + |
| gpu::SharedMemoryLimits GetCompositorContextSharedMemoryLimits( |
| gfx::NativeWindow window) { |
| constexpr size_t kBytesPerPixel = 4; |
| @@ -291,20 +327,6 @@ class VulkanOutputSurface : public cc::OutputSurface { |
| static bool g_initialized = false; |
| -class SingleThreadTaskGraphRunner : public cc::SingleThreadTaskGraphRunner { |
| - public: |
| - SingleThreadTaskGraphRunner() { |
| - Start("CompositorTileWorker1", base::SimpleThread::Options()); |
| - } |
| - |
| - ~SingleThreadTaskGraphRunner() override { |
| - Shutdown(); |
| - } |
| -}; |
| - |
| -base::LazyInstance<SingleThreadTaskGraphRunner> g_task_graph_runner = |
| - LAZY_INSTANCE_INITIALIZER; |
| - |
| } // anonymous namespace |
| // static |
| @@ -320,14 +342,29 @@ void Compositor::Initialize() { |
| } |
| // static |
| +cc::SurfaceManager* CompositorImpl::GetSurfaceManager() { |
| + return &g_compositor_dependencies.Get().surface_manager; |
| +} |
| + |
| +// static |
| +cc::FrameSinkId CompositorImpl::AllocateFrameSinkId() { |
| + // The FrameSinkId generated here must be unique with |
| + // RenderWidgetHostViewAndroid's |
| + // FrameSinkId allocation. |
| + // TODO(crbug.com/685777): Centralize allocation in one place for easier |
| + // maintenance. |
| + return cc::FrameSinkId(0 /* client_id */, |
| + g_compositor_dependencies.Get().next_sink_id++); |
| +} |
| + |
| +// static |
| bool CompositorImpl::IsInitialized() { |
| return g_initialized; |
| } |
| CompositorImpl::CompositorImpl(CompositorClient* client, |
| gfx::NativeWindow root_window) |
| - : frame_sink_id_( |
| - ui::ContextProviderFactory::GetInstance()->AllocateFrameSinkId()), |
| + : frame_sink_id_(AllocateFrameSinkId()), |
| resource_manager_(root_window), |
| window_(NULL), |
| surface_handle_(gpu::kNullSurfaceHandle), |
| @@ -338,9 +375,7 @@ CompositorImpl::CompositorImpl(CompositorClient* client, |
| num_successive_context_creation_failures_(0), |
| compositor_frame_sink_request_pending_(false), |
| weak_factory_(this) { |
| - ui::ContextProviderFactory::GetInstance() |
| - ->GetSurfaceManager() |
| - ->RegisterFrameSinkId(frame_sink_id_); |
| + GetSurfaceManager()->RegisterFrameSinkId(frame_sink_id_); |
| DCHECK(client); |
| DCHECK(root_window); |
| DCHECK(root_window->GetLayer() == nullptr); |
| @@ -358,9 +393,7 @@ CompositorImpl::~CompositorImpl() { |
| root_window_->SetLayer(nullptr); |
| // Clean-up any surface references. |
| SetSurface(NULL); |
| - ui::ContextProviderFactory::GetInstance() |
| - ->GetSurfaceManager() |
| - ->InvalidateFrameSinkId(frame_sink_id_); |
| + GetSurfaceManager()->InvalidateFrameSinkId(frame_sink_id_); |
| } |
| ui::UIResourceProvider& CompositorImpl::GetUIResourceProvider() { |
| @@ -437,7 +470,7 @@ void CompositorImpl::CreateLayerTreeHost() { |
| cc::LayerTreeHost::InitParams params; |
| params.client = this; |
| - params.task_graph_runner = g_task_graph_runner.Pointer(); |
| + params.task_graph_runner = &g_compositor_dependencies.Get().task_graph_runner; |
| params.main_task_runner = base::ThreadTaskRunnerHandle::Get(); |
| params.settings = &settings; |
| params.mutator_host = animation_host_.get(); |
| @@ -559,11 +592,31 @@ void CompositorImpl::HandlePendingCompositorFrameSinkRequest() { |
| return; |
| #endif |
| +#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \ |
| + defined(SYZYASAN) || defined(CYGPROFILE_INSTRUMENTATION) |
| + const int64_t kGpuChannelTimeoutInSeconds = 40; |
| +#else |
| + // The GPU watchdog timeout is 15 seconds (1.5x the kGpuTimeout value due to |
| + // logic in GpuWatchdogThread). Make this slightly longer to give the GPU a |
| + // chance to crash itself before crashing the browser. |
| + const int64_t kGpuChannelTimeoutInSeconds = 20; |
| +#endif |
| + |
| + // Start the timer first, if the result comes synchronously, we want it to |
| + // stop in the callback. |
| + establish_gpu_channel_timeout_.Start( |
| + FROM_HERE, base::TimeDelta::FromSeconds(kGpuChannelTimeoutInSeconds), |
| + this, &CompositorImpl::OnGpuChannelTimeout); |
| + |
| DCHECK(surface_handle_ != gpu::kNullSurfaceHandle); |
| - ContextProviderFactoryImpl::GetInstance()->RequestGpuChannelHost(base::Bind( |
| + BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel(base::Bind( |
| &CompositorImpl::OnGpuChannelEstablished, weak_factory_.GetWeakPtr())); |
| } |
| +void CompositorImpl::OnGpuChannelTimeout() { |
| + LOG(FATAL) << "Timed out waiting for GPU channel."; |
| +} |
| + |
| #if defined(ENABLE_VULKAN) |
| void CompositorImpl::CreateVulkanOutputSurface() { |
| if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| @@ -571,8 +624,7 @@ void CompositorImpl::CreateVulkanOutputSurface() { |
| return; |
| scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider = |
| - ui::ContextProviderFactory::GetInstance() |
| - ->GetSharedVulkanContextProvider(); |
| + GetSharedVulkanContextProvider(); |
| if (!vulkan_context_provider) |
| return; |
| @@ -587,56 +639,54 @@ void CompositorImpl::CreateVulkanOutputSurface() { |
| #endif |
| void CompositorImpl::OnGpuChannelEstablished( |
| - scoped_refptr<gpu::GpuChannelHost> gpu_channel_host, |
| - ui::ContextProviderFactory::GpuChannelHostResult result) { |
| + scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) { |
| + establish_gpu_channel_timeout_.Stop(); |
| + |
| // We might end up queing multiple GpuChannel requests for the same |
| // CompositorFrameSink request as the visibility of the compositor changes, so |
| // the CompositorFrameSink request could have been handled already. |
| if (!compositor_frame_sink_request_pending_) |
| return; |
| - switch (result) { |
| - // Don't retry if we are shutting down. |
| - case ui::ContextProviderFactory::GpuChannelHostResult:: |
| - FAILURE_FACTORY_SHUTDOWN: |
| - break; |
| - case ui::ContextProviderFactory::GpuChannelHostResult:: |
| - FAILURE_GPU_PROCESS_INITIALIZATION_FAILED: |
| - HandlePendingCompositorFrameSinkRequest(); |
| - break; |
| - case ui::ContextProviderFactory::GpuChannelHostResult::SUCCESS: |
| - // We don't need the context anymore if we are invisible. |
| - if (!host_->IsVisible()) |
| - return; |
| - |
| - DCHECK(window_); |
| - DCHECK_NE(surface_handle_, gpu::kNullSurfaceHandle); |
| - scoped_refptr<cc::ContextProvider> context_provider = |
| - ContextProviderFactoryImpl::GetInstance() |
| - ->CreateDisplayContextProvider( |
| - surface_handle_, |
| - GetCompositorContextSharedMemoryLimits(root_window_), |
| - GetCompositorContextAttributes(has_transparent_background_), |
| - false /*support_locking*/, false /*automatic_flushes*/, |
| - std::move(gpu_channel_host)); |
| - if (!context_provider->BindToCurrentThread()) { |
| - LOG(ERROR) << "Failed to init ContextProvider for compositor."; |
| - LOG_IF(FATAL, ++num_successive_context_creation_failures_ >= 2) |
| - << "Too many context creation failures. Giving up... "; |
| - HandlePendingCompositorFrameSinkRequest(); |
| - break; |
| - } |
| - |
| - scoped_refptr<ui::ContextProviderCommandBuffer> |
| - context_provider_command_buffer = |
| - static_cast<ui::ContextProviderCommandBuffer*>( |
| - context_provider.get()); |
| - auto display_output_surface = base::MakeUnique<AndroidOutputSurface>( |
| - std::move(context_provider_command_buffer)); |
| - InitializeDisplay(std::move(display_output_surface), nullptr, |
| - std::move(context_provider)); |
| - break; |
| + if (!gpu_channel_host) { |
| + LOG_IF(FATAL, ++num_successive_gpu_initialization_failures_ > 2) |
|
boliu
2017/02/13 22:00:46
this is new..
if you want to add it, do it in a d
Khushal
2017/02/13 23:49:51
Sure. I'll put it in a separate patch.
|
| + << "Too many Gpu Initialization failures. Giving up..."; |
| + HandlePendingCompositorFrameSinkRequest(); |
| + return; |
| } |
| + num_successive_gpu_initialization_failures_ = 0; |
| + |
| + // We don't need the context anymore if we are invisible. |
| + if (!host_->IsVisible()) |
| + return; |
| + |
| + DCHECK(window_); |
| + DCHECK_NE(surface_handle_, gpu::kNullSurfaceHandle); |
| + constexpr bool support_locking = false; |
| + constexpr bool automatic_flushes = false; |
| + ui::ContextProviderCommandBuffer* shared_context = nullptr; |
| + scoped_refptr<ui::ContextProviderCommandBuffer> context_provider = |
| + new ui::ContextProviderCommandBuffer( |
| + std::move(gpu_channel_host), gpu::GPU_STREAM_DEFAULT, |
| + gpu::GpuStreamPriority::NORMAL, surface_handle_, |
| + GURL(std::string("chrome://gpu/CompositorImpl::") + |
| + std::string("CompositorContextProvider")), |
| + automatic_flushes, support_locking, |
| + GetCompositorContextSharedMemoryLimits(root_window_), |
| + GetCompositorContextAttributes(has_transparent_background_), |
| + shared_context, |
| + ui::command_buffer_metrics::DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT); |
| + if (!context_provider->BindToCurrentThread()) { |
| + LOG(ERROR) << "Failed to init ContextProvider for compositor."; |
| + LOG_IF(FATAL, ++num_successive_context_creation_failures_ >= 2) |
| + << "Too many context creation failures. Giving up... "; |
| + HandlePendingCompositorFrameSinkRequest(); |
| + } |
| + |
| + auto display_output_surface = |
| + base::MakeUnique<AndroidOutputSurface>(std::move(context_provider)); |
| + InitializeDisplay(std::move(display_output_surface), nullptr, |
| + std::move(context_provider)); |
| } |
| void CompositorImpl::InitializeDisplay( |
| @@ -654,8 +704,7 @@ void CompositorImpl::InitializeDisplay( |
| // TODO(danakj): Populate gpu_capabilities_ for VulkanContextProvider. |
| } |
| - cc::SurfaceManager* manager = |
| - ui::ContextProviderFactory::GetInstance()->GetSurfaceManager(); |
| + cc::SurfaceManager* manager = GetSurfaceManager(); |
| auto* task_runner = base::ThreadTaskRunnerHandle::Get().get(); |
| std::unique_ptr<cc::DisplayScheduler> scheduler(new cc::DisplayScheduler( |
| task_runner, display_output_surface->capabilities().max_frames_pending)); |
| @@ -744,9 +793,8 @@ cc::FrameSinkId CompositorImpl::GetFrameSinkId() { |
| void CompositorImpl::AddChildFrameSink(const cc::FrameSinkId& frame_sink_id) { |
| if (has_compositor_frame_sink_) { |
| - ui::ContextProviderFactory::GetInstance() |
| - ->GetSurfaceManager() |
| - ->RegisterFrameSinkHierarchy(frame_sink_id_, frame_sink_id); |
| + GetSurfaceManager()->RegisterFrameSinkHierarchy(frame_sink_id_, |
| + frame_sink_id); |
| } else { |
| pending_child_frame_sink_ids_.insert(frame_sink_id); |
| } |
| @@ -759,9 +807,8 @@ void CompositorImpl::RemoveChildFrameSink( |
| pending_child_frame_sink_ids_.erase(it); |
| return; |
| } |
| - ui::ContextProviderFactory::GetInstance() |
| - ->GetSurfaceManager() |
| - ->UnregisterFrameSinkHierarchy(frame_sink_id_, frame_sink_id); |
| + GetSurfaceManager()->UnregisterFrameSinkHierarchy(frame_sink_id_, |
| + frame_sink_id); |
| } |
| bool CompositorImpl::HavePendingReadbacks() { |