summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--chrome/browser/gpu_process_host.cc52
-rw-r--r--chrome/browser/gpu_process_host.h4
-rw-r--r--chrome/browser/gpu_process_host_ui_shim.cc14
-rw-r--r--chrome/browser/gpu_process_host_ui_shim.h2
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc30
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h8
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view.h6
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.cc2
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm13
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_views.cc5
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.cc161
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.h8
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.cc11
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.h4
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc7
-rw-r--r--chrome/common/gpu_messages_internal.h10
-rw-r--r--chrome/common/render_messages_internal.h8
-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
-rw-r--r--chrome/renderer/render_widget.cc5
21 files changed, 469 insertions, 48 deletions
diff --git a/chrome/browser/gpu_process_host.cc b/chrome/browser/gpu_process_host.cc
index afa904c..c321f97 100644
--- a/chrome/browser/gpu_process_host.cc
+++ b/chrome/browser/gpu_process_host.cc
@@ -177,6 +177,9 @@ void GpuProcessHost::OnControlMessageReceived(const IPC::Message& message) {
OnAcceleratedSurfaceSetIOSurface)
IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
OnAcceleratedSurfaceBuffersSwapped)
+#elif defined(OS_WIN)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_CreateCompositorHostWindow,
+ OnCreateCompositorHostWindow)
#endif
// If the IO thread does not handle the message then automatically route it
// to the UI thread. The UI thread will report an error if it does not
@@ -305,8 +308,8 @@ namespace {
class BuffersSwappedDispatcher : public Task {
public:
BuffersSwappedDispatcher(
- int32 renderer_id,
- int32 render_view_id,
+ int renderer_id,
+ int render_view_id,
gfx::PluginWindowHandle window,
uint64 surface_id,
int32 route_id,
@@ -338,8 +341,8 @@ class BuffersSwappedDispatcher : public Task {
}
private:
- int32 renderer_id_;
- int32 render_view_id_;
+ int renderer_id_;
+ int render_view_id_;
gfx::PluginWindowHandle window_;
uint64 surface_id_;
int32 route_id_;
@@ -366,6 +369,47 @@ void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped(
params.route_id,
params.swap_buffers_count));
}
+
+#elif defined(OS_WIN)
+
+namespace {
+
+void SendDelayedReply(IPC::Message* reply_msg) {
+ GpuProcessHost::Get()->Send(reply_msg);
+}
+
+void CreateCompositorHostWindowDispatcher(
+ int renderer_id,
+ int render_view_id,
+ IPC::Message* reply_msg) {
+ RenderViewHost* host = RenderViewHost::FromID(renderer_id,
+ render_view_id);
+ if (!host) {
+ return;
+ }
+
+ RenderWidgetHostView* view = host->view();
+ gfx::PluginWindowHandle id = view->CreateCompositorHostWindow();
+
+
+ GpuHostMsg_CreateCompositorHostWindow::WriteReplyParams(reply_msg, id);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableFunction(&SendDelayedReply, reply_msg));
+}
+
+} // namespace
+
+void GpuProcessHost::OnCreateCompositorHostWindow(
+ int renderer_id,
+ int render_view_id,
+ IPC::Message* reply_message) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableFunction(&CreateCompositorHostWindowDispatcher,
+ renderer_id, render_view_id, reply_message));
+}
+
#endif
void GpuProcessHost::SendEstablishChannelReply(
diff --git a/chrome/browser/gpu_process_host.h b/chrome/browser/gpu_process_host.h
index 4b40a25..8219355 100644
--- a/chrome/browser/gpu_process_host.h
+++ b/chrome/browser/gpu_process_host.h
@@ -93,6 +93,10 @@ class GpuProcessHost : public BrowserChildProcessHost, public NonThreadSafe {
const GpuHostMsg_AcceleratedSurfaceSetIOSurface_Params& params);
void OnAcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params);
+#elif defined(OS_WIN)
+ void OnCreateCompositorHostWindow(int renderer_id,
+ int render_view_id,
+ IPC::Message* reply_message);
#endif
// Sends the response for establish channel request to the renderer.
diff --git a/chrome/browser/gpu_process_host_ui_shim.cc b/chrome/browser/gpu_process_host_ui_shim.cc
index 2e3a531..d8257a8 100644
--- a/chrome/browser/gpu_process_host_ui_shim.cc
+++ b/chrome/browser/gpu_process_host_ui_shim.cc
@@ -6,6 +6,7 @@
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/gpu_process_host.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/common/child_process_logging.h"
#include "chrome/common/gpu_messages.h"
@@ -105,6 +106,15 @@ void GpuProcessHostUIShim::OnGraphicsInfoCollected(const GPUInfo& gpu_info) {
child_process_logging::SetGpuInfo(gpu_info);
}
+void GpuProcessHostUIShim::OnScheduleComposite(int renderer_id,
+ int render_view_id) {
+ RenderViewHost* host = RenderViewHost::FromID(renderer_id,
+ render_view_id);
+ if (!host) {
+ return;
+ }
+ host->ScheduleComposite();
+}
void GpuProcessHostUIShim::OnControlMessageReceived(
const IPC::Message& message) {
DCHECK(CalledOnValidThread());
@@ -112,6 +122,10 @@ void GpuProcessHostUIShim::OnControlMessageReceived(
IPC_BEGIN_MESSAGE_MAP(GpuProcessHostUIShim, message)
IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected,
OnGraphicsInfoCollected)
+#if defined(OS_WIN)
+ IPC_MESSAGE_HANDLER(GpuHostMsg_ScheduleComposite,
+ OnScheduleComposite);
+#endif
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP()
}
diff --git a/chrome/browser/gpu_process_host_ui_shim.h b/chrome/browser/gpu_process_host_ui_shim.h
index d77c783..eda33d2 100644
--- a/chrome/browser/gpu_process_host_ui_shim.h
+++ b/chrome/browser/gpu_process_host_ui_shim.h
@@ -62,7 +62,7 @@ class GpuProcessHostUIShim : public IPC::Channel::Sender,
// Message handlers.
void OnGraphicsInfoCollected(const GPUInfo& gpu_info);
-
+ void OnScheduleComposite(int32 renderer_id, int32 render_view_id);
void OnControlMessageReceived(const IPC::Message& message);
int last_routing_id_;
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index 4482bbd..caf7d14 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -77,7 +77,7 @@ RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process,
routing_id_(routing_id),
is_loading_(false),
is_hidden_(false),
- is_gpu_rendering_active_(false),
+ is_accelerated_compositing_active_(false),
repaint_ack_pending_(false),
resize_ack_pending_(false),
mouse_move_pending_(false),
@@ -157,8 +157,8 @@ void RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) {
OnMsgImeUpdateTextInputState)
IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition,
OnMsgImeCancelComposition)
- IPC_MESSAGE_HANDLER(ViewHostMsg_GpuRenderingActivated,
- OnMsgGpuRenderingActivated)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DidActivateAcceleratedCompositing,
+ OnMsgDidActivateAcceleratedCompositing)
#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetScreenInfo, OnMsgGetScreenInfo)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetWindowRect, OnMsgGetWindowRect)
@@ -232,7 +232,7 @@ void RenderWidgetHost::WasRestored() {
// the backing store exists.
bool needs_repainting;
if (needs_repainting_on_restore_ || !backing_store ||
- is_gpu_rendering_active()) {
+ is_accelerated_compositing_active()) {
needs_repainting = true;
needs_repainting_on_restore_ = false;
} else {
@@ -402,8 +402,9 @@ void RenderWidgetHost::DonePaintingToBackingStore() {
}
void RenderWidgetHost::ScheduleComposite() {
- DCHECK(!is_hidden_ || !is_gpu_rendering_active_) <<
- "ScheduleCompositeAndSync called while hidden!";
+ if (is_hidden_ || !is_accelerated_compositing_active_) {
+ return;
+ }
// Send out a request to the renderer to paint the view if required.
if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
@@ -658,7 +659,7 @@ void RenderWidgetHost::RendererExited() {
current_size_.SetSize(0, 0);
current_reserved_rect_.SetRect(0, 0, 0, 0);
is_hidden_ = false;
- is_gpu_rendering_active_ = false;
+ is_accelerated_compositing_active_ = false;
if (view_) {
view_->RenderViewGone();
@@ -832,7 +833,7 @@ void RenderWidgetHost::OnMsgUpdateRect(
DCHECK(!params.bitmap_rect.IsEmpty());
DCHECK(!params.view_size.IsEmpty());
- if (!is_gpu_rendering_active_) {
+ if (!is_accelerated_compositing_active_) {
const size_t size = params.bitmap_rect.height() *
params.bitmap_rect.width() * 4;
TransportDIB* dib = process_->GetTransportDIB(params.bitmap);
@@ -879,7 +880,7 @@ void RenderWidgetHost::OnMsgUpdateRect(
// which attempts to move the plugin windows and in the process could
// dispatch other window messages which could cause the view to be
// destroyed.
- if (view_ && !is_gpu_rendering_active_) {
+ if (view_ && !is_accelerated_compositing_active_) {
view_being_painted_ = true;
view_->DidUpdateBackingStore(params.scroll_rect, params.dx, params.dy,
params.copy_rects);
@@ -977,14 +978,16 @@ void RenderWidgetHost::OnMsgImeCancelComposition() {
view_->ImeCancelComposition();
}
-void RenderWidgetHost::OnMsgGpuRenderingActivated(bool activated) {
+void RenderWidgetHost::OnMsgDidActivateAcceleratedCompositing(bool activated) {
#if defined(OS_MACOSX)
- bool old_state = is_gpu_rendering_active_;
+ bool old_state = is_accelerated_compositing_active_;
#endif
- is_gpu_rendering_active_ = activated;
+ is_accelerated_compositing_active_ = activated;
#if defined(OS_MACOSX)
- if (old_state != is_gpu_rendering_active_ && view_)
+ if (old_state != is_accelerated_compositing_active_ && view_)
view_->GpuRenderingStateDidChange();
+#elif defined(OS_WIN)
+ view_->ShowCompositorHostWindow(is_accelerated_compositing_active_);
#elif defined(TOOLKIT_USES_GTK)
view_->AcceleratedCompositingActivated(activated);
#endif
@@ -1089,7 +1092,6 @@ void RenderWidgetHost::OnMsgDestroyPluginContainer(gfx::PluginWindowHandle id) {
NOTIMPLEMENTED();
}
}
-
#endif
void RenderWidgetHost::PaintBackingStoreRect(
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index 9f2225b..47e4dab 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -203,7 +203,9 @@ class RenderWidgetHost : public IPC::Channel::Listener,
virtual void LostCapture();
// Tells us whether the page is rendered directly via the GPU process.
- bool is_gpu_rendering_active() { return is_gpu_rendering_active_; }
+ bool is_accelerated_compositing_active() {
+ return is_accelerated_compositing_active_;
+ }
// Notifies the RenderWidgetHost that the View was destroyed.
void ViewDestroyed();
@@ -484,7 +486,7 @@ class RenderWidgetHost : public IPC::Channel::Listener,
const gfx::Rect& caret_rect);
void OnMsgImeCancelComposition();
- void OnMsgGpuRenderingActivated(bool activated);
+ void OnMsgDidActivateAcceleratedCompositing(bool activated);
#if defined(OS_MACOSX)
void OnMsgGetScreenInfo(gfx::NativeViewId view,
@@ -564,7 +566,7 @@ class RenderWidgetHost : public IPC::Channel::Listener,
bool is_hidden_;
// True when a page is rendered directly via the GPU process.
- bool is_gpu_rendering_active_;
+ bool is_accelerated_compositing_active_;
// Set if we are waiting for a repaint ack for the view.
bool repaint_ack_pending_;
diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h
index 4ad2c41..8235ebf 100644
--- a/chrome/browser/renderer_host/render_widget_host_view.h
+++ b/chrome/browser/renderer_host/render_widget_host_view.h
@@ -246,6 +246,12 @@ class RenderWidgetHostView {
virtual void AcceleratedCompositingActivated(bool activated) = 0;
#endif
+#if defined(OS_WIN)
+ virtual gfx::PluginWindowHandle CreateCompositorHostWindow() = 0;
+ virtual void WillWmDestroy() = 0;
+ virtual void ShowCompositorHostWindow(bool show) = 0;
+#endif
+
// Toggles visual muting of the render view area. This is on when a
// constrained window is showing.
virtual void SetVisuallyDeemphasized(bool deemphasized) = 0;
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
index bf39966..aa43529 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -814,7 +814,7 @@ void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) {
// If the GPU process is rendering directly into the View,
// call the compositor directly.
RenderWidgetHost* render_widget_host = GetRenderWidgetHost();
- if (render_widget_host->is_gpu_rendering_active()) {
+ if (render_widget_host->is_accelerated_compositing_active()) {
host_->ScheduleComposite();
return;
}
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index 307eb2e..b0ef7e6 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -745,7 +745,7 @@ void RenderWidgetHostViewMac::DidUpdateBackingStore(
if (!is_hidden_) {
std::vector<gfx::Rect> rects(copy_rects);
- // Because the findbar might be open, we cannot use scrollRect:by: here. For
+ // Because the findbar might be open, we cannot use scrollRect:by: here. For
// now, simply mark all of scroll rect as dirty.
if (!scroll_rect.IsEmpty())
rects.push_back(scroll_rect);
@@ -1019,8 +1019,8 @@ void RenderWidgetHostViewMac::UpdateRootGpuViewVisibility(
// Plugins are destroyed on page navigate. The compositor layer on the other
// hand is created on demand and then stays alive until its renderer process
// dies (usually on cross-domain navigation). Instead, only a flag
- // |is_gpu_rendering_active()| is flipped when the compositor output should be
- // shown/hidden.
+ // |is_accelerated_compositing_active()| is flipped when the compositor output
+ // should be shown/hidden.
// Show/hide the view belonging to the compositor here.
plugin_container_manager_.set_gpu_rendering_active(show_gpu_widget);
@@ -1085,9 +1085,9 @@ void RenderWidgetHostViewMac::AcknowledgeSwapBuffers(
void RenderWidgetHostViewMac::GpuRenderingStateDidChange() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (GetRenderWidgetHost()->is_gpu_rendering_active()) {
+ if (GetRenderWidgetHost()->is_accelerated_compositing_active()) {
UpdateRootGpuViewVisibility(
- GetRenderWidgetHost()->is_gpu_rendering_active());
+ GetRenderWidgetHost()->is_accelerated_compositing_active());
} else {
needs_gpu_visibility_update_after_repaint_ = true;
}
@@ -1685,7 +1685,8 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) {
const gfx::Rect damagedRect([self flipNSRectToRect:dirtyRect]);
- if (renderWidgetHostView_->render_widget_host_->is_gpu_rendering_active()) {
+ if (renderWidgetHostView_->render_widget_host_->
+ is_accelerated_compositing_active()) {
gfx::Rect gpuRect;
gfx::PluginWindowHandle root_handle =
diff --git a/chrome/browser/renderer_host/render_widget_host_view_views.cc b/chrome/browser/renderer_host/render_widget_host_view_views.cc
index 20797ad..b9f386e 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_views.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_views.cc
@@ -350,7 +350,7 @@ void RenderWidgetHostViewViews::Paint(gfx::Canvas* canvas) {
// Don't do any painting if the GPU process is rendering directly
// into the View.
RenderWidgetHost* render_widget_host = GetRenderWidgetHost();
- if (render_widget_host->is_gpu_rendering_active()) {
+ if (render_widget_host->is_accelerated_compositing_active()) {
return;
}
@@ -603,7 +603,8 @@ bool RenderWidgetHostViewViews::ContainsNativeView(
return false;
}
-void RenderWidgetHostViewViews::AcceleratedCompositingActivated(bool activated) {
+void RenderWidgetHostViewViews::AcceleratedCompositingActivated(
+ bool activated) {
// TODO(anicolao): figure out if we need something here
if (activated)
NOTIMPLEMENTED();
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 3f9b9b1..df78d00 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc
@@ -281,6 +281,7 @@ RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget(
RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
: render_widget_host_(widget),
+ compositor_host_window_(NULL),
track_mouse_leave_(false),
ime_notification_(false),
capture_enter_key_(false),
@@ -382,6 +383,13 @@ void RenderWidgetHostViewWin::SetSize(const gfx::Size& size) {
UINT swp_flags = SWP_NOSENDCHANGING | SWP_NOOWNERZORDER | SWP_NOCOPYBITS |
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE;
SetWindowPos(NULL, 0, 0, size.width(), size.height(), swp_flags);
+ if (compositor_host_window_) {
+ ::SetWindowPos(compositor_host_window_,
+ NULL,
+ 0, 0,
+ size.width(), size.height(),
+ SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE);
+ }
render_widget_host_->WasResized();
EnsureTooltip();
}
@@ -709,6 +717,26 @@ void RenderWidgetHostViewWin::RenderViewGone() {
DestroyWindow();
}
+static BOOL CALLBACK AddChildWindowToVector(HWND hwnd, LPARAM lparam) {
+ std::vector<HWND>* vector = reinterpret_cast<std::vector<HWND>*>(lparam);
+ vector->push_back(hwnd);
+ return TRUE;
+}
+
+void RenderWidgetHostViewWin::WillWmDestroy() {
+ if (!compositor_host_window_)
+ return;
+
+ std::vector<HWND> all_child_windows;
+ ::EnumChildWindows(compositor_host_window_, AddChildWindowToVector,
+ reinterpret_cast<LPARAM>(&all_child_windows));
+ if (all_child_windows.size()) {
+ DCHECK(all_child_windows.size() == 1);
+ ::ShowWindow(all_child_windows[0], SW_HIDE);
+ ::SetParent(all_child_windows[0], NULL);
+ }
+}
+
void RenderWidgetHostViewWin::WillDestroyRenderWidget(RenderWidgetHost* rwh) {
if (rwh == render_widget_host_)
render_widget_host_ = NULL;
@@ -722,6 +750,7 @@ void RenderWidgetHostViewWin::Destroy() {
// OnFinalMessage();
close_on_deactivate_ = false;
being_destroyed_ = true;
+ WillWmDestroy();
DestroyWindow();
}
@@ -849,7 +878,7 @@ void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) {
// If the GPU process is rendering directly into the View,
// call the compositor directly.
RenderWidgetHost* render_widget_host = GetRenderWidgetHost();
- if (render_widget_host->is_gpu_rendering_active()) {
+ if (render_widget_host->is_accelerated_compositing_active()) {
// We initialize paint_dc here so that BeginPaint()/EndPaint()
// get called to validate the region.
CPaintDC paint_dc(m_hWnd);
@@ -1457,6 +1486,136 @@ void RenderWidgetHostViewWin::Observe(NotificationType type,
browser_accessibility_manager_.reset(NULL);
}
+// Looks through the children windows of the CompositorHostWindow. If the
+// compositor child window is found, its size is checked against the host
+// window's size. If the child is smaller in either dimensions, we fill
+// the host window with white to avoid unseemly cracks.
+static void PaintCompositorHostWindow(HWND hWnd) {
+ PAINTSTRUCT paint;
+ BeginPaint(hWnd, &paint);
+
+ std::vector<HWND> child_windows;
+ EnumChildWindows(hWnd, AddChildWindowToVector,
+ reinterpret_cast<LPARAM>(&child_windows));
+
+ if (child_windows.size()) {
+ HWND child = child_windows[0];
+
+ RECT host_rect, child_rect;
+ GetClientRect(hWnd, &host_rect);
+ if (GetClientRect(child, &child_rect)) {
+ if (child_rect.right < host_rect.right ||
+ child_rect.bottom != host_rect.bottom) {
+ FillRect(paint.hdc, &host_rect,
+ static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
+ }
+ }
+ }
+ EndPaint(hWnd, &paint);
+}
+
+// WndProc for the compositor host window. We use this instead of Default so
+// we can drop WM_PAINT and WM_ERASEBKGD messages on the floor.
+static LRESULT CALLBACK CompositorHostWindowProc(HWND hWnd, UINT message,
+ WPARAM wParam, LPARAM lParam) {
+ switch (message) {
+ case WM_ERASEBKGND:
+ return 0;
+ case WM_DESTROY:
+ return 0;
+ case WM_PAINT:
+ PaintCompositorHostWindow(hWnd);
+ return 0;
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+}
+
+// Creates a HWND within the RenderWidgetHostView that will serve as a host
+// for a HWND that the GPU process will create. The host window is used
+// to Z-position the GPU's window relative to other plugin windows.
+gfx::PluginWindowHandle RenderWidgetHostViewWin::CreateCompositorHostWindow() {
+ DCHECK(!compositor_host_window_);
+ static ATOM window_class = 0;
+ if (!window_class) {
+ WNDCLASSEX wcex;
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.style = 0;
+ wcex.lpfnWndProc = CompositorHostWindowProc;
+ 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"CompositorHostWindowClass";
+ wcex.hIconSm = 0;
+ window_class = RegisterClassEx(&wcex);
+ DCHECK(window_class);
+ }
+
+ compositor_host_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, m_hWnd, 0, GetModuleHandle(NULL), 0);
+ DCHECK(compositor_host_window_);
+
+ // We need to not just "WM_SHOW" the new indow, but reparent it
+ // below any existing plugin existing windows.
+ ShowCompositorHostWindow(true);
+
+ return static_cast<gfx::PluginWindowHandle>(compositor_host_window_);
+}
+
+void RenderWidgetHostViewWin::ShowCompositorHostWindow(bool show) {
+ // When we first create the compositor, we will get a show request from
+ // the renderer before we have gotten the create request from the GPU. In this
+ // case, simply ignore the show request.
+ if (compositor_host_window_ == NULL)
+ return;
+
+ if (show) {
+ UINT flags = SWP_NOSENDCHANGING | SWP_NOCOPYBITS | SWP_NOZORDER |
+ SWP_NOACTIVATE | SWP_DEFERERASE | SWP_SHOWWINDOW;
+ gfx::Rect rect = GetViewBounds();
+ ::SetWindowPos(compositor_host_window_, NULL, 0, 0,
+ rect.width(), rect.height(),
+ flags);
+
+ // Get all the child windows of this view, including the compositor window.
+ std::vector<HWND> all_child_windows;
+ ::EnumChildWindows(m_hWnd, AddChildWindowToVector,
+ reinterpret_cast<LPARAM>(&all_child_windows));
+
+ // Build a list of just the plugin window handles
+ std::vector<HWND> plugin_windows;
+ bool compositor_host_window_found = false;
+ for (size_t i = 0; i < all_child_windows.size(); ++i) {
+ if (all_child_windows[i] != compositor_host_window_)
+ plugin_windows.push_back(all_child_windows[i]);
+ else
+ compositor_host_window_found = true;
+ }
+ DCHECK(compositor_host_window_found);
+
+ // Set all the plugin windows to be "after" the compositor window.
+ // When the compositor window is created, gets placed above plugins.
+ for (size_t i = 0; i < plugin_windows.size(); ++i) {
+ HWND next;
+ if (i + 1 < plugin_windows.size())
+ next = plugin_windows[i+1];
+ else
+ next = compositor_host_window_;
+ ::SetWindowPos(plugin_windows[i], next, 0, 0, 0, 0,
+ SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+ }
+ } else {
+ ::ShowWindow(compositor_host_window_, SW_HIDE);
+ }
+}
+
void RenderWidgetHostViewWin::SetAccessibilityFocus(int acc_obj_id) {
if (!browser_accessibility_manager_.get() ||
!render_widget_host_ ||
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h
index 13609e6..7f0a30e 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.h
@@ -154,6 +154,7 @@ class RenderWidgetHostViewWin
const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
const std::vector<gfx::Rect>& copy_rects);
virtual void RenderViewGone();
+ virtual void WillWmDestroy(); // called by TabContents before DestroyWindow
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh);
virtual void Destroy();
virtual void SetTooltipText(const std::wstring& tooltip_text);
@@ -161,6 +162,10 @@ class RenderWidgetHostViewWin
virtual void SetBackground(const SkBitmap& background);
virtual bool ContainsNativeView(gfx::NativeView native_view) const;
virtual void SetVisuallyDeemphasized(bool deemphasized);
+
+ virtual gfx::PluginWindowHandle CreateCompositorHostWindow();
+ virtual void ShowCompositorHostWindow(bool show);
+
virtual void OnAccessibilityNotifications(
const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params);
@@ -265,6 +270,9 @@ class RenderWidgetHostViewWin
// The associated Model.
RenderWidgetHost* render_widget_host_;
+ // When we are doing accelerated compositing
+ HWND compositor_host_window_;
+
// The cursor for the page. This is passed up from the renderer.
WebCursor current_cursor_;
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.cc b/chrome/browser/renderer_host/test/test_render_view_host.cc
index 65d82e9..e4dc729 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.cc
+++ b/chrome/browser/renderer_host/test/test_render_view_host.cc
@@ -181,6 +181,17 @@ void TestRenderWidgetHostView::AcceleratedSurfaceBuffersSwapped(
void TestRenderWidgetHostView::GpuRenderingStateDidChange() {
}
+#elif defined(OS_WIN)
+gfx::PluginWindowHandle TestRenderWidgetHostView::CreateCompositorHostWindow(
+ ) {
+ return gfx::kNullPluginWindow;
+}
+
+void TestRenderWidgetHostView::WillWmDestroy() {
+}
+
+void TestRenderWidgetHostView::ShowCompositorHostWindow(bool show) {
+}
#endif
TestRenderViewHostFactory::TestRenderViewHostFactory(
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h
index fe6daa7..4f5d355 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.h
+++ b/chrome/browser/renderer_host/test/test_render_view_host.h
@@ -124,6 +124,10 @@ class TestRenderWidgetHostView : public RenderWidgetHostView {
int32 route_id,
uint64 swap_buffers_count);
virtual void GpuRenderingStateDidChange();
+#elif defined(OS_WIN)
+ virtual gfx::PluginWindowHandle CreateCompositorHostWindow();
+ virtual void WillWmDestroy();
+ virtual void ShowCompositorHostWindow(bool show);
#endif
virtual void SetVisuallyDeemphasized(bool deemphasized) { }
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index c846d62..4a225b2 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -486,8 +486,13 @@ TabContents::~TabContents() {
#if defined(OS_WIN)
// If we still have a window handle, destroy it. GetNativeView can return
// NULL if this contents was part of a window that closed.
- if (GetNativeView())
+ if (GetNativeView()) {
+ RenderViewHost* host = render_view_host();
+ if (host && host->view()) {
+ host->view()->WillWmDestroy();
+ }
::DestroyWindow(GetNativeView());
+ }
#endif
// OnCloseStarted isn't called in unit tests.
diff --git a/chrome/common/gpu_messages_internal.h b/chrome/common/gpu_messages_internal.h
index c124530..10b0961 100644
--- a/chrome/common/gpu_messages_internal.h
+++ b/chrome/common/gpu_messages_internal.h
@@ -113,6 +113,16 @@ IPC_BEGIN_MESSAGES(GpuHost)
// should cause the browser to redraw the compositor's contents.
IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params)
+#elif defined(OS_WIN)
+ // Create and get the HWND for the compositor window
+ IPC_SYNC_MESSAGE_CONTROL2_1(GpuHostMsg_CreateCompositorHostWindow,
+ int32, /* renderer_id */
+ int32, /* render_view_id */
+ gfx::PluginWindowHandle /* compositor_host_id */)
+
+ IPC_MESSAGE_CONTROL2(GpuHostMsg_ScheduleComposite,
+ int32, /* renderer_id */
+ int32 /* render_view_id */)
#endif
IPC_END_MESSAGES(GpuHost)
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 41b9dca..2d82061 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1315,10 +1315,10 @@ IPC_BEGIN_MESSAGES(ViewHost)
IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateRect,
ViewHostMsg_UpdateRect_Params)
- // Sent by the renderer when GPU compositing is enabled or disabled to notify
- // the browser whether or not is should do paiting.
- IPC_MESSAGE_ROUTED1(ViewHostMsg_GpuRenderingActivated,
- bool /* true if the GPU process renders to window */)
+ // Sent by the renderer when accelerated compositing is enabled or disabled to
+ // notify the browser whether or not is should do painting.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_DidActivateAcceleratedCompositing,
+ bool /* true if the accelerated compositor is actve */)
// Acknowledges receipt of a ViewMsg_HandleInputEvent message.
// Payload is a WebInputEvent::Type which is the type of the event, followed
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
diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc
index bcf58b0..ee1ccd9 100644
--- a/chrome/renderer/render_widget.cc
+++ b/chrome/renderer/render_widget.cc
@@ -523,8 +523,7 @@ void RenderWidget::DoDeferredUpdate() {
dib_id = current_paint_buf_->id();
} else { // Accelerated compositing path
// Begin painting.
- bool finish = next_paint_is_resize_ack();
- webwidget_->composite(finish);
+ webwidget_->composite(false);
}
// sending an ack to browser process that the paint is complete...
@@ -628,7 +627,7 @@ void RenderWidget::didScrollRect(int dx, int dy, const WebRect& clip_rect) {
void RenderWidget::didActivateAcceleratedCompositing(bool active) {
is_accelerated_compositing_active_ = active;
- Send(new ViewHostMsg_GpuRenderingActivated(
+ Send(new ViewHostMsg_DidActivateAcceleratedCompositing(
routing_id_, is_accelerated_compositing_active_));
}