diff options
author | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-19 21:42:06 +0000 |
---|---|---|
committer | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-19 21:42:06 +0000 |
commit | c03a6e7395d13e54365635c6396362a546b796e1 (patch) | |
tree | a3321f370dec32331553509591b4174660dec9e9 | |
parent | a7b85b1c6333f420a5eb43d2899ae56ac487df60 (diff) | |
download | chromium_src-c03a6e7395d13e54365635c6396362a546b796e1.zip chromium_src-c03a6e7395d13e54365635c6396362a546b796e1.tar.gz chromium_src-c03a6e7395d13e54365635c6396362a546b796e1.tar.bz2 |
Progress towards fixing 77536
This first thing this CL does is plumbs through the surface that the GPU will eventually render to very early on (with the ViewMsg_New and ViewMsg_CreateNew IPCs). Previously, these surfaces were acquired at the time that GPU got a request for a command buffer. This required mediation by the browser UI thread. With this CL, we pre-acquire the surfaces so that they can be passed with the request for the command buffer. This will allow us to handle the request on the browser IO thread.
The second thing this CL does is change the surface management a bit. When surfaces were acquired and released when command buffers were created and destroyed, the GPU process host was natural manager of surfaces. This pushes the management further down into the RWHV level and GtkNativeViewManager (on Linux). It fixes a minor resource leak.
BUG=first stage of 77536
TEST=By hand WebGL, 3D CSS, Pepper 3D on Linux, Windows, and Mac.
Review URL: http://codereview.chromium.org/6840060
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82165 0039d316-1c4b-4281-b951-d872f2087c98
36 files changed, 188 insertions, 133 deletions
diff --git a/chrome/browser/gpu_process_host_ui_shim.cc b/chrome/browser/gpu_process_host_ui_shim.cc index d4e8fc9..4d38ad1 100644 --- a/chrome/browser/gpu_process_host_ui_shim.cc +++ b/chrome/browser/gpu_process_host_ui_shim.cc @@ -112,52 +112,33 @@ void RouteToGpuProcessHostUIShimTask::Run() { ui_shim->OnMessageReceived(msg_); } -class GpuProcessHostUIShim::ViewSurface { +#if defined(OS_LINUX) +// Used to put a lock on surfaces so that the window to which the GPU +// process is drawing to doesn't disappear while it is drawing when +// a tab is closed. +class GpuProcessHostUIShim::SurfaceRef { public: - explicit ViewSurface(ViewID view_id); - ~ViewSurface(); - gfx::PluginWindowHandle surface() { return surface_; } + explicit SurfaceRef(gfx::PluginWindowHandle surface); + ~SurfaceRef(); 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)); +GpuProcessHostUIShim::SurfaceRef::SurfaceRef(gfx::PluginWindowHandle surface) + : surface_(surface) { + GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); + if (!manager->AddRefPermanentXID(surface_)) { + LOG(ERROR) << "Surface " << surface << " cannot be referenced."; } +} - RenderWidgetHostView* view = NULL; - if (host) - view = host->view(); - - return view; +GpuProcessHostUIShim::SurfaceRef::~SurfaceRef() { + // TODO(backer): ReleasePermanentXID has to be done on the UI thread. + // Post task to release once we move this code to the IO thread. + GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); + manager->ReleasePermanentXID(surface_); } +#endif // defined(OS_LINUX) GpuProcessHostUIShim::GpuProcessHostUIShim(int host_id, content::CauseForGpuLaunch cause_for_gpu_launch) @@ -418,31 +399,37 @@ void GpuProcessHostUIShim::Synchronize(SynchronizeCallback* callback) { } void GpuProcessHostUIShim::CreateViewCommandBuffer( + gfx::PluginWindowHandle compositing_surface, int32 render_view_id, int32 renderer_id, const GPUCreateCommandBufferConfig& init_params, CreateCommandBufferCallback* callback) { DCHECK(CalledOnValidThread()); linked_ptr<CreateCommandBufferCallback> wrapped_callback(callback); + +#if defined(OS_LINUX) ViewID view_id(renderer_id, render_view_id); // There should only be one such command buffer (for the compositor). In // practice, if the GPU process lost a context, GraphicsContext3D with // associated command buffer and view surface will not be gone until new // one is in place and all layers are reattached. - linked_ptr<ViewSurface> view_surface; - ViewSurfaceMap::iterator it = acquired_surfaces_.find(view_id); - if (it != acquired_surfaces_.end()) - view_surface = (*it).second; + linked_ptr<SurfaceRef> surface_ref; + SurfaceRefMap::iterator it = surface_refs_.find(view_id); + if (it != surface_refs_.end()) + surface_ref = (*it).second; else - view_surface.reset(new ViewSurface(view_id)); + surface_ref.reset(new SurfaceRef(compositing_surface)); +#endif // defined(OS_LINUX) - if (view_surface->surface() != gfx::kNullPluginWindow && + if (compositing_surface != gfx::kNullPluginWindow && Send(new GpuMsg_CreateViewCommandBuffer( - view_surface->surface(), render_view_id, renderer_id, init_params))) { + compositing_surface, render_view_id, renderer_id, init_params))) { create_command_buffer_requests_.push(wrapped_callback); - acquired_surfaces_.insert(std::pair<ViewID, linked_ptr<ViewSurface> >( - view_id, view_surface)); +#if defined(OS_LINUX) + surface_refs_.insert(std::pair<ViewID, linked_ptr<SurfaceRef> >( + view_id, surface_ref)); +#endif // defined(OS_LINUX) } else { CreateCommandBufferError(wrapped_callback.release(), MSG_ROUTING_NONE); } @@ -594,10 +581,12 @@ void GpuProcessHostUIShim::OnCommandBufferCreated(const int32 route_id) { void GpuProcessHostUIShim::OnDestroyCommandBuffer( gfx::PluginWindowHandle window, int32 renderer_id, int32 render_view_id) { +#if defined(OS_LINUX) ViewID view_id(renderer_id, render_view_id); - ViewSurfaceMap::iterator it = acquired_surfaces_.find(view_id); - if (it != acquired_surfaces_.end()) - acquired_surfaces_.erase(it); + SurfaceRefMap::iterator it = surface_refs_.find(view_id); + if (it != surface_refs_.end()) + surface_refs_.erase(it); +#endif // defined(OS_LINUX) } void GpuProcessHostUIShim::OnGraphicsInfoCollected(const GPUInfo& gpu_info) { diff --git a/chrome/browser/gpu_process_host_ui_shim.h b/chrome/browser/gpu_process_host_ui_shim.h index 8bcdb23..cd834a5 100644 --- a/chrome/browser/gpu_process_host_ui_shim.h +++ b/chrome/browser/gpu_process_host_ui_shim.h @@ -122,6 +122,7 @@ class GpuProcessHostUIShim // Tells the GPU process to create a new command buffer that draws into the // window associated with the given renderer. void CreateViewCommandBuffer( + gfx::PluginWindowHandle compositing_surface, int32 render_view_id, int32 renderer_id, const GPUCreateCommandBufferConfig& init_params, @@ -197,16 +198,21 @@ class GpuProcessHostUIShim std::queue<linked_ptr<CreateCommandBufferCallback> > create_command_buffer_requests_; +#if defined(OS_LINUX) 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. Multimap is used to simulate reference counting, see comment in + // Encapsulates surfaces that we lock when creating view command buffers. + // We release this lock once the command buffer (or associated GPU process) + // is destroyed. This prevents the browser from destroying the surface + // while the GPU process is drawing to it. + + // Multimap is used to simulate reference counting, see comment in // GpuProcessHostUIShim::CreateViewCommandBuffer. - class ViewSurface; - typedef std::multimap<ViewID, linked_ptr<ViewSurface> > ViewSurfaceMap; - ViewSurfaceMap acquired_surfaces_; + class SurfaceRef; + typedef std::multimap<ViewID, linked_ptr<SurfaceRef> > SurfaceRefMap; + SurfaceRefMap surface_refs_; +#endif // In single process and in process GPU mode, this references the // GpuChannelManager or null otherwise. It must be called and deleted on the 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 3ea582d..9a5a340 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc @@ -513,7 +513,7 @@ RenderWidgetHostViewGtk::RenderWidgetHostViewGtk(RenderWidgetHost* widget_host) destroy_handler_id_(0), dragged_at_horizontal_edge_(0), dragged_at_vertical_edge_(0), - accelerated_surface_acquired_(false), + compositing_surface_(gfx::kNullPluginWindow), last_mouse_down_(NULL) { host_->set_view(this); } @@ -770,11 +770,9 @@ void RenderWidgetHostViewGtk::RenderViewGone(base::TerminationStatus status, } void RenderWidgetHostViewGtk::Destroy() { - if (accelerated_surface_acquired_) { + if (compositing_surface_ != gfx::kNullPluginWindow) { GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); - gfx::NativeViewId view_id = gfx::IdFromNativeView(GetNativeView()); - gfx::PluginWindowHandle surface = manager->GetXIDForId(&surface, view_id); - manager->ReleasePermanentXID(surface); + manager->ReleasePermanentXID(compositing_surface_); } if (do_x_grab_) { @@ -1128,24 +1126,16 @@ 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()); +gfx::PluginWindowHandle RenderWidgetHostViewGtk::GetCompositingSurface() { + if (compositing_surface_ == gfx::kNullPluginWindow) { + GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); + 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; + if (!manager->GetPermanentXIDForId(&compositing_surface_, view_id)) { + DLOG(ERROR) << "Can't find XID for view id " << view_id; + } } - return surface; -} - -void RenderWidgetHostViewGtk::ReleaseCompositingSurface( - gfx::PluginWindowHandle surface) { - GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); - manager->ReleasePermanentXID(surface); - accelerated_surface_acquired_ = false; + return compositing_surface_; } void RenderWidgetHostViewGtk::ForwardKeyboardEvent( 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 a0038fd..0cf950a 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h @@ -94,8 +94,7 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView, virtual bool ContainsNativeView(gfx::NativeView native_view) const; virtual void AcceleratedCompositingActivated(bool activated); - virtual gfx::PluginWindowHandle AcquireCompositingSurface(); - virtual void ReleaseCompositingSurface(gfx::PluginWindowHandle surface); + virtual gfx::PluginWindowHandle GetCompositingSurface(); // ui::AnimationDelegate implementation. virtual void AnimationEnded(const ui::Animation* animation); @@ -248,7 +247,7 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView, // indicate the top edge, positive the bottom. int dragged_at_vertical_edge_; - bool accelerated_surface_acquired_; + gfx::PluginWindowHandle compositing_surface_; // The event for the last mouse down we handled. We need this for context // menus and drags. 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 eee516b..150c448 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.h +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h @@ -268,8 +268,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { uint64 swap_buffers_count); virtual void GpuRenderingStateDidChange(); - virtual gfx::PluginWindowHandle AcquireCompositingSurface(); - virtual void ReleaseCompositingSurface(gfx::PluginWindowHandle surface); + virtual gfx::PluginWindowHandle GetCompositingSurface(); void DrawAcceleratedSurfaceInstance( CGLContextObj context, @@ -388,6 +387,8 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { // set when the gpu widget needs to be hidden once a paint is completed. bool needs_gpu_visibility_update_after_repaint_; + gfx::PluginWindowHandle compositing_surface_; + DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewMac); }; 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 350a53b..3708e09 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -595,7 +595,8 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) is_loading_(false), is_hidden_(false), shutdown_factory_(this), - needs_gpu_visibility_update_after_repaint_(false) { + needs_gpu_visibility_update_after_repaint_(false), + compositing_surface_(gfx::kNullPluginWindow) { // |cocoa_view_| owns us and we will be deleted when |cocoa_view_| goes away. // Since we autorelease it, our caller must put |native_view()| into the view // hierarchy right after calling us. @@ -1102,8 +1103,7 @@ void RenderWidgetHostViewMac::DeallocFakePluginWindowHandle( plugin_container_manager_.IsRootContainer(window)) { GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::GetForRenderer( render_widget_host_->process()->id(), - content:: - CAUSE_FOR_GPU_LAUNCH_RENDERWIDGETHOSTVIEWMAC_DEALLOCFAKEPLUGINWINDOWHANDLE); + content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH); if (ui_shim) { ui_shim->DidDestroyAcceleratedSurface( render_widget_host_->process()->id(), @@ -1297,13 +1297,11 @@ void RenderWidgetHostViewMac::GpuRenderingStateDidChange() { } } -gfx::PluginWindowHandle RenderWidgetHostViewMac::AcquireCompositingSurface() { - return AllocateFakePluginWindowHandle(/*opaque=*/true, /*root=*/true); -} - -void RenderWidgetHostViewMac::ReleaseCompositingSurface( - gfx::PluginWindowHandle surface) { - DestroyFakePluginWindowHandle(surface); +gfx::PluginWindowHandle RenderWidgetHostViewMac::GetCompositingSurface() { + if (compositing_surface_ == gfx::kNullPluginWindow) + compositing_surface_ = AllocateFakePluginWindowHandle( + /*opaque=*/true, /*root=*/true); + return compositing_surface_; } void RenderWidgetHostViewMac::DrawAcceleratedSurfaceInstance( 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 47dc659..ee2c43f 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_views.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_views.cc @@ -415,7 +415,7 @@ void RenderWidgetHostViewViews::AcceleratedCompositingActivated( NOTIMPLEMENTED(); } -gfx::PluginWindowHandle RenderWidgetHostViewViews::AcquireCompositingSurface() { +gfx::PluginWindowHandle RenderWidgetHostViewViews::GetCompositingSurface() { GtkNativeViewManager* manager = GtkNativeViewManager::GetInstance(); gfx::PluginWindowHandle surface = gfx::kNullPluginWindow; gfx::NativeViewId view_id = gfx::IdFromNativeView(GetInnerNativeView()); @@ -426,10 +426,6 @@ gfx::PluginWindowHandle RenderWidgetHostViewViews::AcquireCompositingSurface() { return surface; } -void RenderWidgetHostViewViews::ReleaseCompositingSurface( - gfx::PluginWindowHandle surface) { -} - gfx::NativeView RenderWidgetHostViewViews::GetInnerNativeView() const { // TODO(sad): Ideally this function should be equivalent to GetNativeView, and // WidgetGtk-specific function call should not be necessary. 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 014844c..177f50b 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_views.h +++ b/chrome/browser/renderer_host/render_widget_host_view_views.h @@ -80,9 +80,7 @@ class RenderWidgetHostViewViews : public RenderWidgetHostView, bool animate) OVERRIDE; virtual bool ContainsNativeView(gfx::NativeView native_view) const OVERRIDE; virtual void AcceleratedCompositingActivated(bool activated) OVERRIDE; - virtual gfx::PluginWindowHandle AcquireCompositingSurface() OVERRIDE; - virtual void ReleaseCompositingSurface( - gfx::PluginWindowHandle surface) OVERRIDE; + virtual gfx::PluginWindowHandle GetCompositingSurface() OVERRIDE; // 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 30cf793..a889910 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -1514,7 +1514,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::AcquireCompositingSurface() { +gfx::PluginWindowHandle RenderWidgetHostViewWin::GetCompositingSurface() { // If the window has been created, don't recreate it a second time if (compositor_host_window_) return compositor_host_window_; @@ -1554,11 +1554,6 @@ gfx::PluginWindowHandle RenderWidgetHostViewWin::AcquireCompositingSurface() { 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 e2d3aa8..d90487c 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.h +++ b/chrome/browser/renderer_host/render_widget_host_view_win.h @@ -161,8 +161,7 @@ class RenderWidgetHostViewWin virtual bool ContainsNativeView(gfx::NativeView native_view) const; virtual void SetVisuallyDeemphasized(const SkColor* color, bool animate); - virtual gfx::PluginWindowHandle AcquireCompositingSurface(); - virtual void ReleaseCompositingSurface(gfx::PluginWindowHandle surface); + virtual gfx::PluginWindowHandle GetCompositingSurface(); virtual void ShowCompositorHostWindow(bool show); virtual void OnAccessibilityNotifications( diff --git a/chrome/test/render_view_test.cc b/chrome/test/render_view_test.cc index ebd16fd..a932d20 100644 --- a/chrome/test/render_view_test.cc +++ b/chrome/test/render_view_test.cc @@ -134,6 +134,7 @@ void RenderViewTest::SetUp() { // This needs to pass the mock render thread to the view. view_ = RenderView::Create(&render_thread_, 0, + gfx::kNullPluginWindow, kOpenerId, RendererPreferences(), WebPreferences(), diff --git a/content/browser/renderer_host/gpu_message_filter.cc b/content/browser/renderer_host/gpu_message_filter.cc index 9902a96..5fa10ad 100644 --- a/content/browser/renderer_host/gpu_message_filter.cc +++ b/content/browser/renderer_host/gpu_message_filter.cc @@ -205,6 +205,7 @@ void GpuMessageFilter::OnSynchronizeGpu(IPC::Message* reply) { } void GpuMessageFilter::OnCreateViewCommandBuffer( + gfx::PluginWindowHandle compositing_surface, int32 render_view_id, const GPUCreateCommandBufferConfig& init_params, IPC::Message* reply) { @@ -219,6 +220,7 @@ void GpuMessageFilter::OnCreateViewCommandBuffer( } ui_shim->CreateViewCommandBuffer( + compositing_surface, render_view_id, render_process_id_, init_params, diff --git a/content/browser/renderer_host/gpu_message_filter.h b/content/browser/renderer_host/gpu_message_filter.h index 34e75f1..c8e8ada 100644 --- a/content/browser/renderer_host/gpu_message_filter.h +++ b/content/browser/renderer_host/gpu_message_filter.h @@ -8,6 +8,7 @@ #include "content/browser/browser_message_filter.h" #include "content/common/gpu_process_launch_causes.h" +#include "ui/gfx/native_widget_types.h" class GpuProcessHost; class GpuProcessHostUIShim; @@ -42,6 +43,7 @@ class GpuMessageFilter : public BrowserMessageFilter, void OnEstablishGpuChannel(content::CauseForGpuLaunch); void OnSynchronizeGpu(IPC::Message* reply); void OnCreateViewCommandBuffer( + gfx::PluginWindowHandle compositing_surface, int32 render_view_id, const GPUCreateCommandBufferConfig& init_params, IPC::Message* reply); diff --git a/content/browser/renderer_host/render_view_host.cc b/content/browser/renderer_host/render_view_host.cc index d5eb8c9..5f11584 100644 --- a/content/browser/renderer_host/render_view_host.cc +++ b/content/browser/renderer_host/render_view_host.cc @@ -168,6 +168,7 @@ bool RenderViewHost::CreateRenderView(const string16& frame_name) { ViewMsg_New_Params params; params.parent_window = GetNativeViewId(); + params.compositing_surface = GetCompositingSurface(); params.renderer_preferences = delegate_->GetRendererPrefs(process()->profile()); params.web_preferences = delegate_->GetWebkitPrefs(); diff --git a/content/browser/renderer_host/render_widget_host.cc b/content/browser/renderer_host/render_widget_host.cc index 57004c9..d7ad0b5 100644 --- a/content/browser/renderer_host/render_widget_host.cc +++ b/content/browser/renderer_host/render_widget_host.cc @@ -122,6 +122,12 @@ gfx::NativeViewId RenderWidgetHost::GetNativeViewId() { return 0; } +gfx::PluginWindowHandle RenderWidgetHost::GetCompositingSurface() { + if (view_) + return view_->GetCompositingSurface(); + return gfx::kNullPluginWindow; +} + bool RenderWidgetHost::PreHandleKeyboardEvent( const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) { @@ -134,7 +140,8 @@ void RenderWidgetHost::Init() { renderer_initialized_ = true; // Send the ack along with the information on placement. - Send(new ViewMsg_CreatingNew_ACK(routing_id_, GetNativeViewId())); + Send(new ViewMsg_CreatingNew_ACK( + routing_id_, GetNativeViewId(), GetCompositingSurface())); WasResized(); } diff --git a/content/browser/renderer_host/render_widget_host.h b/content/browser/renderer_host/render_widget_host.h index 9ed7ccd..ab5aa91 100644 --- a/content/browser/renderer_host/render_widget_host.h +++ b/content/browser/renderer_host/render_widget_host.h @@ -413,6 +413,10 @@ class RenderWidgetHost : public IPC::Channel::Listener, // This is used for various IPC messages, including plugins. gfx::NativeViewId GetNativeViewId(); + // Retrieves an id for the surface that the renderer can draw to + // when accelerated compositing is enabled. + gfx::PluginWindowHandle GetCompositingSurface(); + // Called to handled a keyboard event before sending it to the renderer. // This is overridden by RenderView to send upwards to its delegate. // Returns true if the event was handled, and then the keyboard event will diff --git a/content/browser/renderer_host/render_widget_host_view.h b/content/browser/renderer_host/render_widget_host_view.h index 5d4cf69..76c1db4 100644 --- a/content/browser/renderer_host/render_widget_host_view.h +++ b/content/browser/renderer_host/render_widget_host_view.h @@ -270,8 +270,7 @@ class RenderWidgetHostView { virtual void ShowCompositorHostWindow(bool show) = 0; #endif - virtual gfx::PluginWindowHandle AcquireCompositingSurface() = 0; - virtual void ReleaseCompositingSurface(gfx::PluginWindowHandle surface) = 0; + virtual gfx::PluginWindowHandle GetCompositingSurface() = 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 diff --git a/content/browser/renderer_host/test_render_view_host.cc b/content/browser/renderer_host/test_render_view_host.cc index 6eba441..394d447 100644 --- a/content/browser/renderer_host/test_render_view_host.cc +++ b/content/browser/renderer_host/test_render_view_host.cc @@ -242,7 +242,7 @@ void TestRenderWidgetHostView::ShowCompositorHostWindow(bool show) { } #endif -gfx::PluginWindowHandle TestRenderWidgetHostView::AcquireCompositingSurface() { +gfx::PluginWindowHandle TestRenderWidgetHostView::GetCompositingSurface() { return gfx::kNullPluginWindow; } diff --git a/content/browser/renderer_host/test_render_view_host.h b/content/browser/renderer_host/test_render_view_host.h index 4326529..a860806 100644 --- a/content/browser/renderer_host/test_render_view_host.h +++ b/content/browser/renderer_host/test_render_view_host.h @@ -141,8 +141,7 @@ class TestRenderWidgetHostView : public RenderWidgetHostView { virtual void AcceleratedCompositingActivated(bool activated) { } #endif - virtual gfx::PluginWindowHandle AcquireCompositingSurface(); - virtual void ReleaseCompositingSurface(gfx::PluginWindowHandle surface) { } + virtual gfx::PluginWindowHandle GetCompositingSurface(); virtual bool ContainsNativeView(gfx::NativeView native_view) const; diff --git a/content/common/gpu_messages.h b/content/common/gpu_messages.h index 88fab8a..73fad10 100644 --- a/content/common/gpu_messages.h +++ b/content/common/gpu_messages.h @@ -152,7 +152,7 @@ IPC_MESSAGE_CONTROL3(GpuMsg_VisibilityChanged, // Tells the GPU process to create a new command buffer that renders directly // to a native view. A corresponding GpuCommandBufferStub is created. IPC_MESSAGE_CONTROL4(GpuMsg_CreateViewCommandBuffer, - gfx::PluginWindowHandle, /* view */ + gfx::PluginWindowHandle, /* compositing_surface */ int32, /* render_view_id */ int32, /* renderer_id */ GPUCreateCommandBufferConfig /* init_params */) @@ -210,7 +210,8 @@ IPC_SYNC_MESSAGE_CONTROL0_0(GpuHostMsg_SynchronizeGpu) // A renderer sends this to the browser process when it wants to // create a GL context associated with the given view_id. -IPC_SYNC_MESSAGE_CONTROL2_1(GpuHostMsg_CreateViewCommandBuffer, +IPC_SYNC_MESSAGE_CONTROL3_1(GpuHostMsg_CreateViewCommandBuffer, + gfx::PluginWindowHandle, /* view */ int32, /* render_view_id */ GPUCreateCommandBufferConfig, /* init_params */ int32 /* route_id */) diff --git a/content/common/gpu_process_launch_causes.h b/content/common/gpu_process_launch_causes.h index db4f62a..3d5128f 100644 --- a/content/common/gpu_process_launch_causes.h +++ b/content/common/gpu_process_launch_causes.h @@ -13,7 +13,6 @@ enum CauseForGpuLaunch { CAUSE_FOR_GPU_LAUNCH_ABOUT_GPUHANG, CAUSE_FOR_GPU_LAUNCH_GPUDATAMANAGER_REQUESTCOMPLETEGPUINFOIFNEEDED, CAUSE_FOR_GPU_LAUNCH_RENDERWIDGETFULLSCREENPEPPER_CREATECONTEXT, - CAUSE_FOR_GPU_LAUNCH_RENDERWIDGETHOSTVIEWMAC_DEALLOCFAKEPLUGINWINDOWHANDLE, CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE, CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, CAUSE_FOR_GPU_LAUNCH_MAX_ENUM diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 86e2328..140267e 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -710,6 +710,9 @@ IPC_STRUCT_BEGIN(ViewMsg_New_Params) // The parent window's id. IPC_STRUCT_MEMBER(gfx::NativeViewId, parent_window) + // Surface for accelerated rendering. + IPC_STRUCT_MEMBER(gfx::PluginWindowHandle, compositing_surface) + // Renderer-wide preferences. IPC_STRUCT_MEMBER(RendererPreferences, renderer_preferences) @@ -757,8 +760,9 @@ IPC_MESSAGE_CONTROL1(ViewMsg_New, // Reply in response to ViewHostMsg_ShowView or ViewHostMsg_ShowWidget. // similar to the new command, but used when the renderer created a view // first, and we need to update it. -IPC_MESSAGE_ROUTED1(ViewMsg_CreatingNew_ACK, - gfx::NativeViewId /* parent_hwnd */) +IPC_MESSAGE_ROUTED2(ViewMsg_CreatingNew_ACK, + gfx::NativeViewId /* parent_hwnd */, + gfx::PluginWindowHandle /* compositing_surface */) // Sends updated preferences to the renderer. IPC_MESSAGE_ROUTED1(ViewMsg_SetRendererPrefs, diff --git a/content/renderer/gpu_channel_host.cc b/content/renderer/gpu_channel_host.cc index 7630462..97fd549 100644 --- a/content/renderer/gpu_channel_host.cc +++ b/content/renderer/gpu_channel_host.cc @@ -101,6 +101,7 @@ bool GpuChannelHost::Send(IPC::Message* message) { } CommandBufferProxy* GpuChannelHost::CreateViewCommandBuffer( + gfx::PluginWindowHandle compositing_surface, int render_view_id, const std::string& allowed_extensions, const std::vector<int32>& attribs, @@ -117,7 +118,7 @@ CommandBufferProxy* GpuChannelHost::CreateViewCommandBuffer( int32 route_id; if (!RenderThread::current()->Send( new GpuHostMsg_CreateViewCommandBuffer( - render_view_id, init_params, &route_id))) { + compositing_surface, render_view_id, init_params, &route_id))) { return NULL; } diff --git a/content/renderer/gpu_channel_host.h b/content/renderer/gpu_channel_host.h index fa1d60d..4e50881 100644 --- a/content/renderer/gpu_channel_host.h +++ b/content/renderer/gpu_channel_host.h @@ -67,6 +67,7 @@ class GpuChannelHost : public IPC::Channel::Listener, // Create and connect to a command buffer in the GPU process. CommandBufferProxy* CreateViewCommandBuffer( + gfx::PluginWindowHandle compositing_surface, int render_view_id, const std::string& allowed_extensions, const std::vector<int32>& attribs, diff --git a/content/renderer/render_thread.cc b/content/renderer/render_thread.cc index 625ebbc..1a77c3f 100644 --- a/content/renderer/render_thread.cc +++ b/content/renderer/render_thread.cc @@ -428,6 +428,7 @@ void RenderThread::OnCreateNewView(const ViewMsg_New_Params& params) { RenderView::Create( this, params.parent_window, + params.compositing_surface, MSG_ROUTING_NONE, params.renderer_preferences, params.web_preferences, diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc index 05896d0..e1967c8 100644 --- a/content/renderer/render_view.cc +++ b/content/renderer/render_view.cc @@ -344,6 +344,7 @@ struct RenderView::PendingFileChooser { RenderView::RenderView(RenderThreadBase* render_thread, gfx::NativeViewId parent_hwnd, + gfx::PluginWindowHandle compositing_surface, int32 opener_id, const RendererPreferences& renderer_prefs, const WebPreferences& webkit_prefs, @@ -413,7 +414,7 @@ RenderView::RenderView(RenderThreadBase* render_thread, // completing initialization. Otherwise, we can finish it now. if (opener_id == MSG_ROUTING_NONE) { did_show_ = true; - CompleteInit(parent_hwnd); + CompleteInit(parent_hwnd, compositing_surface); } host_window_ = parent_hwnd; @@ -487,6 +488,7 @@ RenderView* RenderView::FromWebView(WebView* webview) { RenderView* RenderView::Create( RenderThreadBase* render_thread, gfx::NativeViewId parent_hwnd, + gfx::PluginWindowHandle compositing_surface, int32 opener_id, const RendererPreferences& renderer_prefs, const WebPreferences& webkit_prefs, @@ -498,6 +500,7 @@ RenderView* RenderView::Create( return new RenderView( render_thread, parent_hwnd, + compositing_surface, opener_id, renderer_prefs, webkit_prefs, @@ -1274,6 +1277,7 @@ WebView* RenderView::createView( RenderView* view = RenderView::Create(render_thread_, 0, + gfx::kNullPluginWindow, routing_id_, renderer_preferences_, webkit_preferences_, diff --git a/content/renderer/render_view.h b/content/renderer/render_view.h index 8f2afe4..1db83ee 100644 --- a/content/renderer/render_view.h +++ b/content/renderer/render_view.h @@ -176,6 +176,7 @@ class RenderView : public RenderWidget, static RenderView* Create( RenderThreadBase* render_thread, gfx::NativeViewId parent_hwnd, + gfx::PluginWindowHandle compositing_surface, int32 opener_id, const RendererPreferences& renderer_prefs, const WebPreferences& webkit_prefs, @@ -658,6 +659,7 @@ class RenderView : public RenderWidget, RenderView(RenderThreadBase* render_thread, gfx::NativeViewId parent_hwnd, + gfx::PluginWindowHandle compositing_surface, int32 opener_id, const RendererPreferences& renderer_prefs, const WebPreferences& webkit_prefs, diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 8cd6f35..26f3f99 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc @@ -148,10 +148,12 @@ void RenderWidget::DoInit(int32 opener_id, // This is used to complete pending inits and non-pending inits. For non- // pending cases, the parent will be the same as the current parent. This // indicates we do not need to reparent or anything. -void RenderWidget::CompleteInit(gfx::NativeViewId parent_hwnd) { +void RenderWidget::CompleteInit(gfx::NativeViewId parent_hwnd, + gfx::PluginWindowHandle compositing_surface) { DCHECK(routing_id_ != MSG_ROUTING_NONE); host_window_ = parent_hwnd; + compositing_surface_ = compositing_surface; Send(new ViewHostMsg_RenderViewReady(routing_id_)); } @@ -196,10 +198,12 @@ bool RenderWidget::Send(IPC::Message* message) { // Got a response from the browser after the renderer decided to create a new // view. -void RenderWidget::OnCreatingNewAck(gfx::NativeViewId parent) { +void RenderWidget::OnCreatingNewAck( + gfx::NativeViewId parent, + gfx::PluginWindowHandle compositing_surface) { DCHECK(routing_id_ != MSG_ROUTING_NONE); - CompleteInit(parent); + CompleteInit(parent, compositing_surface); } void RenderWidget::OnClose() { diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index b6cf16e..63580c7 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h @@ -74,6 +74,13 @@ class RenderWidget : public IPC::Channel::Listener, // Creates a WebWidget based on the popup type. static WebKit::WebWidget* CreateWebWidget(RenderWidget* render_widget); + // The compositing surface assigned by the RenderWidgetHost + // (or RenderViewHost). Will be gfx::kNullPluginWindow if not assigned yet, + // in which case we should not create any GPU command buffers with it. + gfx::PluginWindowHandle compositing_surface() const { + return compositing_surface_; + } + // The routing ID assigned by the RenderProcess. Will be MSG_ROUTING_NONE if // not yet assigned a view ID, in which case, the process MUST NOT send // messages with this ID to the parent. @@ -144,7 +151,8 @@ class RenderWidget : public IPC::Channel::Listener, IPC::SyncMessage* create_widget_message); // Finishes creation of a pending view started with Init. - void CompleteInit(gfx::NativeViewId parent); + void CompleteInit(gfx::NativeViewId parent, + gfx::PluginWindowHandle compositing_surface); // Paints the given rectangular region of the WebWidget into canvas (a // shared memory segment returned by AllocPaintBuf on Windows). The caller @@ -169,7 +177,8 @@ class RenderWidget : public IPC::Channel::Listener, // RenderWidget IPC message handlers void OnClose(); - void OnCreatingNewAck(gfx::NativeViewId parent); + void OnCreatingNewAck(gfx::NativeViewId parent, + gfx::PluginWindowHandle compositing_surface); virtual void OnResize(const gfx::Size& new_size, const gfx::Rect& resizer_rect); virtual void OnWasHidden(); @@ -367,6 +376,10 @@ class RenderWidget : public IPC::Channel::Listener, // compositor. bool is_accelerated_compositing_active_; + // Handle to a surface that is drawn to when accelerated compositing is + // active. + gfx::PluginWindowHandle compositing_surface_; + base::Time animation_floor_time_; bool animation_update_pending_; bool animation_task_posted_; diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc index d3e2e20..bbe80bc 100644 --- a/content/renderer/render_widget_fullscreen_pepper.cc +++ b/content/renderer/render_widget_fullscreen_pepper.cc @@ -318,6 +318,7 @@ void RenderWidgetFullscreenPepper::CreateContext() { }; context_ = RendererGLContext::CreateViewContext( host, + compositing_surface(), routing_id(), "GL_OES_packed_depth_stencil GL_OES_depth24", attribs, diff --git a/content/renderer/renderer_gl_context.cc b/content/renderer/renderer_gl_context.cc index 0fea88ce..18e0c1d 100644 --- a/content/renderer/renderer_gl_context.cc +++ b/content/renderer/renderer_gl_context.cc @@ -156,6 +156,7 @@ RendererGLContext::~RendererGLContext() { RendererGLContext* RendererGLContext::CreateViewContext( GpuChannelHost* channel, + gfx::PluginWindowHandle render_surface, int render_view_id, const char* allowed_extensions, const int32* attrib_list, @@ -164,6 +165,7 @@ RendererGLContext* RendererGLContext::CreateViewContext( scoped_ptr<RendererGLContext> context(new RendererGLContext(channel, NULL)); if (!context->Initialize( true, + render_surface, render_view_id, gfx::Size(), allowed_extensions, @@ -196,6 +198,7 @@ RendererGLContext* RendererGLContext::CreateOffscreenContext( scoped_ptr<RendererGLContext> context(new RendererGLContext(channel, parent)); if (!context->Initialize( false, + gfx::kNullPluginWindow, 0, size, allowed_extensions, @@ -366,6 +369,7 @@ RendererGLContext::RendererGLContext(GpuChannelHost* channel, } bool RendererGLContext::Initialize(bool onscreen, + gfx::PluginWindowHandle render_surface, int render_view_id, const gfx::Size& size, const char* allowed_extensions, @@ -419,11 +423,17 @@ bool RendererGLContext::Initialize(bool onscreen, // Create a proxy to a command buffer in the GPU process. if (onscreen) { - command_buffer_ = channel_->CreateViewCommandBuffer( - render_view_id, - allowed_extensions, - attribs, - active_url); + if (render_surface == gfx::kNullPluginWindow) { + LOG(ERROR) << "Invalid surface handle for onscreen context."; + command_buffer_ = NULL; + } else { + command_buffer_ = channel_->CreateViewCommandBuffer( + render_surface, + render_view_id, + allowed_extensions, + attribs, + active_url); + } } else { CommandBufferProxy* parent_command_buffer = parent_.get() ? parent_->command_buffer_ : NULL; diff --git a/content/renderer/renderer_gl_context.h b/content/renderer/renderer_gl_context.h index a40f5e1..26a6d00 100644 --- a/content/renderer/renderer_gl_context.h +++ b/content/renderer/renderer_gl_context.h @@ -91,6 +91,7 @@ class RendererGLContext : public base::SupportsWeakPtr<RendererGLContext> { // more cross-platform. static RendererGLContext* CreateViewContext( GpuChannelHost* channel, + gfx::PluginWindowHandle render_surface, int render_view_id, const char* allowed_extensions, const int32* attrib_list, @@ -205,6 +206,7 @@ class RendererGLContext : public base::SupportsWeakPtr<RendererGLContext> { RendererGLContext* parent); bool Initialize(bool onscreen, + gfx::PluginWindowHandle render_surface, int render_view_id, const gfx::Size& size, const char* allowed_extensions, diff --git a/content/renderer/webgraphicscontext3d_command_buffer_impl.cc b/content/renderer/webgraphicscontext3d_command_buffer_impl.cc index 57a66fa..2ff2b98 100644 --- a/content/renderer/webgraphicscontext3d_command_buffer_impl.cc +++ b/content/renderer/webgraphicscontext3d_command_buffer_impl.cc @@ -100,6 +100,7 @@ bool WebGraphicsContext3DCommandBufferImpl::initialize( web_view_ = web_view; context_ = RendererGLContext::CreateViewContext( host, + renderview->compositing_surface(), renderview->routing_id(), kWebGraphicsContext3DPerferredGLExtensions, attribs, diff --git a/ui/gfx/gtk_native_view_id_manager.cc b/ui/gfx/gtk_native_view_id_manager.cc index 3efc3c7..d2a3699 100644 --- a/ui/gfx/gtk_native_view_id_manager.cc +++ b/ui/gfx/gtk_native_view_id_manager.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -129,6 +129,20 @@ bool GtkNativeViewManager::GetPermanentXIDForId(XID* output, return true; } +bool GtkNativeViewManager::AddRefPermanentXID(XID xid) { + base::AutoLock locked(lock_); + + std::map<XID, PermanentXIDInfo>::iterator i = + perm_xid_to_info_.find(xid); + + if (i == perm_xid_to_info_.end()) + return false; + + i->second.ref_count++; + + return true; +} + void GtkNativeViewManager::ReleasePermanentXID(XID xid) { base::AutoLock locked(lock_); diff --git a/ui/gfx/gtk_native_view_id_manager.h b/ui/gfx/gtk_native_view_id_manager.h index 462a51d..6ea16a2 100644 --- a/ui/gfx/gtk_native_view_id_manager.h +++ b/ui/gfx/gtk_native_view_id_manager.h @@ -72,6 +72,11 @@ class GtkNativeViewManager { // returns: true if |id| is a valid id, false otherwise. bool GetPermanentXIDForId(XID* xid, gfx::NativeViewId id); + // Can be called from any thread. + // Will return false if the given XID isn't permanent or has already been + // released. + bool AddRefPermanentXID(XID xid); + // Must be called from the UI thread because we may need to access a // GtkWidget or destroy a GdkWindow. // diff --git a/ui/gfx/gtk_preserve_window.cc b/ui/gfx/gtk_preserve_window.cc index 174e23d..12585f3 100644 --- a/ui/gfx/gtk_preserve_window.cc +++ b/ui/gfx/gtk_preserve_window.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -82,6 +82,12 @@ static void gtk_preserve_window_realize(GtkWidget* widget) { gtk_widget_get_parent_window(widget), widget->allocation.x, widget->allocation.y); + GtkPreserveWindowPrivate* priv = GTK_PRESERVE_WINDOW_GET_PRIVATE(widget); + if (!priv->delegate_resize) { + gdk_window_resize(widget->window, + widget->allocation.width, + widget->allocation.height); + } widget->style = gtk_style_attach(widget->style, widget->window); gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL); |