summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-25 22:08:35 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-25 22:08:35 +0000
commit6217d397bf501ec1ec5b7270d493006badd4d87a (patch)
treefce6c8e9c15b79bab29a9535ce9929dd9d53735b /chrome
parent21dedcc12d21ccb288244249522d77bc074c501e (diff)
downloadchromium_src-6217d397bf501ec1ec5b7270d493006badd4d87a.zip
chromium_src-6217d397bf501ec1ec5b7270d493006badd4d87a.tar.gz
chromium_src-6217d397bf501ec1ec5b7270d493006badd4d87a.tar.bz2
Calling OpenGL from the renderer process
- Added ability for renderer processes to render to a real window (Windows only so far). - Added ability to create offscreen frame buffer objects that can be resized later. - OpenGL context can have a "parent" context that can access its last swapped back buffer through a texture ID. - Moved code to establish GPU channel from RenderWidget to RenderThread. - Changed way service size command buffer object lifetimes are managed. TEST=trybot and visual verification that OpenGL can clear the browser window to magenta. BUG=none Review URL: http://codereview.chromium.org/1136006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42679 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/gpu_process_host.cc14
-rw-r--r--chrome/browser/gpu_process_host.h12
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc8
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.h1
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc8
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h4
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.cc9
-rw-r--r--chrome/common/chrome_constants.cc2
-rw-r--r--chrome/common/chrome_constants.h2
-rw-r--r--chrome/common/gpu_messages_internal.h23
-rw-r--r--chrome/common/render_messages_internal.h6
-rw-r--r--chrome/gpu/gpu_channel.cc112
-rw-r--r--chrome/gpu/gpu_channel.h32
-rw-r--r--chrome/gpu/gpu_command_buffer_stub.cc34
-rw-r--r--chrome/gpu/gpu_command_buffer_stub.h16
-rw-r--r--chrome/gpu/gpu_thread.cc24
-rw-r--r--chrome/gpu/gpu_thread.h4
-rw-r--r--chrome/plugin/command_buffer_stub.cc6
-rw-r--r--chrome/plugin/command_buffer_stub.h2
-rw-r--r--chrome/renderer/command_buffer_proxy.cc4
-rw-r--r--chrome/renderer/command_buffer_proxy.h4
-rw-r--r--chrome/renderer/ggl/ggl.cc88
-rw-r--r--chrome/renderer/ggl/ggl.h34
-rw-r--r--chrome/renderer/gpu_channel_host.cc34
-rw-r--r--chrome/renderer/gpu_channel_host.h10
-rw-r--r--chrome/renderer/render_thread.cc50
-rw-r--r--chrome/renderer/render_thread.h16
-rw-r--r--chrome/renderer/render_widget.cc46
-rw-r--r--chrome/renderer/render_widget.h15
29 files changed, 431 insertions, 189 deletions
diff --git a/chrome/browser/gpu_process_host.cc b/chrome/browser/gpu_process_host.cc
index fc10107..9fa0092 100644
--- a/chrome/browser/gpu_process_host.cc
+++ b/chrome/browser/gpu_process_host.cc
@@ -126,13 +126,11 @@ void GpuProcessHost::RemoveRoute(int32 routing_id) {
router_.RemoveRoute(routing_id);
}
-void GpuProcessHost::EstablishGpuChannel(
- int renderer_id,
- int routing_id) {
+void GpuProcessHost::EstablishGpuChannel(int renderer_id) {
if (Send(new GpuMsg_EstablishChannel(renderer_id)))
- sent_requests_.push(ChannelRequest(renderer_id, routing_id));
+ sent_requests_.push(ChannelRequest(renderer_id));
else
- ReplyToRenderer(renderer_id, routing_id, IPC::ChannelHandle());
+ ReplyToRenderer(renderer_id, IPC::ChannelHandle());
}
void GpuProcessHost::OnControlMessageReceived(const IPC::Message& message) {
@@ -146,21 +144,19 @@ void GpuProcessHost::OnChannelEstablished(
const IPC::ChannelHandle& channel_handle) {
const ChannelRequest& request = sent_requests_.front();
- ReplyToRenderer(request.renderer_id, request.routing_id, channel_handle);
+ ReplyToRenderer(request.renderer_id, channel_handle);
sent_requests_.pop();
}
void GpuProcessHost::ReplyToRenderer(
int renderer_id,
- int routing_id,
const IPC::ChannelHandle& channel) {
// Check whether the renderer process is still around.
RenderProcessHost* process_host = RenderProcessHost::FromID(renderer_id);
if (!process_host)
return;
- CHECK(process_host->Send(new ViewMsg_GpuChannelEstablished(routing_id,
- channel)));
+ CHECK(process_host->Send(new ViewMsg_GpuChannelEstablished(channel)));
}
void GpuProcessHost::PropagateBrowserCommandLineToGpu(
diff --git a/chrome/browser/gpu_process_host.h b/chrome/browser/gpu_process_host.h
index 36d068f..4d74e00 100644
--- a/chrome/browser/gpu_process_host.h
+++ b/chrome/browser/gpu_process_host.h
@@ -13,6 +13,7 @@
#include "chrome/browser/child_process_launcher.h"
#include "chrome/common/gpu_native_window_handle.h"
#include "chrome/common/message_router.h"
+#include "gfx/native_widget_types.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_channel_proxy.h"
@@ -50,26 +51,20 @@ class GpuProcessHost : public IPC::Channel::Sender,
// Tells the GPU process to create a new channel for communication with a
// renderer. Will asynchronously send message to object with given routing id
// on completion.
- void EstablishGpuChannel(int renderer_id, int routing_id);
+ void EstablishGpuChannel(int renderer_id);
private:
friend struct DefaultSingletonTraits<GpuProcessHost>;
// Used to queue pending channel requests.
struct ChannelRequest {
- ChannelRequest(int renderer_id,
- int routing_id) :
- renderer_id(renderer_id),
- routing_id(routing_id) {}
+ explicit ChannelRequest(int renderer_id) : renderer_id(renderer_id) {}
// Used to identify the renderer. The ID is used instead of a pointer to
// the RenderProcessHost in case it is destroyed while the request is
// pending.
// TODO(apatrick): investigate whether these IDs are used for future
// render processes.
int renderer_id;
-
- // Routing ID of object to receive reply message.
- int routing_id;
};
GpuProcessHost();
@@ -81,7 +76,6 @@ class GpuProcessHost : public IPC::Channel::Sender,
void OnChannelEstablished(const IPC::ChannelHandle& channel_handle);
void ReplyToRenderer(int renderer_id,
- int routing_id,
const IPC::ChannelHandle& channel);
// These are the channel requests that we have already sent to
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 0757d17..dccc34d 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -29,6 +29,7 @@
#include "chrome/browser/extensions/extension_message_service.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/user_script_master.h"
+#include "chrome/browser/gpu_process_host.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/net/url_request_context_getter.h"
@@ -45,6 +46,7 @@
#include "chrome/browser/visitedlink_master.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/child_process_info.h"
+#include "chrome/common/gpu_messages.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/pref_names.h"
@@ -770,6 +772,8 @@ void BrowserRenderProcessHost::OnMessageReceived(const IPC::Message& msg) {
OnExtensionRemoveListener)
IPC_MESSAGE_HANDLER(ViewHostMsg_ExtensionCloseChannel,
OnExtensionCloseChannel)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_EstablishGpuChannel,
+ OnMsgEstablishGpuChannel)
IPC_MESSAGE_HANDLER(ViewHostMsg_SpellChecker_RequestDictionary,
OnSpellCheckerRequestDictionary)
IPC_MESSAGE_UNHANDLED_ERROR()
@@ -974,6 +978,10 @@ void BrowserRenderProcessHost::OnExtensionCloseChannel(int port_id) {
}
}
+void BrowserRenderProcessHost::OnMsgEstablishGpuChannel() {
+ GpuProcessHost::Get()->EstablishGpuChannel(id());
+}
+
void BrowserRenderProcessHost::OnSpellCheckerRequestDictionary() {
if (profile()->GetSpellCheckHost()) {
// The spellchecker initialization already started and finished; just send
diff --git a/chrome/browser/renderer_host/browser_render_process_host.h b/chrome/browser/renderer_host/browser_render_process_host.h
index 277a53e..372045a 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.h
+++ b/chrome/browser/renderer_host/browser_render_process_host.h
@@ -110,6 +110,7 @@ class BrowserRenderProcessHost : public RenderProcessHost,
void OnExtensionAddListener(const std::string& event_name);
void OnExtensionRemoveListener(const std::string& event_name);
void OnExtensionCloseChannel(int port_id);
+ void OnMsgEstablishGpuChannel();
// Initialize support for visited links. Send the renderer process its initial
// set of visited links.
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index 152aae1..5dc9badc 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -8,7 +8,6 @@
#include "base/histogram.h"
#include "base/keyboard_codes.h"
#include "base/message_loop.h"
-#include "chrome/browser/gpu_process_host.h"
#include "chrome/browser/renderer_host/backing_store.h"
#include "chrome/browser/renderer_host/backing_store_manager.h"
#include "chrome/browser/renderer_host/render_process_host.h"
@@ -16,7 +15,6 @@
#include "chrome/browser/renderer_host/render_widget_host_painting_observer.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/renderer_host/video_layer.h"
-#include "chrome/common/gpu_messages.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/render_messages.h"
#include "webkit/glue/webcursor.h"
@@ -139,8 +137,6 @@ void RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnMsgFocusedNodeChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnMsgSetCursor)
IPC_MESSAGE_HANDLER(ViewHostMsg_ImeUpdateStatus, OnMsgImeUpdateStatus)
- IPC_MESSAGE_HANDLER(ViewHostMsg_EstablishGpuChannel,
- OnMsgEstablishGpuChannel)
#if defined(OS_LINUX)
IPC_MESSAGE_HANDLER(ViewHostMsg_CreatePluginContainer,
OnMsgCreatePluginContainer)
@@ -869,10 +865,6 @@ void RenderWidgetHost::OnMsgImeUpdateStatus(int control,
}
}
-void RenderWidgetHost::OnMsgEstablishGpuChannel() {
- GpuProcessHost::Get()->EstablishGpuChannel(process_->id(), routing_id_);
-}
-
#if defined(OS_LINUX)
void RenderWidgetHost::OnMsgCreatePluginContainer(gfx::PluginWindowHandle id) {
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index 5c95535..f8b8218 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -445,10 +445,6 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// having to bring in render_messages.h in a header file.
void OnMsgImeUpdateStatus(int control, const gfx::Rect& caret_rect);
- // Renderer process is requesting that the browser process establish a GPU
- // channel.
- void OnMsgEstablishGpuChannel();
-
#if defined(OS_LINUX)
void OnMsgCreatePluginContainer(gfx::PluginWindowHandle id);
void OnMsgDestroyPluginContainer(gfx::PluginWindowHandle id);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc
index 55e2762..2d08f42 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc
@@ -293,6 +293,15 @@ RenderWidgetHostViewWin::~RenderWidgetHostViewWin() {
void RenderWidgetHostViewWin::CreateWnd(HWND parent) {
Create(parent); // ATL function to create the window.
+
+ // Add a property indicating that a particular renderer is associated with
+ // this window. Used by the GPU process to validate window handles it
+ // receives from renderer processes.
+ int renderer_id = render_widget_host_->process()->id();
+ SetProp(m_hWnd,
+ chrome::kChromiumRendererIdProperty,
+ reinterpret_cast<HANDLE>(renderer_id));
+
// Uncommenting this will enable experimental out-of-process painting.
// Contact brettw for more,
// gpu_view_host_.reset(new GpuViewHost(render_widget_host_, m_hWnd));
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc
index 38cf59e..a6ad651 100644
--- a/chrome/common/chrome_constants.cc
+++ b/chrome/common/chrome_constants.cc
@@ -134,6 +134,8 @@ const int kHistogramSynchronizerReservedSequenceNumber = 0;
const int kMaxSessionHistoryEntries = 50;
+const wchar_t kChromiumRendererIdProperty[] = L"ChromiumRendererId";
+
} // namespace chrome
#undef FPL
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h
index 554a48b..456cea0 100644
--- a/chrome/common/chrome_constants.h
+++ b/chrome/common/chrome_constants.h
@@ -83,6 +83,8 @@ extern const int kHistogramSynchronizerReservedSequenceNumber;
// The maximum number of session history entries per tab.
extern const int kMaxSessionHistoryEntries;
+extern const wchar_t kChromiumRendererIdProperty[];
+
} // namespace chrome
#endif // CHROME_COMMON_CHROME_CONSTANTS_H_
diff --git a/chrome/common/gpu_messages_internal.h b/chrome/common/gpu_messages_internal.h
index 6780a5e..9107aed 100644
--- a/chrome/common/gpu_messages_internal.h
+++ b/chrome/common/gpu_messages_internal.h
@@ -9,6 +9,7 @@
// This file needs to be included again, even though we're actually included
// from it via utility_messages.h.
#include "base/shared_memory.h"
+#include "gfx/size.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_message_macros.h"
@@ -96,9 +97,21 @@ IPC_END_MESSAGES(GpuHost)
// These are messages from a renderer process to the GPU process.
IPC_BEGIN_MESSAGES(GpuChannel)
- // Tells the GPU process to create a new command buffer with the given
- // id. A corresponding GpuCommandBufferStub is created.
- IPC_SYNC_MESSAGE_CONTROL0_1(GpuChannelMsg_CreateCommandBuffer,
+ // Tells the GPU process to create a new command buffer that renders directly
+ // to a native view. A corresponding GpuCommandBufferStub is created.
+ IPC_SYNC_MESSAGE_CONTROL1_1(GpuChannelMsg_CreateViewCommandBuffer,
+ gfx::NativeViewId, /* view */
+ int32 /* route_id */)
+
+ // Tells the GPU process to create a new command buffer that renders to an
+ // offscreen frame buffer. If parent_route_id is not zero, the texture backing
+ // the frame buffer is mapped into the corresponding parent command buffer's
+ // namespace, with the name of parent_texture_id. This ID is in the parent's
+ // namespace.
+ IPC_SYNC_MESSAGE_CONTROL3_1(GpuChannelMsg_CreateOffscreenCommandBuffer,
+ int32, /* parent_route_id */
+ gfx::Size, /* size */
+ uint32, /* parent_texture_id */
int32 /* route_id */)
// The CommandBufferProxy sends this to the GpuCommandBufferStub in its
@@ -168,6 +181,10 @@ IPC_BEGIN_MESSAGES(GpuCommandBuffer)
// repainted.
IPC_MESSAGE_ROUTED0(GpuCommandBufferMsg_NotifyRepaint)
+ // Tells the GPU process to resize an offscreen frame buffer.
+ IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_ResizeOffscreenFrameBuffer,
+ gfx::Size /* size */)
+
#if defined(OS_MACOSX)
// On Mac OS X the GPU plugin must be offscreen, because there is no
// true cross-process window hierarchy. For this reason we must send
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index a0f5d14..0372a49 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -604,8 +604,8 @@ IPC_BEGIN_MESSAGES(View)
// The browser sends this to a renderer process in response to a
// ViewHostMsg_EstablishGpuChannel message.
- IPC_MESSAGE_ROUTED1(ViewMsg_GpuChannelEstablished,
- IPC::ChannelHandle /* handle to channel */)
+ IPC_MESSAGE_CONTROL1(ViewMsg_GpuChannelEstablished,
+ IPC::ChannelHandle /* handle to channel */)
// Notifies the renderer of the appcache that has been selected for a
// a particular host. This is sent in reply to AppCacheMsg_SelectCache.
@@ -1340,7 +1340,7 @@ IPC_BEGIN_MESSAGES(ViewHost)
// create connect to the GPU. The browser will create the GPU process if
// necessary, and will return a handle to the channel via
// a GpuChannelEstablished message.
- IPC_MESSAGE_ROUTED0(ViewHostMsg_EstablishGpuChannel)
+ IPC_MESSAGE_CONTROL0(ViewHostMsg_EstablishGpuChannel)
// A renderer sends this to the browser process when it wants to start
// a new instance of the Native Client process. The browser will launch
diff --git a/chrome/gpu/gpu_channel.cc b/chrome/gpu/gpu_channel.cc
index 4269022..b2b5bf9 100644
--- a/chrome/gpu/gpu_channel.cc
+++ b/chrome/gpu/gpu_channel.cc
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
#include "chrome/gpu/gpu_channel.h"
#include "base/command_line.h"
@@ -11,6 +15,7 @@
#include "base/waitable_event.h"
#include "build/build_config.h"
#include "chrome/common/child_process.h"
+#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/gpu_messages.h"
#include "chrome/gpu/gpu_thread.h"
@@ -27,44 +32,12 @@ class GpuReleaseTask : public Task {
}
};
-typedef base::hash_map<std::string, scoped_refptr<GpuChannel> >
- GpuChannelMap;
-
// How long we wait before releasing the GPU process.
const int kGpuReleaseTimeMS = 10000;
-
-GpuChannelMap g_gpu_channels;
} // namespace anonymous
-GpuChannel* GpuChannel::EstablishGpuChannel(int renderer_id) {
- // Map renderer ID to a (single) channel to that process.
- std::string channel_name = StringPrintf(
- "%d.r%d", base::GetCurrentProcId(), renderer_id);
-
- scoped_refptr<GpuChannel> channel;
-
- GpuChannelMap::const_iterator iter = g_gpu_channels.find(channel_name);
- if (iter == g_gpu_channels.end()) {
- channel = new GpuChannel;
- } else {
- channel = iter->second;
- }
-
- DCHECK(channel != NULL);
-
- if (!channel->channel_.get()) {
- if (channel->Init(channel_name)) {
- g_gpu_channels[channel_name] = channel;
- } else {
- channel = NULL;
- }
- }
-
- return channel.get();
-}
-
-GpuChannel::GpuChannel()
- : renderer_id_(-1)
+GpuChannel::GpuChannel(int renderer_id)
+ : renderer_id_(renderer_id)
#if defined(OS_POSIX)
, renderer_fd_(-1)
#endif
@@ -141,8 +114,10 @@ bool GpuChannel::Send(IPC::Message* message) {
void GpuChannel::OnControlMessageReceived(const IPC::Message& msg) {
IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg)
- IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateCommandBuffer,
- OnCreateCommandBuffer)
+ IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateViewCommandBuffer,
+ OnCreateViewCommandBuffer)
+ IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateOffscreenCommandBuffer,
+ OnCreateOffscreenCommandBuffer)
IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyCommandBuffer,
OnDestroyCommandBuffer)
IPC_MESSAGE_UNHANDLED_ERROR()
@@ -154,11 +129,57 @@ int GpuChannel::GenerateRouteID() {
return ++last_id;
}
-void GpuChannel::OnCreateCommandBuffer(int* route_id) {
+void GpuChannel::OnCreateViewCommandBuffer(gfx::NativeViewId view_id,
+ int32* route_id) {
+ *route_id = 0;
+
#if defined(ENABLE_GPU)
+
+#if defined(OS_WIN)
+ gfx::NativeView view = gfx::NativeViewFromId(view_id);
+
+ // Check that the calling renderer is allowed to render to this window.
+ // TODO(apatrick): consider killing the renderer process rather than failing.
+ int view_renderer_id = reinterpret_cast<int>(
+ GetProp(view, chrome::kChromiumRendererIdProperty));
+ if (view_renderer_id != renderer_id_)
+ return;
+#else
+ // TODO(apatrick): This needs to be something valid for mac and linux.
+ // Offscreen rendering will work on these platforms but not rendering to the
+ // window.
+ DCHECK_EQ(view_id, 0);
+ gfx::NativeView view = 0;
+#endif
+
*route_id = GenerateRouteID();
scoped_refptr<GpuCommandBufferStub> stub = new GpuCommandBufferStub(
- this, *route_id);
+ this, view, NULL, gfx::Size(), 0, *route_id);
+ router_.AddRoute(*route_id, stub);
+ stubs_[*route_id] = stub;
+#endif // ENABLE_GPU
+}
+
+void GpuChannel::OnCreateOffscreenCommandBuffer(int32 parent_route_id,
+ const gfx::Size& size,
+ uint32 parent_texture_id,
+ int32* route_id) {
+#if defined(ENABLE_GPU)
+ *route_id = GenerateRouteID();
+ scoped_refptr<GpuCommandBufferStub> parent_stub;
+ if (parent_route_id != 0) {
+ StubMap::iterator it = stubs_.find(parent_route_id);
+ DCHECK(it != stubs_.end());
+ parent_stub = it->second;
+ }
+
+ scoped_refptr<GpuCommandBufferStub> stub = new GpuCommandBufferStub(
+ this,
+ NULL,
+ parent_stub.get(),
+ size,
+ parent_texture_id,
+ *route_id);
router_.AddRoute(*route_id, stub);
stubs_[*route_id] = stub;
#else
@@ -166,7 +187,7 @@ void GpuChannel::OnCreateCommandBuffer(int* route_id) {
#endif
}
-void GpuChannel::OnDestroyCommandBuffer(int route_id) {
+void GpuChannel::OnDestroyCommandBuffer(int32 route_id) {
#if defined(ENABLE_GPU)
StubMap::iterator it = stubs_.find(route_id);
DCHECK(it != stubs_.end());
@@ -175,8 +196,13 @@ void GpuChannel::OnDestroyCommandBuffer(int route_id) {
#endif
}
-bool GpuChannel::Init(const std::string& channel_name) {
- channel_name_ = channel_name;
+bool GpuChannel::Init() {
+ // Check whether we're already initialized.
+ if (channel_.get())
+ return true;
+
+ // Map renderer ID to a (single) channel to that process.
+ std::string channel_name = GetChannelName();
#if defined(OS_POSIX)
// This gets called when the GpuChannel is initially created. At this
// point, create the socketpair and assign the GPU side FD to the channel
@@ -192,3 +218,7 @@ bool GpuChannel::Init(const std::string& channel_name) {
ChildProcess::current()->GetShutDownEvent()));
return true;
}
+
+std::string GpuChannel::GetChannelName() {
+ return StringPrintf("%d.r%d", base::GetCurrentProcId(), renderer_id_);
+}
diff --git a/chrome/gpu/gpu_channel.h b/chrome/gpu/gpu_channel.h
index 17ea363..60dc906 100644
--- a/chrome/gpu/gpu_channel.h
+++ b/chrome/gpu/gpu_channel.h
@@ -13,6 +13,8 @@
#include "build/build_config.h"
#include "chrome/common/message_router.h"
#include "chrome/gpu/gpu_command_buffer_stub.h"
+#include "gfx/native_widget_types.h"
+#include "gfx/size.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sync_channel.h"
@@ -23,17 +25,12 @@ class GpuChannel : public IPC::Channel::Listener,
public IPC::Message::Sender,
public base::RefCountedThreadSafe<GpuChannel> {
public:
- // Get a new GpuChannel object for the current process to talk to the
- // given renderer process. The renderer ID is an opaque unique ID generated
- // by the browser.
- //
- // POSIX only: If |channel_fd| > 0, use that file descriptor for the
- // channel socket.
- static GpuChannel* EstablishGpuChannel(int renderer_id);
-
+ explicit GpuChannel(int renderer_id);
virtual ~GpuChannel();
- std::string channel_name() const { return channel_name_; }
+ bool Init();
+
+ std::string GetChannelName();
base::ProcessHandle renderer_handle() const {
return renderer_process_.handle();
@@ -60,21 +57,20 @@ class GpuChannel : public IPC::Channel::Listener,
virtual bool Send(IPC::Message* msg);
private:
- // Called on the plugin thread
- GpuChannel();
-
- bool Init(const std::string& channel_name);
-
void OnControlMessageReceived(const IPC::Message& msg);
int GenerateRouteID();
// Message handlers.
- void OnCreateCommandBuffer(int* instance_id);
- void OnDestroyCommandBuffer(int instance_id);
+ void OnCreateViewCommandBuffer(gfx::NativeViewId view,
+ int32* route_id);
+ void OnCreateOffscreenCommandBuffer(int32 parent_route_id,
+ const gfx::Size& size,
+ uint32 parent_texture_id,
+ int32* route_id);
+ void OnDestroyCommandBuffer(int32 route_id);
scoped_ptr<IPC::SyncChannel> channel_;
- std::string channel_name_;
// Handle to the renderer process who is on the other side of the channel.
base::ScopedOpenProcess renderer_process_;
@@ -92,7 +88,7 @@ class GpuChannel : public IPC::Channel::Listener,
MessageRouter router_;
#if defined(ENABLE_GPU)
- typedef base::hash_map<int, scoped_refptr<GpuCommandBufferStub> > StubMap;
+ typedef base::hash_map<int32, scoped_refptr<GpuCommandBufferStub> > StubMap;
StubMap stubs_;
#endif
diff --git a/chrome/gpu/gpu_command_buffer_stub.cc b/chrome/gpu/gpu_command_buffer_stub.cc
index 6c3f5cc..5d6842d 100644
--- a/chrome/gpu/gpu_command_buffer_stub.cc
+++ b/chrome/gpu/gpu_command_buffer_stub.cc
@@ -6,6 +6,7 @@
#include "base/process_util.h"
#include "base/shared_memory.h"
+#include "build/build_config.h"
#include "chrome/common/gpu_messages.h"
#include "chrome/gpu/gpu_channel.h"
#include "chrome/gpu/gpu_command_buffer_stub.h"
@@ -13,12 +14,23 @@
using gpu::Buffer;
GpuCommandBufferStub::GpuCommandBufferStub(GpuChannel* channel,
+ gfx::NativeView view,
+ GpuCommandBufferStub* parent,
+ const gfx::Size& size,
+ uint32 parent_texture_id,
int32 route_id)
: channel_(channel),
+ view_(view),
+ parent_(parent),
+ initial_size_(size),
+ parent_texture_id_(parent_texture_id),
route_id_(route_id) {
}
GpuCommandBufferStub::~GpuCommandBufferStub() {
+ if (processor_.get()) {
+ processor_->Destroy();
+ }
}
void GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
@@ -34,6 +46,8 @@ void GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
OnDestroyTransferBuffer);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_GetTransferBuffer,
OnGetTransferBuffer);
+ IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ResizeOffscreenFrameBuffer,
+ OnResizeOffscreenFrameBuffer);
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP()
}
@@ -55,8 +69,18 @@ void GpuCommandBufferStub::OnInitialize(
if (command_buffer_->Initialize(size)) {
Buffer buffer = command_buffer_->GetRingBuffer();
if (buffer.shared_memory) {
- processor_ = new gpu::GPUProcessor(command_buffer_.get());
- if (processor_->Initialize(gfx::kNullPluginWindow)) {
+ gpu::GPUProcessor* parent_processor =
+ parent_ ? parent_->processor_.get() : NULL;
+ processor_.reset(new gpu::GPUProcessor(command_buffer_.get()));
+ // TODO(apatrick): The reinterpret_cast below is only valid on windows.
+#if !defined(OS_WIN)
+ DCHECK_EQ(view_, static_cast<gfx::NativeView>(0));
+#endif
+ if (processor_->Initialize(
+ reinterpret_cast<gfx::PluginWindowHandle>(view_),
+ parent_processor,
+ initial_size_,
+ parent_texture_id_)) {
command_buffer_->SetPutOffsetChangeCallback(
NewCallback(processor_.get(),
&gpu::GPUProcessor::ProcessCommands));
@@ -66,7 +90,7 @@ void GpuCommandBufferStub::OnInitialize(
buffer.shared_memory->ShareToProcess(channel_->renderer_handle(),
ring_buffer);
} else {
- processor_ = NULL;
+ processor_.reset();
command_buffer_.reset();
}
}
@@ -117,4 +141,8 @@ void GpuCommandBufferStub::OnGetTransferBuffer(
}
}
+void GpuCommandBufferStub::OnResizeOffscreenFrameBuffer(const gfx::Size& size) {
+ processor_->ResizeOffscreenFrameBuffer(size);
+}
+
#endif // ENABLE_GPU
diff --git a/chrome/gpu/gpu_command_buffer_stub.h b/chrome/gpu/gpu_command_buffer_stub.h
index eb927a3..7aaf68a 100644
--- a/chrome/gpu/gpu_command_buffer_stub.h
+++ b/chrome/gpu/gpu_command_buffer_stub.h
@@ -10,6 +10,7 @@
#include "base/process.h"
#include "base/ref_counted.h"
#include "gfx/native_widget_types.h"
+#include "gfx/size.h"
#include "gpu/command_buffer/service/command_buffer_service.h"
#include "gpu/command_buffer/service/gpu_processor.h"
#include "ipc/ipc_channel.h"
@@ -23,6 +24,10 @@ class GpuCommandBufferStub
public base::RefCountedThreadSafe<GpuCommandBufferStub> {
public:
GpuCommandBufferStub(GpuChannel* channel,
+ gfx::NativeView view,
+ GpuCommandBufferStub* parent,
+ const gfx::Size& size,
+ uint32 parent_texture_id,
int32 route_id);
virtual ~GpuCommandBufferStub();
@@ -33,7 +38,7 @@ class GpuCommandBufferStub
// IPC::Message::Sender implementation:
virtual bool Send(IPC::Message* msg);
- int route_id() const { return route_id_; }
+ int32 route_id() const { return route_id_; }
private:
// Message handlers:
@@ -47,12 +52,17 @@ class GpuCommandBufferStub
void OnGetTransferBuffer(int32 id,
base::SharedMemoryHandle* transfer_buffer,
uint32* size);
+ void OnResizeOffscreenFrameBuffer(const gfx::Size& size);
scoped_refptr<GpuChannel> channel_;
- int route_id_;
+ gfx::NativeView view_;
+ scoped_refptr<GpuCommandBufferStub> parent_;
+ gfx::Size initial_size_;
+ uint32 parent_texture_id_;
+ int32 route_id_;
scoped_ptr<gpu::CommandBufferService> command_buffer_;
- scoped_refptr<gpu::GPUProcessor> processor_;
+ scoped_ptr<gpu::GPUProcessor> processor_;
DISALLOW_COPY_AND_ASSIGN(GpuCommandBufferStub);
};
diff --git a/chrome/gpu/gpu_thread.cc b/chrome/gpu/gpu_thread.cc
index 1839412..9de441c 100644
--- a/chrome/gpu/gpu_thread.cc
+++ b/chrome/gpu/gpu_thread.cc
@@ -7,7 +7,6 @@
#include "build/build_config.h"
#include "chrome/common/child_process.h"
#include "chrome/common/gpu_messages.h"
-#include "chrome/gpu/gpu_channel.h"
#include "chrome/gpu/gpu_config.h"
#if defined(OS_WIN)
@@ -47,11 +46,28 @@ void GpuThread::OnControlMessageReceived(const IPC::Message& msg) {
}
void GpuThread::OnEstablishChannel(int renderer_id) {
- scoped_refptr<GpuChannel> channel =
- GpuChannel::EstablishGpuChannel(renderer_id);
+ scoped_refptr<GpuChannel> channel;
+
+ GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id);
+ if (iter == gpu_channels_.end()) {
+ channel = new GpuChannel(renderer_id);
+ } else {
+ channel = iter->second;
+ }
+
+ DCHECK(channel != NULL);
+
+ if (channel->Init()) {
+ // TODO(apatrick): figure out when to remove channels from the map. They
+ // will never be destroyed otherwise.
+ gpu_channels_[renderer_id] = channel;
+ } else {
+ channel = NULL;
+ }
+
IPC::ChannelHandle channel_handle;
if (channel.get()) {
- channel_handle.name = channel->channel_name();
+ channel_handle.name = channel->GetChannelName();
#if defined(OS_POSIX)
// On POSIX, pass the renderer-side FD. Also mark it as auto-close so that
// it gets closed after it has been sent.
diff --git a/chrome/gpu/gpu_thread.h b/chrome/gpu/gpu_thread.h
index c32b513..23b8ba1 100644
--- a/chrome/gpu/gpu_thread.h
+++ b/chrome/gpu/gpu_thread.h
@@ -10,6 +10,7 @@
#include "build/build_config.h"
#include "chrome/common/child_thread.h"
#include "chrome/common/gpu_native_window_handle.h"
+#include "chrome/gpu/gpu_channel.h"
#include "chrome/gpu/gpu_config.h"
#include "chrome/gpu/x_util.h"
#include "gfx/native_widget_types.h"
@@ -38,6 +39,9 @@ class GpuThread : public ChildThread {
void OnNewRenderWidgetHostView(GpuNativeWindowHandle parent_window,
int32 routing_id);
+ typedef base::hash_map<int, scoped_refptr<GpuChannel> > GpuChannelMap;
+ GpuChannelMap gpu_channels_;
+
#if defined(GPU_USE_GLX)
Display* display_;
scoped_ptr<GpuBackingStoreGLXContext> glx_context_;
diff --git a/chrome/plugin/command_buffer_stub.cc b/chrome/plugin/command_buffer_stub.cc
index 7dc049c..de18db6 100644
--- a/chrome/plugin/command_buffer_stub.cc
+++ b/chrome/plugin/command_buffer_stub.cc
@@ -92,8 +92,8 @@ void CommandBufferStub::OnInitialize(int32 size,
}
// Initialize the GPUProcessor.
- processor_ = new gpu::GPUProcessor(command_buffer_.get());
- if (!processor_->Initialize(window_)) {
+ processor_.reset(new gpu::GPUProcessor(command_buffer_.get()));
+ if (!processor_->Initialize(window_, NULL, gfx::Size(), 0)) {
Destroy();
return;
}
@@ -175,7 +175,7 @@ void CommandBufferStub::OnGetTransferBuffer(
}
void CommandBufferStub::Destroy() {
- processor_ = NULL;
+ processor_.reset();
command_buffer_.reset();
DestroyPlatformSpecific();
diff --git a/chrome/plugin/command_buffer_stub.h b/chrome/plugin/command_buffer_stub.h
index 026110f..83564ca 100644
--- a/chrome/plugin/command_buffer_stub.h
+++ b/chrome/plugin/command_buffer_stub.h
@@ -73,7 +73,7 @@ class CommandBufferStub : public IPC::Channel::Listener,
gfx::PluginWindowHandle window_;
int route_id_;
scoped_ptr<gpu::CommandBufferService> command_buffer_;
- scoped_refptr<gpu::GPUProcessor> processor_;
+ scoped_ptr<gpu::GPUProcessor> processor_;
};
#endif // ENABLE_GPU
diff --git a/chrome/renderer/command_buffer_proxy.cc b/chrome/renderer/command_buffer_proxy.cc
index bd0f3a0..4a624a3 100644
--- a/chrome/renderer/command_buffer_proxy.cc
+++ b/chrome/renderer/command_buffer_proxy.cc
@@ -183,6 +183,10 @@ void CommandBufferProxy::SetParseError(
NOTREACHED();
}
+void CommandBufferProxy::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
+ Send(new GpuCommandBufferMsg_ResizeOffscreenFrameBuffer(route_id_, size));
+}
+
#if defined(OS_MACOSX)
void CommandBufferProxy::SetWindowSize(int32 width, int32 height) {
Send(new GpuCommandBufferMsg_SetWindowSize(route_id_, width, height));
diff --git a/chrome/renderer/command_buffer_proxy.h b/chrome/renderer/command_buffer_proxy.h
index 5d72f2c..e6fce0a 100644
--- a/chrome/renderer/command_buffer_proxy.h
+++ b/chrome/renderer/command_buffer_proxy.h
@@ -15,6 +15,7 @@
#include "base/scoped_ptr.h"
#include "base/shared_memory.h"
#include "base/task.h"
+#include "gfx/size.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_message.h"
@@ -51,6 +52,9 @@ class CommandBufferProxy : public gpu::CommandBuffer,
virtual void SetToken(int32 token);
virtual void SetParseError(gpu::error::Error error);
+ // Asynchronously resizes an offscreen frame buffer.
+ void ResizeOffscreenFrameBuffer(const gfx::Size& size);
+
// Set a task that will be invoked the next time the window becomes invalid
// and needs to be repainted. Takes ownership of task.
void SetNotifyRepaintTask(Task* task) {
diff --git a/chrome/renderer/ggl/ggl.cc b/chrome/renderer/ggl/ggl.cc
index b5c1d9d..2c41126 100644
--- a/chrome/renderer/ggl/ggl.cc
+++ b/chrome/renderer/ggl/ggl.cc
@@ -50,12 +50,21 @@ class GLES2Initializer {
// Manages a GL context.
class Context {
public:
- Context();
+ Context(GpuChannelHost* channel, Context* parent);
~Context();
// Initialize a GGL context that can be used in association with a a GPU
// channel acquired from a RenderWidget or RenderView.
- bool Initialize(GpuChannelHost* channel);
+ bool Initialize(gfx::NativeViewId view, const gfx::Size& size);
+
+ // Asynchronously resizes an offscreen frame buffer.
+ void ResizeOffscreen(const gfx::Size& size);
+
+ // For an offscreen frame buffer context, return the frame buffer ID with
+ // respect to the parent.
+ uint32 parent_texture_id() const {
+ return parent_texture_id_;
+ }
// Destroy all resources associated with the GGL context.
void Destroy();
@@ -73,6 +82,8 @@ class Context {
private:
scoped_refptr<GpuChannelHost> channel_;
+ Context* parent_;
+ uint32 parent_texture_id_;
CommandBufferProxy* command_buffer_;
gpu::gles2::GLES2CmdHelper* gles2_helper_;
int32 transfer_buffer_id_;
@@ -81,31 +92,46 @@ class Context {
DISALLOW_COPY_AND_ASSIGN(Context);
};
-Context::Context()
- : channel_(NULL),
+Context::Context(GpuChannelHost* channel, Context* parent)
+ : channel_(channel),
+ parent_(parent),
+ parent_texture_id_(0),
command_buffer_(NULL),
gles2_helper_(NULL),
transfer_buffer_id_(0),
gles2_implementation_(NULL) {
+ DCHECK(channel);
}
Context::~Context() {
Destroy();
}
-bool Context::Initialize(GpuChannelHost* channel) {
- DCHECK(channel);
+bool Context::Initialize(gfx::NativeViewId view, const gfx::Size& size) {
+ DCHECK(size.width() >= 0 && size.height() >= 0);
- if (!channel->ready())
+ if (!channel_->ready())
return false;
- channel_ = channel;
-
// Ensure the gles2 library is initialized first in a thread safe way.
Singleton<GLES2Initializer>::get();
+ // Allocate a frame buffer ID with respect to the parent.
+ if (parent_) {
+ parent_->gles2_implementation_->MakeIds(1, &parent_texture_id_);
+ }
+
// Create a proxy to a command buffer in the GPU process.
- command_buffer_ = channel_->CreateCommandBuffer();
+ if (view) {
+ command_buffer_ = channel_->CreateViewCommandBuffer(view);
+ } else {
+ CommandBufferProxy* parent_command_buffer =
+ parent_ ? parent_->command_buffer_ : NULL;
+ command_buffer_ = channel_->CreateOffscreenCommandBuffer(
+ parent_command_buffer,
+ size,
+ parent_texture_id_);
+ }
if (!command_buffer_) {
Destroy();
return false;
@@ -151,7 +177,15 @@ bool Context::Initialize(GpuChannelHost* channel) {
return true;
}
+void Context::ResizeOffscreen(const gfx::Size& size) {
+ DCHECK(size.width() > 0 && size.height() > 0);
+ command_buffer_->ResizeOffscreenFrameBuffer(size);
+}
+
void Context::Destroy() {
+ if (parent_ && parent_texture_id_ != 0)
+ parent_->gles2_implementation_->FreeIds(1, &parent_texture_id_);
+
delete gles2_implementation_;
gles2_implementation_ = NULL;
@@ -213,10 +247,10 @@ Error Context::GetError() {
#endif // ENABLE_GPU
-Context* CreateContext(GpuChannelHost* channel) {
+Context* CreateViewContext(GpuChannelHost* channel, gfx::NativeViewId view) {
#if defined(ENABLE_GPU)
- scoped_ptr<Context> context(new Context);
- if (!context->Initialize(channel))
+ scoped_ptr<Context> context(new Context(channel, NULL));
+ if (!context->Initialize(view, gfx::Size()))
return NULL;
return context.release();
@@ -225,6 +259,34 @@ Context* CreateContext(GpuChannelHost* channel) {
#endif
}
+Context* CreateOffscreenContext(GpuChannelHost* channel,
+ Context* parent,
+ const gfx::Size& size) {
+#if defined(ENABLE_GPU)
+ scoped_ptr<Context> context(new Context(channel, parent));
+ if (!context->Initialize(NULL, size))
+ return NULL;
+
+ return context.release();
+#else
+ return NULL;
+#endif
+}
+
+void ResizeOffscreenContext(Context* context, const gfx::Size& size) {
+#if defined(ENABLE_GPU)
+ context->ResizeOffscreen(size);
+#endif
+}
+
+uint32 GetParentTextureId(Context* context) {
+#if defined(ENABLE_GPU)
+ return context->parent_texture_id();
+#else
+ return 0;
+#endif
+}
+
bool MakeCurrent(Context* context) {
#if defined(ENABLE_GPU)
return Context::MakeCurrent(context);
diff --git a/chrome/renderer/ggl/ggl.h b/chrome/renderer/ggl/ggl.h
index 26607ec..e5c661f 100644
--- a/chrome/renderer/ggl/ggl.h
+++ b/chrome/renderer/ggl/ggl.h
@@ -10,6 +10,9 @@
#ifndef CHROME_RENDERER_GGL_GGL_H_
#define CHROME_RENDERER_GGL_GGL_H_
+#include "gfx/native_widget_types.h"
+#include "gfx/size.h"
+
class GpuChannelHost;
namespace ggl {
@@ -32,8 +35,30 @@ bool Initialize();
// have completed.
bool Terminate();
-// Create A GGL context for an offscreen 1 x 1 pbuffer.
-Context* CreateContext(GpuChannelHost* channel);
+// Create a GGL context that renders directly to a view.
+Context* CreateViewContext(GpuChannelHost* channel, gfx::NativeViewId view);
+
+// Create a GGL context that renders to an offscreen frame buffer. If parent is
+// not NULL, that context can access a copy of the created
+// context's frame buffer that is updated every time SwapBuffers is called. It
+// is not as general as shared contexts in other implementations of OpenGL. If
+// parent is not NULL, it must be used on the same thread as the parent. A child
+// context may not outlive its parent.
+Context* CreateOffscreenContext(GpuChannelHost* channel,
+ Context* parent,
+ const gfx::Size& size);
+
+// Resize an offscreen frame buffer. The resize occurs on the next call to
+// SwapBuffers. This is to avoid waiting until all pending GL calls have been
+// executed by the GPU process. Everything rendered up to the call to
+// SwapBuffers will be lost. A lost context will be reported if the resize
+// fails.
+void ResizeOffscreenContext(Context* context, const gfx::Size& size);
+
+// For an offscreen frame buffer context, return the texture ID with
+// respect to the parent context. Returns zero if context does not have a
+// parent.
+uint32 GetParentTextureId(Context* context);
// Set the current GGL context for the calling thread.
bool MakeCurrent(Context* context);
@@ -41,7 +66,10 @@ bool MakeCurrent(Context* context);
// Get the calling thread's current GGL context.
Context* GetCurrentContext();
-// Display everything that has been rendered since the last call.
+// For a view context, display everything that has been rendered since the
+// last call. For an offscreen context, resolve everything that has been
+// rendered since the last call to a copy that can be accessed by the parent
+// context.
bool SwapBuffers();
// Destroy the given GGL context.
diff --git a/chrome/renderer/gpu_channel_host.cc b/chrome/renderer/gpu_channel_host.cc
index 8e48b85..8d2cdd9 100644
--- a/chrome/renderer/gpu_channel_host.cc
+++ b/chrome/renderer/gpu_channel_host.cc
@@ -64,14 +64,43 @@ bool GpuChannelHost::Send(IPC::Message* message) {
return channel_->Send(message);
}
-CommandBufferProxy* GpuChannelHost::CreateCommandBuffer() {
+CommandBufferProxy* GpuChannelHost::CreateViewCommandBuffer(
+ gfx::NativeViewId view) {
#if defined(ENABLE_GPU)
// An error occurred. Need to get the host again to reinitialize it.
if (!channel_.get())
return NULL;
int32 route_id;
- if (!Send(new GpuChannelMsg_CreateCommandBuffer(&route_id)) &&
+ if (!Send(new GpuChannelMsg_CreateViewCommandBuffer(view, &route_id)) &&
+ route_id != MSG_ROUTING_NONE) {
+ return NULL;
+ }
+
+ CommandBufferProxy* command_buffer = new CommandBufferProxy(this, route_id);
+ router_.AddRoute(route_id, command_buffer);
+ proxies_[route_id] = command_buffer;
+ return command_buffer;
+#else
+ return NULL;
+#endif
+}
+
+CommandBufferProxy* GpuChannelHost::CreateOffscreenCommandBuffer(
+ CommandBufferProxy* parent,
+ const gfx::Size& size,
+ uint32 parent_texture_id) {
+#if defined(ENABLE_GPU)
+ // An error occurred. Need to get the host again to reinitialize it.
+ if (!channel_.get())
+ return NULL;
+
+ int32 parent_route_id = parent ? parent->route_id() : 0;
+ int32 route_id;
+ if (!Send(new GpuChannelMsg_CreateOffscreenCommandBuffer(parent_route_id,
+ size,
+ parent_texture_id,
+ &route_id)) &&
route_id != MSG_ROUTING_NONE) {
return NULL;
}
@@ -99,3 +128,4 @@ void GpuChannelHost::DestroyCommandBuffer(CommandBufferProxy* command_buffer) {
delete command_buffer;
#endif
}
+
diff --git a/chrome/renderer/gpu_channel_host.h b/chrome/renderer/gpu_channel_host.h
index 00a6129..4b982bf 100644
--- a/chrome/renderer/gpu_channel_host.h
+++ b/chrome/renderer/gpu_channel_host.h
@@ -9,6 +9,8 @@
#include "base/hash_tables.h"
#include "chrome/common/message_router.h"
+#include "gfx/native_widget_types.h"
+#include "gfx/size.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sync_channel.h"
@@ -52,7 +54,13 @@ class GpuChannelHost : public IPC::Channel::Listener,
virtual bool Send(IPC::Message* msg);
// Create and connect to a command buffer in the GPU process.
- CommandBufferProxy* CreateCommandBuffer();
+ CommandBufferProxy* CreateViewCommandBuffer(gfx::NativeViewId view);
+
+ // Create and connect to a command buffer in the GPU process.
+ CommandBufferProxy* CreateOffscreenCommandBuffer(CommandBufferProxy* parent,
+ const gfx::Size& size,
+ uint32 parent_texture_id);
+
// Destroy a command buffer created by this channel.
void DestroyCommandBuffer(CommandBufferProxy* command_buffer);
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index ab97f2a..4fb0971 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -90,6 +90,10 @@
#include "chrome/app/breakpad_mac.h"
#endif
+#if defined(OS_POSIX)
+#include "ipc/ipc_channel_posix.h"
+#endif
+
using WebKit::WebCache;
using WebKit::WebCrossOriginPreflightResultCache;
using WebKit::WebFontCache;
@@ -565,6 +569,7 @@ void RenderThread::OnControlMessageReceived(const IPC::Message& msg) {
OnSpellCheckWordAdded)
IPC_MESSAGE_HANDLER(ViewMsg_SpellChecker_EnableAutoSpellCorrect,
OnSpellCheckEnableAutoSpellCorrect)
+ IPC_MESSAGE_HANDLER(ViewMsg_GpuChannelEstablished, OnGpuChannelEstablished)
IPC_END_MESSAGE_MAP()
}
@@ -680,6 +685,34 @@ void RenderThread::UpdateActiveExtensions() {
child_process_logging::SetActiveExtensions(active_extensions);
}
+void RenderThread::EstablishGpuChannel() {
+ if (gpu_channel_.get()) {
+ // Do nothing if we are already establishing GPU channel.
+ if (gpu_channel_->state() == GpuChannelHost::UNCONNECTED)
+ return;
+
+ // Recreate the channel if it has been lost.
+ if (gpu_channel_->state() == GpuChannelHost::LOST)
+ gpu_channel_ = NULL;
+ }
+
+ if (!gpu_channel_.get())
+ gpu_channel_ = new GpuChannelHost;
+
+ // Ask the browser for the channel name.
+ Send(new ViewHostMsg_EstablishGpuChannel());
+}
+
+GpuChannelHost* RenderThread::GetGpuChannel() {
+ if (!gpu_channel_.get())
+ return NULL;
+
+ if (gpu_channel_->state() != GpuChannelHost::CONNECTED)
+ return NULL;
+
+ return gpu_channel_.get();
+}
+
static void* CreateHistogram(
const char *name, int min, int max, size_t buckets) {
if (min <= 0)
@@ -940,3 +973,20 @@ void RenderThread::OnSpellCheckEnableAutoSpellCorrect(bool enable) {
void RenderThread::OnSetIsIncognitoProcess(bool is_incognito_process) {
is_incognito_process_ = is_incognito_process;
}
+
+void RenderThread::OnGpuChannelEstablished(
+ const IPC::ChannelHandle& channel_handle) {
+#if defined(OS_POSIX)
+ // If we received a ChannelHandle, register it now.
+ if (channel_handle.socket.fd >= 0)
+ IPC::AddChannelSocket(channel_handle.name, channel_handle.socket.fd);
+#endif
+
+ if (channel_handle.name.size() != 0) {
+ // Connect to the GPU process if a channel name was received.
+ gpu_channel_->Connect(channel_handle.name);
+ } else {
+ // Otherwise cancel the connection.
+ gpu_channel_ = NULL;
+ }
+}
diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h
index fea7e41..3caed00 100644
--- a/chrome/renderer/render_thread.h
+++ b/chrome/renderer/render_thread.h
@@ -18,9 +18,11 @@
#include "chrome/common/child_thread.h"
#include "chrome/common/css_colors.h"
#include "chrome/common/dom_storage_common.h"
+#include "chrome/renderer/gpu_channel_host.h"
#include "chrome/renderer/renderer_histogram_snapshots.h"
#include "chrome/renderer/visitedlink_slave.h"
#include "gfx/native_widget_types.h"
+#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_platform_file.h"
class AppCacheDispatcher;
@@ -165,6 +167,15 @@ class RenderThread : public RenderThreadBase,
// Update the list of active extensions that will be reported when we crash.
void UpdateActiveExtensions();
+ // Asynchronously establish a channel to the GPU plugin if not previously
+ // established or if it has been lost (for example if the GPU plugin crashed).
+ // Use GetGpuChannel() to determine when the channel is ready for use.
+ void EstablishGpuChannel();
+
+ // Get the GPU channel. Returns NULL if the channel is not established or
+ // has been lost.
+ GpuChannelHost* GetGpuChannel();
+
private:
virtual void OnControlMessageReceived(const IPC::Message& msg);
@@ -220,6 +231,8 @@ class RenderThread : public RenderThreadBase,
void OnSpellCheckWordAdded(const std::string& word);
void OnSpellCheckEnableAutoSpellCorrect(bool enable);
+ void OnGpuChannelEstablished(const IPC::ChannelHandle& channel_handle);
+
// Gather usage statistics from the in-memory cache and inform our host.
// These functions should be call periodically so that the host can make
// decisions about how to allocation resources using current information.
@@ -288,6 +301,9 @@ class RenderThread : public RenderThreadBase,
// not idle, to ensure that IdleHandle gets called eventually.
base::RepeatingTimer<RenderThread> forced_idle_timer_;
+ // The channel from the renderer process to the GPU process.
+ scoped_refptr<GpuChannelHost> gpu_channel_;
+
DISALLOW_COPY_AND_ASSIGN(RenderThread);
};
diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc
index def6e47..50af08f 100644
--- a/chrome/renderer/render_widget.cc
+++ b/chrome/renderer/render_widget.cc
@@ -150,7 +150,6 @@ IPC_DEFINE_MESSAGE_MAP(RenderWidget)
IPC_MESSAGE_HANDLER(ViewMsg_ImeSetComposition, OnImeSetComposition)
IPC_MESSAGE_HANDLER(ViewMsg_Repaint, OnMsgRepaint)
IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection)
- IPC_MESSAGE_HANDLER(ViewMsg_GpuChannelEstablished, OnGpuChannelEstablished)
IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck)
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP()
@@ -732,23 +731,6 @@ void RenderWidget::OnSetTextDirection(WebTextDirection direction) {
webwidget_->setTextDirection(direction);
}
-void RenderWidget::OnGpuChannelEstablished(
- const IPC::ChannelHandle& channel_handle) {
-#if defined(OS_POSIX)
- // If we received a ChannelHandle, register it now.
- if (channel_handle.socket.fd >= 0)
- IPC::AddChannelSocket(channel_handle.name, channel_handle.socket.fd);
-#endif
-
- if (channel_handle.name.size() != 0) {
- // Connect to the GPU process if a channel name was received.
- gpu_channel_->Connect(channel_handle.name);
- } else {
- // Otherwise cancel the connection.
- gpu_channel_ = NULL;
- }
-}
-
void RenderWidget::SetHidden(bool hidden) {
if (is_hidden_ == hidden)
return;
@@ -892,31 +874,3 @@ void RenderWidget::CleanupWindowInPluginMoves(gfx::PluginWindowHandle window) {
}
}
-void RenderWidget::EstablishGpuChannel() {
- if (gpu_channel_.get()) {
- // Do nothing if we are already establishing GPU channel.
- if (gpu_channel_->state() == GpuChannelHost::UNCONNECTED)
- return;
-
- // Recreate the channel if it has been lost.
- if (gpu_channel_->state() == GpuChannelHost::LOST)
- gpu_channel_ = NULL;
- }
-
- if (!gpu_channel_.get())
- gpu_channel_ = new GpuChannelHost;
-
- // Ask the browser for the channel name.
- CHECK(Send(new ViewHostMsg_EstablishGpuChannel(routing_id_)));
-}
-
-GpuChannelHost* RenderWidget::GetGpuChannel() {
- if (!gpu_channel_.get())
- return NULL;
-
- if (gpu_channel_->state() != GpuChannelHost::CONNECTED)
- return NULL;
-
- return gpu_channel_.get();
-}
-
diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h
index 4759e30..4781790 100644
--- a/chrome/renderer/render_widget.h
+++ b/chrome/renderer/render_widget.h
@@ -10,7 +10,6 @@
#include "base/basictypes.h"
#include "base/ref_counted.h"
#include "base/shared_memory.h"
-#include "chrome/renderer/gpu_channel_host.h"
#include "chrome/renderer/paint_aggregator.h"
#include "chrome/renderer/render_process.h"
#include "gfx/native_widget_types.h"
@@ -18,7 +17,6 @@
#include "gfx/rect.h"
#include "gfx/size.h"
#include "ipc/ipc_channel.h"
-#include "ipc/ipc_channel_handle.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/WebKit/WebKit/chromium/public/WebCompositionCommand.h"
@@ -107,15 +105,6 @@ class RenderWidget : public IPC::Channel::Listener,
// Close the underlying WebWidget.
virtual void Close();
- // Asynchronously establish a channel to the GPU plugin if not previously
- // established or if it has been lost (for example if the GPU plugin crashed).
- // Use GetGpuChannel() to determine when the channel is ready for use.
- void EstablishGpuChannel();
-
- // Get the GPU channel. Returns NULL if the channel is not established or
- // has been lost.
- GpuChannelHost* GetGpuChannel();
-
protected:
// Friend RefCounted so that the dtor can be non-public. Using this class
// without ref-counting is an error.
@@ -171,7 +160,6 @@ class RenderWidget : public IPC::Channel::Listener,
const string16& ime_string);
void OnMsgRepaint(const gfx::Size& size_to_paint);
void OnSetTextDirection(WebKit::WebTextDirection direction);
- void OnGpuChannelEstablished(const IPC::ChannelHandle& channel_handle);
// Override point to notify derived classes that a paint has happened.
// DidInitiatePaint happens when we've generated a new bitmap and sent it to
@@ -332,9 +320,6 @@ class RenderWidget : public IPC::Channel::Listener,
// Indicates if the next sequence of Char events should be suppressed or not.
bool suppress_next_char_events_;
- // The channel from the renderer process to the GPU process.
- scoped_refptr<GpuChannelHost> gpu_channel_;
-
DISALLOW_COPY_AND_ASSIGN(RenderWidget);
};