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..4b56a5cf43c87a082aec6108f891d945ed730646 |
| --- /dev/null |
| +++ b/content/browser/renderer_host/context_provider_factory_impl_android.cc |
| @@ -0,0 +1,220 @@ |
| +// 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() |
| + : widget(gfx::kNullAcceleratedWidget), |
| + support_locking(false), |
| + automatic_flushes(false), |
| + shared_context_provider(nullptr) {} |
| + |
| +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::CreateDisplayContextProvider( |
| + gfx::AcceleratedWidget widget, |
| + gpu::SharedMemoryLimits shared_memory_limits, |
| + gpu::gles2::ContextCreationAttribHelper attributes, |
| + bool support_locking, |
| + bool automatic_flushes, |
| + ContextProviderCallback result_callback) { |
| + DCHECK(widget != gfx::kNullAcceleratedWidget); |
| + CreateContextProviderInternal(widget, shared_memory_limits, attributes, |
| + support_locking, automatic_flushes, nullptr, |
| + result_callback); |
| +} |
| + |
| +void ContextProviderFactoryImpl::CreateOffscreenContextProvider( |
| + gpu::SharedMemoryLimits shared_memory_limits, |
| + gpu::gles2::ContextCreationAttribHelper attributes, |
| + bool support_locking, |
| + bool automatic_flushes, |
| + cc::ContextProvider* shared_context_provider, |
| + ContextProviderCallback result_callback) { |
| + CreateContextProviderInternal(gfx::kNullAcceleratedWidget, |
| + shared_memory_limits, attributes, |
| + support_locking, automatic_flushes, |
| + shared_context_provider, result_callback); |
| +} |
| + |
| +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::CreateContextProviderInternal( |
| + gfx::AcceleratedWidget widget, |
| + gpu::SharedMemoryLimits shared_memory_limits, |
| + gpu::gles2::ContextCreationAttribHelper attributes, |
| + bool support_locking, |
| + bool automatic_flushes, |
| + cc::ContextProvider* shared_context_provider, |
| + 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.shared_context_provider = shared_context_provider; |
| + context_request.result_callback = result_callback; |
| + |
| + context_provider_requests_.push_back(context_request); |
| + HandlePendingRequests(); |
| +} |
| + |
| +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) { |
| + scoped_refptr<cc::ContextProvider> context_provider; |
| + |
| + 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) { |
| + context_request.result_callback.Run(context_provider); |
| + continue; |
| + } |
| + |
| + 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, |
| + static_cast<ContextProviderCommandBuffer*>( |
| + context_request.shared_context_provider), |
| + create_onscreen_context |
| + ? command_buffer_metrics::DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT |
|
Khushal
2016/08/04 20:49:33
Btw, is this okay? Or do we need something else fo
no sievers
2016/08/04 21:02:34
You can add a type if you don't want it tracked as
Khushal
2016/08/04 22:04:25
Thanks, added another type. I figured it shouldn't
|
| + : command_buffer_metrics::RENDER_COMPOSITOR_CONTEXT); |
| + context_request.result_callback.Run(context_provider); |
| + } |
| + } |
| + } |
| + |
| + if (!context_provider_requests_.empty()) |
| + HandlePendingRequests(); |
| +} |
| + |
| +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 |