summaryrefslogtreecommitdiffstats
path: root/chrome/gpu
diff options
context:
space:
mode:
authornduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-27 19:39:42 +0000
committernduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-27 19:39:42 +0000
commit50bd645cfa2824a22f98096cb6a66bbd7cf757f4 (patch)
tree3cae036733b722b0ec731363179c5fdec5f7e137 /chrome/gpu
parent1bead0713628b2410ffd7ba49700c5901059d07b (diff)
downloadchromium_src-50bd645cfa2824a22f98096cb6a66bbd7cf757f4.zip
chromium_src-50bd645cfa2824a22f98096cb6a66bbd7cf757f4.tar.gz
chromium_src-50bd645cfa2824a22f98096cb6a66bbd7cf757f4.tar.bz2
When accelerated compositing is enabled, we create a plugin-like pair of windows,
CompositorHostWindow and CompositorWindow inside the RenderWidgetHostView. The host-side HWND is used to position the compositor output relative to plugins; the GPU process creates the compositor window as a child of the CompositorHostWindow. Once we land webkit bugfix 49396, ANGLE issue 3038042, Chromium issue 4671003, this will fix bugs 54301 and 61516 for windows. BUG=none TEST=none Review URL: http://codereview.chromium.org/4815001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67495 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/gpu')
-rw-r--r--chrome/gpu/gpu_channel.cc4
-rw-r--r--chrome/gpu/gpu_command_buffer_stub.cc153
-rw-r--r--chrome/gpu/gpu_command_buffer_stub.h10
3 files changed, 159 insertions, 8 deletions
diff --git a/chrome/gpu/gpu_channel.cc b/chrome/gpu/gpu_channel.cc
index 7cd06d2..6d97a3d 100644
--- a/chrome/gpu/gpu_channel.cc
+++ b/chrome/gpu/gpu_channel.cc
@@ -133,6 +133,10 @@ void GpuChannel::OnCreateViewCommandBuffer(
GetProp(view, chrome::kChromiumRendererIdProperty));
if (view_renderer_id != renderer_id_)
return;
+
+ // Note, we don't actually render into the view HWND. Instead, inside
+ // the GpuCommandBufferStub, we will create a child window within the view
+ // HWND into which we will render.
handle = view;
#elif defined(OS_LINUX)
ChildThread* gpu_thread = ChildThread::current();
diff --git a/chrome/gpu/gpu_command_buffer_stub.cc b/chrome/gpu/gpu_command_buffer_stub.cc
index 1872246..3c87c99 100644
--- a/chrome/gpu/gpu_command_buffer_stub.cc
+++ b/chrome/gpu/gpu_command_buffer_stub.cc
@@ -14,6 +14,10 @@
using gpu::Buffer;
+#if defined(OS_WIN)
+#define kCompositorWindowOwner L"CompositorWindowOwner"
+#endif
+
GpuCommandBufferStub::GpuCommandBufferStub(
GpuChannel* channel,
gfx::PluginWindowHandle handle,
@@ -38,10 +42,124 @@ GpuCommandBufferStub::GpuCommandBufferStub(
render_view_id_(render_view_id) {
}
+#if defined(OS_WIN)
+static LRESULT CALLBACK CompositorWindowProc(
+ HWND hwnd,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam) {
+ switch (message) {
+ case WM_ERASEBKGND:
+ return 0;
+ case WM_DESTROY:
+ RemoveProp(hwnd, kCompositorWindowOwner);
+ return 0;
+ case WM_PAINT: {
+ PAINTSTRUCT paint;
+ HDC dc = BeginPaint(hwnd, &paint);
+ if (dc) {
+ HANDLE h = GetProp(hwnd, kCompositorWindowOwner);
+ if (h) {
+ GpuCommandBufferStub* stub =
+ reinterpret_cast<GpuCommandBufferStub*>(h);
+ stub->OnCompositorWindowPainted();
+ }
+ EndPaint(hwnd, &paint);
+ }
+ break;
+ }
+ default:
+ return DefWindowProc(hwnd, message, wparam, lparam);
+ }
+ return 0;
+}
+
+bool GpuCommandBufferStub::CreateCompositorWindow() {
+ DCHECK(handle_ != gfx::kNullPluginWindow);
+
+ // Ask the browser to create the the host window.
+ ChildThread* gpu_thread = ChildThread::current();
+ gfx::PluginWindowHandle host_window_id = gfx::kNullPluginWindow;
+ gpu_thread->Send(new GpuHostMsg_CreateCompositorHostWindow(
+ renderer_id_,
+ render_view_id_,
+ &host_window_id));
+ if (host_window_id == gfx::kNullPluginWindow)
+ return false;
+ HWND host_window = static_cast<HWND>(host_window_id);
+
+ // Create the compositor window itself.
+ DCHECK(host_window);
+ static ATOM window_class = 0;
+ if (!window_class) {
+ WNDCLASSEX wcex;
+ wcex.cbSize = sizeof(wcex);
+ wcex.style = 0;
+ wcex.lpfnWndProc = CompositorWindowProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = GetModuleHandle(NULL);
+ wcex.hIcon = 0;
+ wcex.hCursor = 0;
+ wcex.hbrBackground = NULL;
+ wcex.lpszMenuName = 0;
+ wcex.lpszClassName = L"CompositorWindowClass";
+ wcex.hIconSm = 0;
+ window_class = RegisterClassEx(&wcex);
+ DCHECK(window_class);
+ }
+
+ HWND compositor_window = CreateWindowEx(
+ WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
+ MAKEINTATOM(window_class),
+ 0,
+ WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DISABLED,
+ 0, 0,
+ 0, 0,
+ host_window,
+ 0,
+ GetModuleHandle(NULL),
+ 0);
+ if (!compositor_window) {
+ compositor_window_ = gfx::kNullPluginWindow;
+ return false;
+ }
+ SetProp(compositor_window, kCompositorWindowOwner,
+ reinterpret_cast<HANDLE>(this));
+
+ RECT parent_rect;
+ GetClientRect(host_window, &parent_rect);
+
+ UINT flags = SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOZORDER |
+ SWP_NOACTIVATE | SWP_DEFERERASE | SWP_SHOWWINDOW;
+ SetWindowPos(compositor_window,
+ NULL,
+ 0, 0,
+ parent_rect.right - parent_rect.left,
+ parent_rect.bottom - parent_rect.top,
+ flags);
+ compositor_window_ = static_cast<gfx::PluginWindowHandle>(compositor_window);
+ return true;
+}
+
+void GpuCommandBufferStub::OnCompositorWindowPainted() {
+ ChildThread* gpu_thread = ChildThread::current();
+ gpu_thread->Send(new GpuHostMsg_ScheduleComposite(
+ renderer_id_, render_view_id_));
+}
+#endif // defined(OS_WIN)
+
+
GpuCommandBufferStub::~GpuCommandBufferStub() {
if (processor_.get()) {
processor_->Destroy();
}
+#if defined(OS_WIN)
+ if (compositor_window_) {
+ DestroyWindow(static_cast<HWND>(compositor_window_));
+ compositor_window_ = NULL;
+ }
+#endif
}
void GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
@@ -79,6 +197,21 @@ void GpuCommandBufferStub::OnInitialize(
command_buffer_.reset(new gpu::CommandBufferService);
+ // Create the child window, if needed
+#if defined(OS_WIN)
+ gfx::PluginWindowHandle output_window_handle;
+ if (handle_) {
+ if (!CreateCompositorWindow()) {
+ return;
+ }
+ output_window_handle = compositor_window_;
+ } else {
+ output_window_handle = handle_;
+ }
+#else
+ gfx::PluginWindowHandle output_window_handle = handle_;
+#endif
+
// Initialize the CommandBufferService and GPUProcessor.
if (command_buffer_->Initialize(size)) {
Buffer buffer = command_buffer_->GetRingBuffer();
@@ -87,7 +220,7 @@ void GpuCommandBufferStub::OnInitialize(
parent_ ? parent_->processor_.get() : NULL;
processor_.reset(new gpu::GPUProcessor(command_buffer_.get(), NULL));
if (processor_->Initialize(
- handle_,
+ output_window_handle,
initial_size_,
allowed_extensions_.c_str(),
requested_attribs_,
@@ -113,10 +246,10 @@ void GpuCommandBufferStub::OnInitialize(
NewCallback(this,
&GpuCommandBufferStub::SwapBuffersCallback));
}
-#elif defined(OS_LINUX)
+#elif defined(OS_LINUX) || defined(OS_WIN)
if (handle_) {
- // Set up a pathway to allow the Gpu process to ask the browser
- // for a window resize.
+ // Set up a pathway for resizing the output window at the right time
+ // relative to other GL commands.
processor_->SetResizeCallback(
NewCallback(this,
&GpuCommandBufferStub::ResizeCallback));
@@ -227,13 +360,21 @@ void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped(
}
#endif // defined(OS_MACOSX)
-#if defined(OS_LINUX)
void GpuCommandBufferStub::ResizeCallback(gfx::Size size) {
+ if (handle_ == gfx::kNullPluginWindow)
+ return;
+
+#if defined(OS_LINUX)
ChildThread* gpu_thread = ChildThread::current();
bool result = false;
gpu_thread->Send(
new GpuHostMsg_ResizeXID(handle_, size, &result));
+#elif defined(OS_WIN)
+ HWND hwnd = static_cast<HWND>(compositor_window_);
+ UINT swp_flags = SWP_NOSENDCHANGING | SWP_NOOWNERZORDER | SWP_NOCOPYBITS |
+ SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE;
+ SetWindowPos(hwnd, NULL, 0, 0, size.width(), size.height(), swp_flags);
+#endif
}
-#endif // defined(OS_LINUX)
#endif // ENABLE_GPU
diff --git a/chrome/gpu/gpu_command_buffer_stub.h b/chrome/gpu/gpu_command_buffer_stub.h
index ef57715..6d888aa 100644
--- a/chrome/gpu/gpu_command_buffer_stub.h
+++ b/chrome/gpu/gpu_command_buffer_stub.h
@@ -51,6 +51,11 @@ class GpuCommandBufferStub
int32 route_id() const { return route_id_; }
+#if defined(OS_WIN)
+ // Called only by the compositor window's window proc
+ void OnCompositorWindowPainted();
+#endif
+
#if defined(OS_MACOSX)
// Called only by the GpuChannel.
void AcceleratedSurfaceBuffersSwapped(uint64 swap_buffers_count);
@@ -75,11 +80,12 @@ class GpuCommandBufferStub
#if defined(OS_MACOSX)
void OnSetWindowSize(const gfx::Size& size);
void SwapBuffersCallback();
+#elif defined(OS_WIN)
+ bool CreateCompositorWindow();
+ HWND compositor_window_;
#endif
-#if defined(OS_LINUX)
void ResizeCallback(gfx::Size size);
-#endif
// The lifetime of objects of this class is managed by a GpuChannel. The
// GpuChannels destroy all the GpuCommandBufferStubs that they own when they