summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorbacker@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 21:42:06 +0000
committerbacker@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 21:42:06 +0000
commitc03a6e7395d13e54365635c6396362a546b796e1 (patch)
treea3321f370dec32331553509591b4174660dec9e9 /chrome
parenta7b85b1c6333f420a5eb43d2899ae56ac487df60 (diff)
downloadchromium_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
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/gpu_process_host_ui_shim.cc89
-rw-r--r--chrome/browser/gpu_process_host_ui_shim.h18
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.cc32
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.h5
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h5
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm18
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_views.cc6
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_views.h4
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.cc7
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.h3
-rw-r--r--chrome/test/render_view_test.cc1
11 files changed, 80 insertions, 108 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(),