Chromium Code Reviews| Index: content/browser/renderer_host/context_provider_factory_impl_android.cc |
| diff --git a/content/browser/renderer_host/context_provider_factory_impl_android.cc b/content/browser/renderer_host/context_provider_factory_impl_android.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5e9c9df9a4d2ac95ff78006f401a7857570df0cf |
| --- /dev/null |
| +++ b/content/browser/renderer_host/context_provider_factory_impl_android.cc |
| @@ -0,0 +1,257 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/renderer_host/context_provider_factory_impl_android.h" |
| + |
| +#include "base/auto_reset.h" |
| +#include "base/command_line.h" |
| +#include "base/lazy_instance.h" |
| +#include "base/memory/singleton.h" |
| +#include "cc/output/context_provider.h" |
| +#include "cc/output/vulkan_in_process_context_provider.h" |
| +#include "cc/surfaces/surface_manager.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/gpu/gpu_surface_tracker.h" |
| +#include "content/common/gpu/client/context_provider_command_buffer.h" |
| +#include "content/common/host_shared_bitmap_manager.h" |
| +#include "content/public/common/content_switches.h" |
| +#include "gpu/command_buffer/client/gles2_interface.h" |
| +#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" |
| +#include "gpu/ipc/client/gpu_channel_host.h" |
| + |
| +namespace content { |
| + |
| +// static |
| +ContextProviderFactoryImpl* ContextProviderFactoryImpl::GetInstance() { |
| + return base::Singleton<ContextProviderFactoryImpl>::get(); |
| +} |
| + |
| +ContextProviderFactoryImpl::ContextProviderFactoryImpl() |
| + : in_handle_pending_requests_(false), |
| + surface_client_id_(0), |
| + weak_factory_(this) {} |
| + |
| +ContextProviderFactoryImpl::~ContextProviderFactoryImpl() {} |
| + |
| +ContextProviderFactoryImpl::ContextProvidersRequest::ContextProvidersRequest() = |
| + default; |
| + |
| +ContextProviderFactoryImpl::ContextProvidersRequest:: |
| + ~ContextProvidersRequest() = default; |
| + |
| +scoped_refptr<cc::VulkanContextProvider> |
| +ContextProviderFactoryImpl::GetSharedVulkanContextProvider() { |
| + if (!shared_vulkan_context_provider_) |
| + shared_vulkan_context_provider_ = |
| + cc::VulkanInProcessContextProvider::Create(); |
| + |
| + return shared_vulkan_context_provider_.get(); |
| +} |
| + |
| +void ContextProviderFactoryImpl::RequestContextProviders( |
| + gfx::AcceleratedWidget widget, |
| + gpu::SharedMemoryLimits shared_memory_limits, |
| + gpu::gles2::ContextCreationAttribHelper attributes, |
| + bool support_locking, |
| + bool automatic_flushes, |
| + ContextProviderCallback result_callback) { |
| + DCHECK(!result_callback.is_null()); |
| + |
| + ContextProvidersRequest context_request; |
| + context_request.widget = widget; |
| + context_request.shared_memory_limits = shared_memory_limits; |
| + context_request.attributes = attributes; |
| + context_request.support_locking = support_locking; |
| + context_request.automatic_flushes = automatic_flushes; |
| + context_request.result_callback = result_callback; |
| + |
| + context_provider_requests_.push_back(context_request); |
| + HandlePendingRequests(); |
| +} |
| + |
| +cc::SurfaceManager* ContextProviderFactoryImpl::GetSurfaceManager() { |
| + if (!surface_manager_) |
| + surface_manager_ = base::WrapUnique(new cc::SurfaceManager); |
| + |
| + return surface_manager_.get(); |
| +} |
| + |
| +uint32_t ContextProviderFactoryImpl::AllocateSurfaceClientId() { |
| + return ++surface_client_id_; |
| +} |
| + |
| +cc::SharedBitmapManager* ContextProviderFactoryImpl::GetSharedBitmapManager() { |
| + return HostSharedBitmapManager::current(); |
| +} |
| + |
| +gpu::GpuMemoryBufferManager* |
| +ContextProviderFactoryImpl::GetGpuMemoryBufferManager() { |
| + return BrowserGpuMemoryBufferManager::current(); |
| +} |
| + |
| +void ContextProviderFactoryImpl::HandlePendingRequests() { |
| + // Failure to initialize the context could result in new requests. Handle |
| + // them after going through the current list. |
| + if (in_handle_pending_requests_) |
| + return; |
| + |
| + { |
| + base::AutoReset<bool> auto_reset_in_handle_requests( |
| + &in_handle_pending_requests_, true); |
| + |
| + scoped_refptr<gpu::GpuChannelHost> gpu_channel_host( |
| + EnsureGpuChannelEstablished()); |
| + if (!gpu_channel_host) |
| + return; |
| + |
| + if (!context_provider_requests_.empty()) { |
| + std::list<ContextProvidersRequest> context_requests = |
| + context_provider_requests_; |
| + context_provider_requests_.clear(); |
| + |
| + for (ContextProvidersRequest& context_request : context_requests) { |
| + ContextProviders context_providers; |
| + CreateCompositorContexts(context_providers, context_request, |
| + gpu_channel_host); |
| + context_request.result_callback.Run(context_providers); |
| + } |
| + } |
| + } |
| + |
| + if (!context_provider_requests_.empty()) |
| + HandlePendingRequests(); |
| +} |
| + |
| +void ContextProviderFactoryImpl::CreateCompositorContexts( |
| + ContextProviders& context_providers, |
| + ContextProvidersRequest& context_request, |
|
no sievers
2016/08/02 20:44:34
nit: pass by pointer per style guide for non-const
Khushal
2016/08/02 22:22:16
Done.
|
| + scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) { |
|
no sievers
2016/08/02 20:44:34
nit: const scoped_refptr<>&
Khushal
2016/08/02 22:22:16
Done.
|
| + DCHECK(gpu_channel_host); |
| + |
| + const bool create_onscreen_context = |
| + context_request.widget != gfx::kNullAcceleratedWidget; |
| + gpu::SurfaceHandle surface_handle = |
| + create_onscreen_context |
| + ? GpuSurfaceTracker::GetInstance()->GetSurfaceForNativeWidget( |
| + context_request.widget) |
| + : gpu::kNullSurfaceHandle; |
| + |
| + // Is the request for an onscreen context? Make sure the surface is |
| + // still valid in that case. |
| + if (create_onscreen_context && surface_handle == gpu::kNullSurfaceHandle) |
| + return; |
| + |
| + scoped_refptr<ContextProviderCommandBuffer> worker_context_provider; |
| + // The display compositor does not use a worker context. |
| + if (!create_onscreen_context) { |
| + worker_context_provider = |
| + SharedCompositorWorkerContextProvider(gpu_channel_host); |
| + |
| + // Cause the compositor to wait and try again. |
| + if (!worker_context_provider) |
| + return; |
| + } |
| + |
| + // The compositor context shares resources with the worker context unless |
| + // the worker is async. |
| + ContextProviderCommandBuffer* share_context = worker_context_provider.get(); |
| + if (IsAsyncWorkerContextEnabled()) |
| + share_context = nullptr; |
| + |
| + context_providers.compositor_context_provider = |
| + new ContextProviderCommandBuffer( |
| + gpu_channel_host, gpu::GPU_STREAM_DEFAULT, |
| + gpu::GpuStreamPriority::NORMAL, surface_handle, |
| + GURL(std::string("chrome://gpu/ContextProviderFactoryImpl::") + |
| + std::string("CompositorContextProvider")), |
| + context_request.automatic_flushes, context_request.support_locking, |
| + context_request.shared_memory_limits, context_request.attributes, |
| + share_context, |
| + create_onscreen_context |
| + ? command_buffer_metrics::DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT |
| + : command_buffer_metrics::RENDER_COMPOSITOR_CONTEXT); |
| + context_providers.worker_context_provider = worker_context_provider; |
| +} |
| + |
| +scoped_refptr<ContextProviderCommandBuffer> |
| +ContextProviderFactoryImpl::SharedCompositorWorkerContextProvider( |
| + scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) { |
| + // Try to reuse existing shared worker context provider. |
| + if (shared_worker_context_provider_) { |
| + // Note: If context is lost, delete reference after releasing the lock. |
| + cc::ContextProvider::ScopedContextLock lock( |
| + shared_worker_context_provider_.get()); |
| + if (shared_worker_context_provider_->ContextGL() |
| + ->GetGraphicsResetStatusKHR() == GL_NO_ERROR) |
| + return shared_worker_context_provider_; |
| + } |
| + |
| + int32_t stream_id = gpu::GPU_STREAM_DEFAULT; |
| + gpu::GpuStreamPriority stream_priority = gpu::GpuStreamPriority::NORMAL; |
| + if (IsAsyncWorkerContextEnabled()) { |
| + stream_id = gpu_channel_host->GenerateStreamID(); |
| + stream_priority = gpu::GpuStreamPriority::LOW; |
| + } |
| + |
| + bool support_locking = true; |
| + gpu::gles2::ContextCreationAttribHelper attributes; |
| + attributes.alpha_size = -1; |
| + attributes.depth_size = 0; |
| + attributes.stencil_size = 0; |
| + attributes.samples = 0; |
| + attributes.sample_buffers = 0; |
| + attributes.bind_generates_resource = false; |
| + attributes.lose_context_when_out_of_memory = true; |
| + const bool automatic_flushes = false; |
| + |
| + shared_worker_context_provider_ = new ContextProviderCommandBuffer( |
| + std::move(gpu_channel_host), stream_id, stream_priority, |
| + gpu::kNullSurfaceHandle, |
| + GURL(std::string("chrome://gpu/ContextProviderFactoryImpl::") + |
| + std::string("SharedCompositorWorkerContextProvider")), |
| + automatic_flushes, support_locking, gpu::SharedMemoryLimits(), attributes, |
| + nullptr, command_buffer_metrics::RENDER_WORKER_CONTEXT); |
| + |
| + if (!shared_worker_context_provider_->BindToCurrentThread()) |
| + shared_worker_context_provider_ = nullptr; |
| + return shared_worker_context_provider_; |
| +} |
| + |
| +gpu::GpuChannelHost* ContextProviderFactoryImpl::EnsureGpuChannelEstablished() { |
| +#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \ |
| + defined(SYZYASAN) || defined(CYGPROFILE_INSTRUMENTATION) |
| + const int64_t kGpuChannelTimeoutInSeconds = 40; |
| +#else |
| + const int64_t kGpuChannelTimeoutInSeconds = 10; |
| +#endif |
| + |
| + BrowserGpuChannelHostFactory* factory = |
| + BrowserGpuChannelHostFactory::instance(); |
| + |
| + if (factory->GetGpuChannel()) |
| + return factory->GetGpuChannel(); |
| + |
| + factory->EstablishGpuChannel( |
| + CAUSE_FOR_GPU_LAUNCH_DISPLAY_COMPOSITOR_CONTEXT, |
| + base::Bind(&ContextProviderFactoryImpl::OnGpuChannelEstablished, |
| + weak_factory_.GetWeakPtr())); |
| + establish_gpu_channel_timeout_.Start( |
| + FROM_HERE, base::TimeDelta::FromSeconds(kGpuChannelTimeoutInSeconds), |
| + this, &ContextProviderFactoryImpl::OnGpuChannelTimeout); |
| + |
| + return nullptr; |
| +} |
| + |
| +void ContextProviderFactoryImpl::OnGpuChannelEstablished() { |
| + establish_gpu_channel_timeout_.Stop(); |
| + HandlePendingRequests(); |
| +} |
| + |
| +void ContextProviderFactoryImpl::OnGpuChannelTimeout() { |
| + LOG(FATAL) << "Timed out waiting for GPU channel."; |
| +} |
| + |
| +} // namespace content |