diff options
author | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-18 13:30:25 +0000 |
---|---|---|
committer | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-18 13:30:25 +0000 |
commit | 9c6ce3cae3a48d077c3c26e69dac40bb397d439f (patch) | |
tree | 8f964b8dad39d114e2ceb91ebae79d40b20ebc82 /chrome | |
parent | a5624d948df50aaaac50a12b4919966dd39dbfb0 (diff) | |
download | chromium_src-9c6ce3cae3a48d077c3c26e69dac40bb397d439f.zip chromium_src-9c6ce3cae3a48d077c3c26e69dac40bb397d439f.tar.gz chromium_src-9c6ce3cae3a48d077c3c26e69dac40bb397d439f.tar.bz2 |
Refactor how surfaces are acquired for GPU compositing.
Rather than have a couple of nasty #if defined blocks, push the code down into the platform specific RenderWidgetHostView layer. Added support for releasing surfaces:
- if renderer crashes, RenderWidgetHostView releases the surfaces (no change from previous code)
- if gpu process crashes, the GpuProcessHostUIShim releases the surfaces (introduced in this patch)
- if the channel between the renderer and gpu process falls, the gpu process asks the GpuProcessHostUIShim to release the surface
BUG=none
TEST=by hand 3D css and WebGL on win, max, linux, and linux views
Review URL: http://codereview.chromium.org/6462034
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75387 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
13 files changed, 153 insertions, 67 deletions
diff --git a/chrome/browser/gpu_process_host_ui_shim.cc b/chrome/browser/gpu_process_host_ui_shim.cc index ef3f999..70bb25f 100644 --- a/chrome/browser/gpu_process_host_ui_shim.cc +++ b/chrome/browser/gpu_process_host_ui_shim.cc @@ -46,6 +46,53 @@ class SendOnIOThreadTask : public Task { } // namespace +class GpuProcessHostUIShim::ViewSurface { + public: + explicit ViewSurface(ViewID view_id); + ~ViewSurface(); + gfx::PluginWindowHandle surface() { return surface_; } + private: + RenderWidgetHostView* GetRenderWidgetHostView(); + ViewID view_id_; + gfx::PluginWindowHandle surface_; +}; + +GpuProcessHostUIShim::ViewSurface::ViewSurface(ViewID view_id) + : view_id_(view_id), surface_(gfx::kNullPluginWindow) { + RenderWidgetHostView* view = GetRenderWidgetHostView(); + if (view) + surface_ = view->AcquireCompositingSurface(); +} + +GpuProcessHostUIShim::ViewSurface::~ViewSurface() { + if (!surface_) + return; + + RenderWidgetHostView* view = GetRenderWidgetHostView(); + if (view) + view->ReleaseCompositingSurface(surface_); +} + +// We do separate lookups for the RenderWidgetHostView when acquiring +// and releasing surfaces (rather than caching) because the +// RenderWidgetHostView could die without warning. In such a case, +// it's the RenderWidgetHostView's responsibility to cleanup. +RenderWidgetHostView* GpuProcessHostUIShim::ViewSurface:: + GetRenderWidgetHostView() { + RenderProcessHost* process = RenderProcessHost::FromID(view_id_.first); + RenderWidgetHost* host = NULL; + if (process) { + host = static_cast<RenderWidgetHost*>( + process->GetListenerByID(view_id_.second)); + } + + RenderWidgetHostView* view = NULL; + if (host) + view = host->view(); + + return view; +} + GpuProcessHostUIShim::GpuProcessHostUIShim() : last_routing_id_(1), initialized_(false), @@ -213,44 +260,22 @@ void GpuProcessHostUIShim::CreateViewCommandBuffer( CreateCommandBufferCallback* callback) { DCHECK(CalledOnValidThread()); linked_ptr<CreateCommandBufferCallback> wrapped_callback(callback); + ViewID view_id(renderer_id, render_view_id); - gfx::PluginWindowHandle window = gfx::kNullPluginWindow; - RenderProcessHost* process = RenderProcessHost::FromID(renderer_id); - RenderWidgetHost* host = NULL; - if (process) { - host = static_cast<RenderWidgetHost*>( - process->GetListenerByID(render_view_id)); + // We assume that there can only be one such command buffer (for the + // compositor). + if (acquired_surfaces_.count(view_id) != 0) { + CreateCommandBufferError(wrapped_callback.release(), MSG_ROUTING_NONE); + return; } - RenderWidgetHostView* view = NULL; - if (host) - view = host->view(); + linked_ptr<ViewSurface> view_surface(new ViewSurface(view_id)); - if (view) { -#if defined(OS_LINUX) - gfx::NativeViewId view_id = NULL; - view_id = gfx::IdFromNativeView(view->GetNativeView()); - - // Lock the window that we will draw into. - GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); - if (!manager->GetPermanentXIDForId(&window, view_id)) { - DLOG(ERROR) << "Can't find XID for view id " << view_id; - } -#elif defined(OS_MACOSX) - // On Mac OS X we currently pass a (fake) PluginWindowHandle for the - // window that we draw to. - window = view->AllocateFakePluginWindowHandle( - /*opaque=*/true, /*root=*/true); -#elif defined(OS_WIN) - // Create a window that we will overlay. - window = view->GetCompositorHostWindow(); -#endif - } - - if (window != gfx::kNullPluginWindow && + if (view_surface->surface() != gfx::kNullPluginWindow && Send(new GpuMsg_CreateViewCommandBuffer( - window, render_view_id, renderer_id, init_params))) { + view_surface->surface(), render_view_id, renderer_id, init_params))) { create_command_buffer_requests_.push(wrapped_callback); + acquired_surfaces_[view_id] = view_surface; } else { CreateCommandBufferError(wrapped_callback.release(), MSG_ROUTING_NONE); } @@ -280,7 +305,7 @@ const GPUInfo& GpuProcessHostUIShim::gpu_info() const { void GpuProcessHostUIShim::AddCustomLogMessage(int level, const std::string& header, const std::string& message) { - OnLogMessage(level, header, message); + OnLogMessage(level, header, message); } bool GpuProcessHostUIShim::OnControlMessageReceived( @@ -389,31 +414,8 @@ void GpuProcessHostUIShim::OnCommandBufferCreated(const int32 route_id) { void GpuProcessHostUIShim::OnDestroyCommandBuffer( gfx::PluginWindowHandle window, int32 renderer_id, int32 render_view_id) { - if (!window) - return; - -#if defined(OS_LINUX) - GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); - manager->ReleasePermanentXID(window); -#elif defined(OS_MACOSX) || defined(OS_WIN) - RenderProcessHost* process = RenderProcessHost::FromID(renderer_id); - RenderWidgetHost* host = NULL; - if (process) { - host = static_cast<RenderWidgetHost*>( - process->GetListenerByID(render_view_id)); - } - RenderWidgetHostView* view = NULL; - if (host) - view = host->view(); - - if (view) { -#if defined(OS_MACOSX) - view->DestroyFakePluginWindowHandle(window); -#elif defined(OS_WIN) - view->ShowCompositorHostWindow(false); -#endif - } -#endif // defined(OS_MACOSX) || defined(OS_WIN) + ViewID view_id(renderer_id, render_view_id); + acquired_surfaces_.erase(view_id); } void GpuProcessHostUIShim::OnGraphicsInfoCollected(const GPUInfo& gpu_info) { @@ -512,3 +514,4 @@ bool GpuProcessHostUIShim::LoadGpuBlacklist() { gpu_blacklist_.reset(NULL); return false; } + diff --git a/chrome/browser/gpu_process_host_ui_shim.h b/chrome/browser/gpu_process_host_ui_shim.h index 396c2fc..14c2585 100644 --- a/chrome/browser/gpu_process_host_ui_shim.h +++ b/chrome/browser/gpu_process_host_ui_shim.h @@ -11,6 +11,7 @@ // portion of this class, the GpuProcessHost, is responsible for // shuttling messages between the browser and GPU processes. +#include <map> #include <queue> #include "base/callback.h" @@ -177,6 +178,15 @@ class GpuProcessHostUIShim : public IPC::Channel::Sender, std::queue<linked_ptr<CreateCommandBufferCallback> > create_command_buffer_requests_; + typedef std::pair<int32 /* renderer_id */, + int32 /* render_view_id */> ViewID; + + // Encapsulates surfaces that we acquire when creating view command buffers. + // We assume that a render view has at most 1 such surface associated + // with it. + class ViewSurface; + std::map<ViewID, linked_ptr<ViewSurface> > acquired_surfaces_; + bool initialized_; bool initialized_successfully_; diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h index 332c264..b6137ff 100644 --- a/chrome/browser/renderer_host/render_widget_host_view.h +++ b/chrome/browser/renderer_host/render_widget_host_view.h @@ -261,11 +261,13 @@ class RenderWidgetHostView { #endif #if defined(OS_WIN) - virtual gfx::PluginWindowHandle GetCompositorHostWindow() = 0; virtual void WillWmDestroy() = 0; virtual void ShowCompositorHostWindow(bool show) = 0; #endif + virtual gfx::PluginWindowHandle AcquireCompositingSurface() = 0; + virtual void ReleaseCompositingSurface(gfx::PluginWindowHandle surface) = 0; + // Toggles visual muting of the render view area. This is on when a // constrained window is showing, for example. |color| is the shade of // the overlay that covers the render view. If |animate| is true, the overlay 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 7fce046..5ef533d 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc @@ -38,6 +38,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/x/x11_util.h" #include "ui/gfx/gtk_preserve_window.h" +#include "ui/gfx/gtk_native_view_id_manager.h" #include "webkit/glue/webaccessibility.h" #include "webkit/glue/webcursor_gtk_data.h" #include "webkit/plugins/npapi/webplugin.h" @@ -495,7 +496,8 @@ RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host) do_x_grab_(false), is_fullscreen_(false), dragged_at_horizontal_edge_(0), - dragged_at_vertical_edge_(0) { + dragged_at_vertical_edge_(0), + accelerated_surface_acquired_(false) { host_->set_view(this); } @@ -732,6 +734,13 @@ void RenderWidgetHostViewGtk::RenderViewGone(base::TerminationStatus status, } void RenderWidgetHostViewGtk::Destroy() { + if (accelerated_surface_acquired_) { + GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); + gfx::NativeViewId view_id = gfx::IdFromNativeView(GetNativeView()); + gfx::PluginWindowHandle surface = manager->GetXIDForId(&surface, view_id); + manager->ReleasePermanentXID(surface); + } + if (do_x_grab_) { // Undo the X grab. GdkDisplay* display = gtk_widget_get_display(parent_); @@ -1071,6 +1080,26 @@ void RenderWidgetHostViewGtk::AcceleratedCompositingActivated(bool activated) { gtk_preserve_window_delegate_resize(widget, activated); } +gfx::PluginWindowHandle RenderWidgetHostViewGtk::AcquireCompositingSurface() { + GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); + gfx::PluginWindowHandle surface = gfx::kNullPluginWindow; + gfx::NativeViewId view_id = gfx::IdFromNativeView(GetNativeView()); + + if (!manager->GetPermanentXIDForId(&surface, view_id)) { + DLOG(ERROR) << "Can't find XID for view id " << view_id; + } else { + accelerated_surface_acquired_ = true; + } + return surface; +} + +void RenderWidgetHostViewGtk::ReleaseCompositingSurface( + gfx::PluginWindowHandle surface) { + GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); + manager->ReleasePermanentXID(surface); + accelerated_surface_acquired_ = false; +} + void RenderWidgetHostViewGtk::ForwardKeyboardEvent( const NativeWebKeyboardEvent& event) { if (!host_) diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h index b354a7b..6854067 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h @@ -90,7 +90,10 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView, virtual void DestroyPluginContainer(gfx::PluginWindowHandle id); virtual void SetVisuallyDeemphasized(const SkColor* color, bool animate); virtual bool ContainsNativeView(gfx::NativeView native_view) const; + virtual void AcceleratedCompositingActivated(bool activated); + virtual gfx::PluginWindowHandle AcquireCompositingSurface(); + virtual void ReleaseCompositingSurface(gfx::PluginWindowHandle surface); // ui::AnimationDelegate implementation. virtual void AnimationEnded(const ui::Animation* animation); @@ -224,6 +227,8 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView, // indicate the top edge, positive the bottom. int dragged_at_vertical_edge_; + bool accelerated_surface_acquired_; + #if defined(OS_CHROMEOS) // Custimized tooltip window. scoped_ptr<views::TooltipWindowGtk> tooltip_window_; diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h index 160197c..939ae36 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.h +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h @@ -262,6 +262,10 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { int32 route_id, uint64 swap_buffers_count); virtual void GpuRenderingStateDidChange(); + + virtual gfx::PluginWindowHandle AcquireCompositingSurface(); + virtual void ReleaseCompositingSurface(gfx::PluginWindowHandle surface); + void DrawAcceleratedSurfaceInstance( CGLContextObj context, gfx::PluginWindowHandle plugin_handle, 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 943c8cc..4bb8f77 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -1247,6 +1247,15 @@ void RenderWidgetHostViewMac::GpuRenderingStateDidChange() { } } +gfx::PluginWindowHandle RenderWidgetHostViewMac::AcquireCompositingSurface() { + return AllocateFakePluginWindowHandle(/*opaque=*/true, /*root=*/true); +} + +void RenderWidgetHostViewMac::ReleaseCompositingSurface( + gfx::PluginWindowHandle surface) { + DestroyFakePluginWindowHandle(surface); +} + void RenderWidgetHostViewMac::DrawAcceleratedSurfaceInstance( CGLContextObj context, gfx::PluginWindowHandle plugin_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 849924f..dac444a 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_views.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_views.cc @@ -27,6 +27,7 @@ #include "ui/base/x/x11_util.h" #include "ui/gfx/canvas.h" #include "ui/gfx/canvas_skia.h" +#include "ui/gfx/gtk_native_view_id_manager.h" #include "views/events/event.h" #include "views/ime/ime_context.h" #include "views/widget/widget.h" @@ -786,6 +787,21 @@ void RenderWidgetHostViewViews::AcceleratedCompositingActivated( NOTIMPLEMENTED(); } +gfx::PluginWindowHandle RenderWidgetHostViewViews::AcquireCompositingSurface() { + GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); + gfx::PluginWindowHandle surface = gfx::kNullPluginWindow; + gfx::NativeViewId view_id = gfx::IdFromNativeView(GetInnerNativeView()); + + if (!manager->GetXIDForId(&surface, view_id)) { + DLOG(ERROR) << "Can't find XID for view id " << view_id; + } + return surface; +} + +void RenderWidgetHostViewViews::ReleaseCompositingSurface( + gfx::PluginWindowHandle surface) { +} + WebKit::WebMouseEvent RenderWidgetHostViewViews::WebMouseEventFromViewsEvent( const views::MouseEvent& event) { WebKit::WebMouseEvent wmevent; diff --git a/chrome/browser/renderer_host/render_widget_host_view_views.h b/chrome/browser/renderer_host/render_widget_host_view_views.h index 2facf43..f7a2f05 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_views.h +++ b/chrome/browser/renderer_host/render_widget_host_view_views.h @@ -79,6 +79,8 @@ class RenderWidgetHostViewViews : public RenderWidgetHostView, virtual void SetVisuallyDeemphasized(const SkColor* color, bool animate); virtual bool ContainsNativeView(gfx::NativeView native_view) const; virtual void AcceleratedCompositingActivated(bool activated); + virtual gfx::PluginWindowHandle AcquireCompositingSurface(); + virtual void ReleaseCompositingSurface(gfx::PluginWindowHandle surface); // On some systems, there can be two native views, where an outer native view // contains the inner native view (e.g. when using GTK+). This returns the 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 896862b..cac04a02 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -1545,7 +1545,7 @@ static LRESULT CALLBACK CompositorHostWindowProc(HWND hWnd, UINT message, // 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::GetCompositorHostWindow() { +gfx::PluginWindowHandle RenderWidgetHostViewWin::AcquireCompositingSurface() { // If the window has been created, don't recreate it a second time if (compositor_host_window_) return compositor_host_window_; @@ -1584,6 +1584,11 @@ gfx::PluginWindowHandle RenderWidgetHostViewWin::GetCompositorHostWindow() { return static_cast<gfx::PluginWindowHandle>(compositor_host_window_); } +void RenderWidgetHostViewWin::ReleaseCompositingSurface( + gfx::PluginWindowHandle surface) { + ShowCompositorHostWindow(false); +} + 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 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 5af890a..977ef0a 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.h +++ b/chrome/browser/renderer_host/render_widget_host_view_win.h @@ -159,7 +159,8 @@ class RenderWidgetHostViewWin virtual bool ContainsNativeView(gfx::NativeView native_view) const; virtual void SetVisuallyDeemphasized(const SkColor* color, bool animate); - virtual gfx::PluginWindowHandle GetCompositorHostWindow(); + virtual gfx::PluginWindowHandle AcquireCompositingSurface(); + virtual void ReleaseCompositingSurface(gfx::PluginWindowHandle surface); virtual void ShowCompositorHostWindow(bool show); virtual void OnAccessibilityNotifications( 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 60e9f33..4bab6c8 100644 --- a/chrome/browser/renderer_host/test/test_render_view_host.cc +++ b/chrome/browser/renderer_host/test/test_render_view_host.cc @@ -220,10 +220,6 @@ void TestRenderWidgetHostView::AcceleratedSurfaceBuffersSwapped( void TestRenderWidgetHostView::GpuRenderingStateDidChange() { } #elif defined(OS_WIN) -gfx::PluginWindowHandle TestRenderWidgetHostView::GetCompositorHostWindow() { - return gfx::kNullPluginWindow; -} - void TestRenderWidgetHostView::WillWmDestroy() { } 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 dfc3d53..78afa0e 100644 --- a/chrome/browser/renderer_host/test/test_render_view_host.h +++ b/chrome/browser/renderer_host/test/test_render_view_host.h @@ -128,7 +128,6 @@ class TestRenderWidgetHostView : public RenderWidgetHostView { uint64 swap_buffers_count); virtual void GpuRenderingStateDidChange(); #elif defined(OS_WIN) - virtual gfx::PluginWindowHandle GetCompositorHostWindow(); virtual void WillWmDestroy(); virtual void ShowCompositorHostWindow(bool show); #endif @@ -140,6 +139,11 @@ class TestRenderWidgetHostView : public RenderWidgetHostView { virtual void AcceleratedCompositingActivated(bool activated) { } #endif + virtual gfx::PluginWindowHandle AcquireCompositingSurface() { + return gfx::kNullPluginWindow; + } + virtual void ReleaseCompositingSurface(gfx::PluginWindowHandle surface) { } + virtual bool ContainsNativeView(gfx::NativeView native_view) const; bool is_showing() const { return is_showing_; } |