diff options
author | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-10 02:56:10 +0000 |
---|---|---|
committer | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-10 02:56:10 +0000 |
commit | 5b040e597b56713c3f2d69a198079ace7af978d5 (patch) | |
tree | 56df9e3662cd13be3f7345d8b3499ed7ed542ace | |
parent | cd5a32f483300bc2ba17f1b9aae589bd4f128eaa (diff) | |
download | chromium_src-5b040e597b56713c3f2d69a198079ace7af978d5.zip chromium_src-5b040e597b56713c3f2d69a198079ace7af978d5.tar.gz chromium_src-5b040e597b56713c3f2d69a198079ace7af978d5.tar.bz2 |
Add BrowserGpuChannelHostFactory
BUG=99516
TEST=None yet, integration tests coming in future CLs.
Review URL: http://codereview.chromium.org/9361052
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@121390 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/browser/browser_main_loop.cc | 5 | ||||
-rw-r--r-- | content/browser/gpu/browser_gpu_channel_host_factory.cc | 215 | ||||
-rw-r--r-- | content/browser/gpu/browser_gpu_channel_host_factory.h | 80 | ||||
-rw-r--r-- | content/common/gpu/client/gpu_channel_host.cc | 7 | ||||
-rw-r--r-- | content/common/gpu/client/gpu_channel_host.h | 2 | ||||
-rw-r--r-- | content/content_browser.gypi | 2 | ||||
-rw-r--r-- | content/renderer/render_thread_impl.cc | 3 | ||||
-rw-r--r-- | content/renderer/render_thread_impl.h | 2 |
8 files changed, 310 insertions, 6 deletions
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 6a0c1ca..00b2a87 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc @@ -15,6 +15,7 @@ #include "content/browser/browser_thread_impl.h" #include "content/browser/download/download_file_manager.h" #include "content/browser/download/save_file_manager.h" +#include "content/browser/gpu/browser_gpu_channel_host_factory.h" #include "content/browser/gpu/gpu_process_host_ui_shim.h" #include "content/browser/in_process_webkit/webkit_thread.h" #include "content/browser/plugin_service_impl.h" @@ -395,6 +396,8 @@ void BrowserMainLoop::RunMainMessageLoopParts( } } + BrowserGpuChannelHostFactory::Initialize(); + BrowserThreadsStarted(); if (parts_.get()) @@ -442,6 +445,8 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() { if (resource_dispatcher_host_.get()) resource_dispatcher_host_.get()->Shutdown(); + BrowserGpuChannelHostFactory::Terminate(); + // Must be size_t so we can subtract from it. for (size_t thread_id = BrowserThread::ID_COUNT - 1; thread_id >= (BrowserThread::UI + 1); diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc new file mode 100644 index 0000000..1b7fb7d --- /dev/null +++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc @@ -0,0 +1,215 @@ +// Copyright (c) 2012 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/gpu/browser_gpu_channel_host_factory.h" + +#include "base/bind.h" +#include "content/browser/gpu/gpu_data_manager.h" +#include "content/browser/gpu/gpu_process_host.h" +#include "content/browser/gpu/gpu_surface_tracker.h" +#include "content/common/gpu/gpu_messages.h" +#include "content/common/child_process_host_impl.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/common/content_client.h" + +namespace content { + +BrowserGpuChannelHostFactory::CreateRequest::CreateRequest() + : event(false, false), + route_id(MSG_ROUTING_NONE) { +} + +BrowserGpuChannelHostFactory::CreateRequest::~CreateRequest() { +} + +BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest() + : event(false, false), + gpu_process_handle(base::kNullProcessHandle) { +} + +BrowserGpuChannelHostFactory::EstablishRequest::~EstablishRequest() { +} + +void BrowserGpuChannelHostFactory::Initialize() { + new BrowserGpuChannelHostFactory(); +} + +void BrowserGpuChannelHostFactory::Terminate() { + delete instance(); +} + +BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory() + : gpu_client_id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), + shutdown_event_(new base::WaitableEvent(true, false)), + gpu_host_id_(0) { + set_instance(this); +} + +BrowserGpuChannelHostFactory::~BrowserGpuChannelHostFactory() { + shutdown_event_->Signal(); + set_instance(NULL); +} + +bool BrowserGpuChannelHostFactory::IsMainThread() { + return BrowserThread::CurrentlyOn(BrowserThread::UI); +} + +bool BrowserGpuChannelHostFactory::IsIOThread() { + return BrowserThread::CurrentlyOn(BrowserThread::IO); +} + +MessageLoop* BrowserGpuChannelHostFactory::GetMainLoop() { + return BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::UI); +} + +scoped_refptr<base::MessageLoopProxy> +BrowserGpuChannelHostFactory::GetIOLoopProxy() { + return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); +} + +base::WaitableEvent* BrowserGpuChannelHostFactory::GetShutDownEvent() { + return shutdown_event_.get(); +} + +scoped_ptr<base::SharedMemory> +BrowserGpuChannelHostFactory::AllocateSharedMemory(uint32 size) { + scoped_ptr<base::SharedMemory> shm(new base::SharedMemory()); + if (!shm->CreateAnonymous(size)) + return scoped_ptr<base::SharedMemory>(); + return shm.Pass(); +} + +void BrowserGpuChannelHostFactory::CreateViewCommandBufferOnIO( + CreateRequest* request, + int32 surface_id, + const GPUCreateCommandBufferConfig& init_params) { + GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); + if (!host) { + request->event.Signal(); + return; + } + + gfx::GLSurfaceHandle surface = + GpuSurfaceTracker::Get()->GetSurfaceHandle(surface_id); + + host->CreateViewCommandBuffer( + surface, + surface_id, + gpu_client_id_, + init_params, + base::Bind(&BrowserGpuChannelHostFactory::CommandBufferCreatedOnIO, + request)); +} + +// static +void BrowserGpuChannelHostFactory::CommandBufferCreatedOnIO( + CreateRequest* request, int32 route_id) { + request->route_id = route_id; + request->event.Signal(); +} + +int32 BrowserGpuChannelHostFactory::CreateViewCommandBuffer( + int32 surface_id, + const GPUCreateCommandBufferConfig& init_params) { + CreateRequest request; + GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind( + &BrowserGpuChannelHostFactory::CreateViewCommandBufferOnIO, + base::Unretained(this), + &request, + surface_id, + init_params)); + // We're blocking the UI thread, which is generally undesirable. + // In this case we need to wait for this before we can show any UI /anyway/, + // so it won't cause additional jank. + // TODO(piman): Make this asynchronous. + request.event.Wait(); + return request.route_id; +} + +void BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO( + EstablishRequest* request, + CauseForGpuLaunch cause_for_gpu_launch) { + GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); + if (!host) { + host = GpuProcessHost::GetForRenderer(gpu_client_id_, cause_for_gpu_launch); + if (!host) { + request->event.Signal(); + return; + } + gpu_host_id_ = host->host_id(); + } + + host->EstablishGpuChannel( + gpu_client_id_, + base::Bind(&BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO, + request)); +} + +// static +void BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO( + EstablishRequest* request, + const IPC::ChannelHandle& channel_handle, + base::ProcessHandle gpu_process_handle, + const GPUInfo& gpu_info) { + request->channel_handle = channel_handle; + request->gpu_process_handle = gpu_process_handle; + request->gpu_info = gpu_info; + request->event.Signal(); +} + +GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync( + CauseForGpuLaunch cause_for_gpu_launch) { + if (gpu_channel_.get()) { + // Recreate the channel if it has been lost. + if (gpu_channel_->state() == GpuChannelHost::kLost) + gpu_channel_ = NULL; + else + return gpu_channel_.get(); + } + // Ensure initialization on the main thread. + GpuDataManager::GetInstance(); + + EstablishRequest request; + GetIOLoopProxy()->PostTask( + FROM_HERE, + base::Bind( + &BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO, + base::Unretained(this), + &request, + cause_for_gpu_launch)); + // We're blocking the UI thread, which is generally undesirable. + // In this case we need to wait for this before we can show any UI /anyway/, + // so it won't cause additional jank. + // TODO(piman): Make this asynchronous. + request.event.Wait(); + + if (request.channel_handle.name.empty() || + request.gpu_process_handle == base::kNullProcessHandle) + return NULL; + + base::ProcessHandle browser_process_for_gpu; +#if defined(OS_WIN) + // Create a process handle that the GPU process can use to access our handles. + DuplicateHandle(base::GetCurrentProcessHandle(), + base::GetCurrentProcessHandle(), + request.gpu_process_handle, + &browser_process_for_gpu, + PROCESS_DUP_HANDLE, + FALSE, + 0); +#else + browser_process_for_gpu = base::GetCurrentProcessHandle(); +#endif + + gpu_channel_ = new GpuChannelHost(this); + gpu_channel_->set_gpu_info(request.gpu_info); + content::GetContentClient()->SetGpuInfo(request.gpu_info); + + // Connect to the GPU process if a channel name was received. + gpu_channel_->Connect(request.channel_handle, browser_process_for_gpu); + + return gpu_channel_.get(); +} + +} // namespace content diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h new file mode 100644 index 0000000..cecb3c4 --- /dev/null +++ b/content/browser/gpu/browser_gpu_channel_host_factory.h @@ -0,0 +1,80 @@ +// Copyright (c) 2012 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. + +#ifndef CONTENT_BROWSER_GPU_BROWSER_GPU_CHANNEL_HOST_FACTORY_H_ +#define CONTENT_BROWSER_GPU_BROWSER_GPU_CHANNEL_HOST_FACTORY_H_ +#pragma once + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/process.h" +#include "base/synchronization/waitable_event.h" +#include "content/common/gpu/client/gpu_channel_host.h" +#include "ipc/ipc_channel_handle.h" + +namespace content { + +class BrowserGpuChannelHostFactory : public GpuChannelHostFactory { + public: + static void Initialize(); + static void Terminate(); + + // GpuChannelHostFactory implementation. + virtual bool IsMainThread() OVERRIDE; + virtual bool IsIOThread() OVERRIDE; + virtual MessageLoop* GetMainLoop() OVERRIDE; + virtual scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() OVERRIDE; + virtual base::WaitableEvent* GetShutDownEvent() OVERRIDE; + virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory( + uint32 size) OVERRIDE; + virtual int32 CreateViewCommandBuffer( + int32 surface_id, + const GPUCreateCommandBufferConfig& init_params) OVERRIDE; + virtual GpuChannelHost* EstablishGpuChannelSync( + CauseForGpuLaunch cause_for_gpu_launch) OVERRIDE; + + private: + struct CreateRequest { + CreateRequest(); + ~CreateRequest(); + base::WaitableEvent event; + int32 route_id; + }; + + struct EstablishRequest { + EstablishRequest(); + ~EstablishRequest(); + base::WaitableEvent event; + IPC::ChannelHandle channel_handle; + base::ProcessHandle gpu_process_handle; + GPUInfo gpu_info; + }; + + BrowserGpuChannelHostFactory(); + virtual ~BrowserGpuChannelHostFactory(); + + void CreateViewCommandBufferOnIO( + CreateRequest* request, + int32 surface_id, + const GPUCreateCommandBufferConfig& init_params); + static void CommandBufferCreatedOnIO(CreateRequest* request, int32 route_id); + void EstablishGpuChannelOnIO(EstablishRequest* request, + CauseForGpuLaunch cause_for_gpu_launch); + static void GpuChannelEstablishedOnIO( + EstablishRequest* request, + const IPC::ChannelHandle& channel_handle, + base::ProcessHandle gpu_process_handle, + const GPUInfo& gpu_info); + + int gpu_client_id_; + scoped_ptr<base::WaitableEvent> shutdown_event_; + scoped_refptr<GpuChannelHost> gpu_channel_; + int gpu_host_id_; + + DISALLOW_COPY_AND_ASSIGN(BrowserGpuChannelHostFactory); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_GPU_BROWSER_GPU_CHANNEL_HOST_FACTORY_H_ diff --git a/content/common/gpu/client/gpu_channel_host.cc b/content/common/gpu/client/gpu_channel_host.cc index cdb93e8..16fee44 100644 --- a/content/common/gpu/client/gpu_channel_host.cc +++ b/content/common/gpu/client/gpu_channel_host.cc @@ -113,9 +113,10 @@ void GpuChannelHost::Connect( DCHECK(factory_->IsMainThread()); // Open a channel to the GPU process. We pass NULL as the main listener here // since we need to filter everything to route it to the right thread. + scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy(); channel_.reset(new IPC::SyncChannel( channel_handle, IPC::Channel::MODE_CLIENT, NULL, - factory_->GetIOLoopProxy(), true, + io_loop, true, factory_->GetShutDownEvent())); sync_filter_ = new IPC::SyncMessageFilter( @@ -286,7 +287,7 @@ void GpuChannelHost::AddRoute( int route_id, base::WeakPtr<IPC::Channel::Listener> listener) { DCHECK(MessageLoopProxy::current()); - MessageLoopProxy* io_loop = factory_->GetIOLoopProxy(); + scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy(); io_loop->PostTask(FROM_HERE, base::Bind(&GpuChannelHost::MessageFilter::AddRoute, channel_filter_.get(), route_id, listener, @@ -294,7 +295,7 @@ void GpuChannelHost::AddRoute( } void GpuChannelHost::RemoveRoute(int route_id) { - MessageLoopProxy* io_loop = factory_->GetIOLoopProxy(); + scoped_refptr<base::MessageLoopProxy> io_loop = factory_->GetIOLoopProxy(); io_loop->PostTask(FROM_HERE, base::Bind(&GpuChannelHost::MessageFilter::RemoveRoute, channel_filter_.get(), route_id)); diff --git a/content/common/gpu/client/gpu_channel_host.h b/content/common/gpu/client/gpu_channel_host.h index 1e6df16..38d0403 100644 --- a/content/common/gpu/client/gpu_channel_host.h +++ b/content/common/gpu/client/gpu_channel_host.h @@ -57,7 +57,7 @@ class CONTENT_EXPORT GpuChannelHostFactory { virtual bool IsMainThread() = 0; virtual bool IsIOThread() = 0; virtual MessageLoop* GetMainLoop() = 0; - virtual base::MessageLoopProxy* GetIOLoopProxy() = 0; + virtual scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() = 0; virtual base::WaitableEvent* GetShutDownEvent() = 0; virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory(uint32 size) = 0; virtual int32 CreateViewCommandBuffer( diff --git a/content/content_browser.gypi b/content/content_browser.gypi index fa2aa26..6e43dcb 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -313,6 +313,8 @@ 'browser/geolocation/win7_location_api_win.h', 'browser/geolocation/win7_location_provider_win.cc', 'browser/geolocation/win7_location_provider_win.h', + 'browser/gpu/browser_gpu_channel_host_factory.cc', + 'browser/gpu/browser_gpu_channel_host_factory.h', 'browser/gpu/gpu_blacklist.cc', 'browser/gpu/gpu_blacklist.h', 'browser/gpu/gpu_data_manager.cc', diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 09e9622..27996e8 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -694,7 +694,8 @@ bool RenderThreadImpl::IsIOThread() { MessageLoop* RenderThreadImpl::GetMainLoop() { return message_loop(); } -base::MessageLoopProxy* RenderThreadImpl::GetIOLoopProxy() { + +scoped_refptr<base::MessageLoopProxy> RenderThreadImpl::GetIOLoopProxy() { return ChildProcess::current()->io_message_loop_proxy(); } diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index b3cc602..505f585 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -125,7 +125,7 @@ class CONTENT_EXPORT RenderThreadImpl : public content::RenderThread, virtual bool IsMainThread() OVERRIDE; virtual bool IsIOThread() OVERRIDE; virtual MessageLoop* GetMainLoop() OVERRIDE; - virtual base::MessageLoopProxy* GetIOLoopProxy() OVERRIDE; + virtual scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() OVERRIDE; virtual base::WaitableEvent* GetShutDownEvent() OVERRIDE; virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory( uint32 size) OVERRIDE; |