summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-10 02:56:10 +0000
committerpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-10 02:56:10 +0000
commit5b040e597b56713c3f2d69a198079ace7af978d5 (patch)
tree56df9e3662cd13be3f7345d8b3499ed7ed542ace
parentcd5a32f483300bc2ba17f1b9aae589bd4f128eaa (diff)
downloadchromium_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.cc5
-rw-r--r--content/browser/gpu/browser_gpu_channel_host_factory.cc215
-rw-r--r--content/browser/gpu/browser_gpu_channel_host_factory.h80
-rw-r--r--content/common/gpu/client/gpu_channel_host.cc7
-rw-r--r--content/common/gpu/client/gpu_channel_host.h2
-rw-r--r--content/content_browser.gypi2
-rw-r--r--content/renderer/render_thread_impl.cc3
-rw-r--r--content/renderer/render_thread_impl.h2
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;