summaryrefslogtreecommitdiffstats
path: root/chrome/browser
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/browser
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/browser')
-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
15 files changed, 294 insertions, 33 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.