Index: chrome/gpu/gpu_command_buffer_stub.cc |
=================================================================== |
--- chrome/gpu/gpu_command_buffer_stub.cc (revision 67491) |
+++ chrome/gpu/gpu_command_buffer_stub.cc (working copy) |
@@ -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 @@ |
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 @@ |
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 @@ |
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 @@ |
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 @@ |
} |
#endif // defined(OS_MACOSX) |
+void GpuCommandBufferStub::ResizeCallback(gfx::Size size) { |
+ if (handle_ == gfx::kNullPluginWindow) |
+ return; |
+ |
#if defined(OS_LINUX) |
-void GpuCommandBufferStub::ResizeCallback(gfx::Size size) { |
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 |