diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-27 19:21:55 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-27 19:21:55 +0000 |
commit | 2d7c85529b0210e148d70eb3d0edf485d6521708 (patch) | |
tree | 59152cec5d13a4f91b88ffa8610ca9a82f4fdcce /content/browser | |
parent | be16cf2bcf61a6ac255c347a6ba8c65d213a5a11 (diff) | |
download | chromium_src-2d7c85529b0210e148d70eb3d0edf485d6521708.zip chromium_src-2d7c85529b0210e148d70eb3d0edf485d6521708.tar.gz chromium_src-2d7c85529b0210e148d70eb3d0edf485d6521708.tar.bz2 |
GPU compositing surface handle is no longer sent to renderer process.
Instead it is stored in a map in RenderWidgetHelper indexed by RenderWidgetHost route ID. This allows the UI thread to maintain the mapping as windows are created and destroyed and the IO thread to lookup the mapping in order to create GL contexts that render to the windows.
This avoids a race where JavaScript would open a popup window and immediately try to use an accelerated canvas to render to it (2D canvas or WebGL canvas). <-- This is no longer true of this patch. There was a potential deadlock.
WebGL canvas used to work in this case only because it would fall back to using ReadPixels.
This goes some way to fixing the bug referenced below but does not fix it completely.BUG=80703
Review URL: http://codereview.chromium.org/7136001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90617 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
16 files changed, 102 insertions, 19 deletions
diff --git a/content/browser/renderer_host/browser_render_process_host.cc b/content/browser/renderer_host/browser_render_process_host.cc index 1c2d42d..0ced958 100644 --- a/content/browser/renderer_host/browser_render_process_host.cc +++ b/content/browser/renderer_host/browser_render_process_host.cc @@ -364,7 +364,7 @@ void BrowserRenderProcessHost::CreateMessageFilters() { channel_->AddFilter( GeolocationDispatcherHost::New( id(), profile()->GetGeolocationPermissionContext())); - channel_->AddFilter(new GpuMessageFilter(id())); + channel_->AddFilter(new GpuMessageFilter(id(), widget_helper_.get())); channel_->AddFilter(new PepperFileMessageFilter(id(), profile())); channel_->AddFilter( new PepperMessageFilter(&profile()->GetResourceContext())); @@ -715,6 +715,12 @@ void BrowserRenderProcessHost::ClearTransportDIBCache() { cached_dibs_.clear(); } +void BrowserRenderProcessHost::SetCompositingSurface( + int render_widget_id, + gfx::PluginWindowHandle compositing_surface) { + widget_helper_->SetCompositingSurface(render_widget_id, compositing_surface); +} + bool BrowserRenderProcessHost::Send(IPC::Message* msg) { if (!channel_.get()) { if (!is_initialized_) { diff --git a/content/browser/renderer_host/browser_render_process_host.h b/content/browser/renderer_host/browser_render_process_host.h index c41c489..880809d 100644 --- a/content/browser/renderer_host/browser_render_process_host.h +++ b/content/browser/renderer_host/browser_render_process_host.h @@ -61,6 +61,9 @@ class BrowserRenderProcessHost : public RenderProcessHost, virtual bool FastShutdownIfPossible(); virtual base::ProcessHandle GetHandle(); virtual TransportDIB* GetTransportDIB(TransportDIB::Id dib_id); + virtual void SetCompositingSurface( + int render_widget_id, + gfx::PluginWindowHandle compositing_surface); // IPC::Channel::Sender via RenderProcessHost. virtual bool Send(IPC::Message* msg); diff --git a/content/browser/renderer_host/gpu_message_filter.cc b/content/browser/renderer_host/gpu_message_filter.cc index ce028b6..600de33 100644 --- a/content/browser/renderer_host/gpu_message_filter.cc +++ b/content/browser/renderer_host/gpu_message_filter.cc @@ -10,11 +10,14 @@ #include "base/callback.h" #include "content/browser/gpu/gpu_process_host.h" +#include "content/browser/renderer_host/render_widget_helper.h" #include "content/common/gpu/gpu_messages.h" -GpuMessageFilter::GpuMessageFilter(int render_process_id) +GpuMessageFilter::GpuMessageFilter(int render_process_id, + RenderWidgetHelper* render_widget_helper) : gpu_host_id_(0), - render_process_id_(render_process_id) { + render_process_id_(render_process_id), + render_widget_helper_(render_widget_helper) { } // WeakPtrs to a GpuMessageFilter need to be Invalidated from @@ -153,12 +156,15 @@ void GpuMessageFilter::OnEstablishGpuChannel( } void GpuMessageFilter::OnCreateViewCommandBuffer( - gfx::PluginWindowHandle compositing_surface, int32 render_view_id, const GPUCreateCommandBufferConfig& init_params, IPC::Message* reply) { GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); - if (!host) { + + gfx::PluginWindowHandle compositing_surface = + render_widget_helper_->LookupCompositingSurface(render_view_id); + + if (!host || compositing_surface == gfx::kNullPluginWindow) { // TODO(apatrick): Eventually, this IPC message will be routed to a // GpuProcessStub with a particular routing ID. The error will be set if // the GpuProcessStub with that routing ID is not in the MessageRouter. diff --git a/content/browser/renderer_host/gpu_message_filter.h b/content/browser/renderer_host/gpu_message_filter.h index 7246f5a..d4e3651 100644 --- a/content/browser/renderer_host/gpu_message_filter.h +++ b/content/browser/renderer_host/gpu_message_filter.h @@ -6,6 +6,7 @@ #define CONTENT_BROWSER_RENDERER_HOST_GPU_MESSAGE_FILTER_H_ #pragma once +#include "base/memory/ref_counted.h" #include "content/browser/browser_message_filter.h" #include "content/common/gpu/gpu_process_launch_causes.h" #include "ui/gfx/native_widget_types.h" @@ -14,6 +15,7 @@ class GpuProcessHost; class GpuProcessHostUIShim; struct GPUCreateCommandBufferConfig; struct GPUInfo; +class RenderWidgetHelper; namespace IPC { struct ChannelHandle; @@ -25,7 +27,8 @@ struct ChannelHandle; class GpuMessageFilter : public BrowserMessageFilter, public base::SupportsWeakPtr<GpuMessageFilter> { public: - explicit GpuMessageFilter(int render_process_id); + GpuMessageFilter(int render_process_id, + RenderWidgetHelper* render_widget_helper); // BrowserMessageFilter methods: virtual bool OnMessageReceived(const IPC::Message& message, @@ -41,7 +44,6 @@ class GpuMessageFilter : public BrowserMessageFilter, void OnEstablishGpuChannel(content::CauseForGpuLaunch, IPC::Message* reply); void OnCreateViewCommandBuffer( - gfx::PluginWindowHandle compositing_surface, int32 render_view_id, const GPUCreateCommandBufferConfig& init_params, IPC::Message* reply); @@ -49,6 +51,8 @@ class GpuMessageFilter : public BrowserMessageFilter, int gpu_host_id_; int render_process_id_; + scoped_refptr<RenderWidgetHelper> render_widget_helper_; + DISALLOW_COPY_AND_ASSIGN(GpuMessageFilter); }; diff --git a/content/browser/renderer_host/mock_render_process_host.cc b/content/browser/renderer_host/mock_render_process_host.cc index 2cbfd89..4b27ce3 100644 --- a/content/browser/renderer_host/mock_render_process_host.cc +++ b/content/browser/renderer_host/mock_render_process_host.cc @@ -103,6 +103,11 @@ TransportDIB* MockRenderProcessHost::GetTransportDIB(TransportDIB::Id dib_id) { return transport_dib_; } +void MockRenderProcessHost::SetCompositingSurface( + int render_widget_id, + gfx::PluginWindowHandle compositing_surface) { +} + bool MockRenderProcessHost::OnMessageReceived(const IPC::Message& msg) { return false; } diff --git a/content/browser/renderer_host/mock_render_process_host.h b/content/browser/renderer_host/mock_render_process_host.h index e4ae3db..a785129 100644 --- a/content/browser/renderer_host/mock_render_process_host.h +++ b/content/browser/renderer_host/mock_render_process_host.h @@ -52,6 +52,9 @@ class MockRenderProcessHost : public RenderProcessHost { virtual bool FastShutdownIfPossible(); virtual base::ProcessHandle GetHandle(); virtual TransportDIB* GetTransportDIB(TransportDIB::Id dib_id); + virtual void SetCompositingSurface( + int render_widget_id, + gfx::PluginWindowHandle compositing_surface); // IPC::Channel::Sender via RenderProcessHost. virtual bool Send(IPC::Message* msg); diff --git a/content/browser/renderer_host/render_process_host.h b/content/browser/renderer_host/render_process_host.h index c5b45e0..5035cd4 100644 --- a/content/browser/renderer_host/render_process_host.h +++ b/content/browser/renderer_host/render_process_host.h @@ -14,6 +14,7 @@ #include "base/process_util.h" #include "base/time.h" #include "ipc/ipc_channel_proxy.h" +#include "ui/gfx/native_widget_types.h" #include "ui/gfx/surface/transport_dib.h" class Profile; @@ -226,6 +227,14 @@ class RenderProcessHost : public IPC::Channel::Sender, // still owns the returned DIB. virtual TransportDIB* GetTransportDIB(TransportDIB::Id dib_id) = 0; + // RenderWidgetHost / compositing surface mapping functions ------------------ + + // Set a mapping from a RenderWidgetHost to a compositing surface. Pass a null + // handle to remove the mapping. + virtual void SetCompositingSurface( + int render_widget_id, + gfx::PluginWindowHandle compositing_surface) = 0; + // Static management functions ----------------------------------------------- // Flag to run the renderer in process. This is primarily diff --git a/content/browser/renderer_host/render_view_host.cc b/content/browser/renderer_host/render_view_host.cc index 59d65e2..5030cc6 100644 --- a/content/browser/renderer_host/render_view_host.cc +++ b/content/browser/renderer_host/render_view_host.cc @@ -161,9 +161,11 @@ bool RenderViewHost::CreateRenderView(const string16& frame_name) { renderer_initialized_ = true; + process()->SetCompositingSurface(routing_id(), + GetCompositingSurface()); + 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_helper.cc b/content/browser/renderer_host/render_widget_helper.cc index f297110..cbfa094 100644 --- a/content/browser/renderer_host/render_widget_helper.cc +++ b/content/browser/renderer_host/render_widget_helper.cc @@ -333,3 +333,24 @@ void RenderWidgetHelper::ClearAllocatedDIBs() { allocated_dibs_.clear(); } #endif + +void RenderWidgetHelper::SetCompositingSurface( + int render_widget_id, + gfx::PluginWindowHandle compositing_surface) { + base::AutoLock locked(view_compositing_surface_map_lock_); + if (compositing_surface != gfx::kNullPluginWindow) + view_compositing_surface_map_[render_widget_id] = compositing_surface; + else + view_compositing_surface_map_.erase(render_widget_id); +} + +gfx::PluginWindowHandle RenderWidgetHelper::LookupCompositingSurface( + int render_widget_id) { + base::AutoLock locked(view_compositing_surface_map_lock_); + ViewCompositingSurfaceMap::iterator it = + view_compositing_surface_map_.find(render_widget_id); + if (it == view_compositing_surface_map_.end()) + return gfx::kNullPluginWindow; + + return it->second; +} diff --git a/content/browser/renderer_host/render_widget_helper.h b/content/browser/renderer_host/render_widget_helper.h index 0c7f695..cab0947 100644 --- a/content/browser/renderer_host/render_widget_helper.h +++ b/content/browser/renderer_host/render_widget_helper.h @@ -16,6 +16,7 @@ #include "base/synchronization/waitable_event.h" #include "content/common/window_container_type.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupType.h" +#include "ui/gfx/native_widget_types.h" #include "ui/gfx/surface/transport_dib.h" namespace IPC { @@ -117,6 +118,10 @@ class RenderWidgetHelper TransportDIB* MapTransportDIB(TransportDIB::Id dib_id); #endif + // Set a mapping from a RenderWidgetHost to a compositing surface. Pass a null + // handle to remove the mapping. + void SetCompositingSurface(int render_widget_id, + gfx::PluginWindowHandle compositing_surface); // IO THREAD ONLY ----------------------------------------------------------- @@ -145,6 +150,9 @@ class RenderWidgetHelper void FreeTransportDIB(TransportDIB::Id dib_id); #endif + // Lookup the compositing surface corresponding to a widget ID. + gfx::PluginWindowHandle LookupCompositingSurface(int render_widget_id); + private: // A class used to proxy a paint message. PaintMsgProxy objects are created // on the IO thread and destroyed on the UI thread. @@ -200,6 +208,11 @@ class RenderWidgetHelper UpdateMsgProxyMap pending_paints_; base::Lock pending_paints_lock_; + // Maps from view ID to compositing surface. + typedef std::map<int, gfx::PluginWindowHandle> ViewCompositingSurfaceMap; + ViewCompositingSurfaceMap view_compositing_surface_map_; + base::Lock view_compositing_surface_map_lock_; + int render_process_id_; // Event used to implement WaitForUpdateMsg. diff --git a/content/browser/renderer_host/render_widget_host.cc b/content/browser/renderer_host/render_widget_host.cc index b962f6e..4e01606 100644 --- a/content/browser/renderer_host/render_widget_host.cc +++ b/content/browser/renderer_host/render_widget_host.cc @@ -98,12 +98,21 @@ RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process, } RenderWidgetHost::~RenderWidgetHost() { + SetView(NULL); + // Clear our current or cached backing store if either remains. BackingStoreManager::RemoveBackingStore(this); process_->Release(routing_id_); } +void RenderWidgetHost::SetView(RenderWidgetHostView* view) { + view_ = view; + + if (!view_) + process_->SetCompositingSurface(routing_id_, gfx::kNullPluginWindow); +} + gfx::NativeViewId RenderWidgetHost::GetNativeViewId() { if (view_) return gfx::IdFromNativeView(view_->GetNativeView()); @@ -127,9 +136,11 @@ void RenderWidgetHost::Init() { renderer_initialized_ = true; + process_->SetCompositingSurface(routing_id_, + GetCompositingSurface()); + // Send the ack along with the information on placement. - Send(new ViewMsg_CreatingNew_ACK( - routing_id_, GetNativeViewId(), GetCompositingSurface())); + Send(new ViewMsg_CreatingNew_ACK(routing_id_, GetNativeViewId())); WasResized(); } @@ -363,7 +374,7 @@ void RenderWidgetHost::LostCapture() { void RenderWidgetHost::ViewDestroyed() { // TODO(evanm): tracking this may no longer be necessary; // eliminate this function if so. - view_ = NULL; + SetView(NULL); } void RenderWidgetHost::SetIsLoading(bool is_loading) { diff --git a/content/browser/renderer_host/render_widget_host.h b/content/browser/renderer_host/render_widget_host.h index 80f1bc4b..947ef2b 100644 --- a/content/browser/renderer_host/render_widget_host.h +++ b/content/browser/renderer_host/render_widget_host.h @@ -144,7 +144,7 @@ class RenderWidgetHost : public IPC::Channel::Listener, // RenderWidget is being destroyed or the render process crashed. You should // never cache this pointer since it can become NULL if the renderer crashes, // instead you should always ask for it using the accessor. - void set_view(RenderWidgetHostView* view) { view_ = view; } + void SetView(RenderWidgetHostView* view); RenderWidgetHostView* view() const { return view_; } RenderProcessHost* process() const { return process_; } diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc index 0018fe5..17c8108 100644 --- a/content/browser/renderer_host/render_widget_host_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_unittest.cc @@ -260,7 +260,7 @@ class RenderWidgetHostTest : public testing::Test { process_ = new RenderWidgetHostProcess(profile_.get()); host_.reset(new MockRenderWidgetHost(process_, 1)); view_.reset(new TestView(host_.get())); - host_->set_view(view_.get()); + host_->SetView(view_.get()); host_->Init(); } void TearDown() { @@ -416,13 +416,13 @@ TEST_F(RenderWidgetHostTest, ResizeThenCrash) { // Simulate a renderer crash before the update message. Ensure all the // resize ack logic is cleared. Must clear the view first so it doesn't get // deleted. - host_->set_view(NULL); + host_->SetView(NULL); host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1); EXPECT_FALSE(host_->resize_ack_pending_); EXPECT_EQ(gfx::Size(), host_->in_flight_size_); // Reset the view so we can exit the test cleanly. - host_->set_view(view_.get()); + host_->SetView(view_.get()); } // Tests setting custom background @@ -430,7 +430,7 @@ TEST_F(RenderWidgetHostTest, Background) { #if !defined(OS_MACOSX) scoped_ptr<RenderWidgetHostView> view( RenderWidgetHostView::CreateViewForWidget(host_.get())); - host_->set_view(view.get()); + host_->SetView(view.get()); // Create a checkerboard background to test with. gfx::CanvasSkia canvas(4, 4, true); diff --git a/content/browser/renderer_host/test_render_view_host.cc b/content/browser/renderer_host/test_render_view_host.cc index 6a6b512..00b29ac 100644 --- a/content/browser/renderer_host/test_render_view_host.cc +++ b/content/browser/renderer_host/test_render_view_host.cc @@ -51,7 +51,7 @@ TestRenderViewHost::TestRenderViewHost(SiteInstance* instance, // For normal RenderViewHosts, this is freed when |Shutdown()| is called. // For TestRenderViewHost, the view is explicitly deleted in the destructor // below, because TestRenderWidgetHostView::Destroy() doesn't |delete this|. - set_view(new TestRenderWidgetHostView(this)); + SetView(new TestRenderWidgetHostView(this)); } TestRenderViewHost::~TestRenderViewHost() { diff --git a/content/browser/tab_contents/interstitial_page.cc b/content/browser/tab_contents/interstitial_page.cc index 85edfb9..07c661b 100644 --- a/content/browser/tab_contents/interstitial_page.cc +++ b/content/browser/tab_contents/interstitial_page.cc @@ -426,7 +426,7 @@ TabContentsView* InterstitialPage::CreateTabContentsView() { TabContentsView* tab_contents_view = tab()->view(); RenderWidgetHostView* view = tab_contents_view->CreateViewForWidget(render_view_host_); - render_view_host_->set_view(view); + render_view_host_->SetView(view); render_view_host_->AllowBindings(BindingsPolicy::DOM_AUTOMATION); render_view_host_->CreateRenderView(string16()); diff --git a/content/browser/tab_contents/render_view_host_manager.cc b/content/browser/tab_contents/render_view_host_manager.cc index 48133e4..1a49d4d 100644 --- a/content/browser/tab_contents/render_view_host_manager.cc +++ b/content/browser/tab_contents/render_view_host_manager.cc @@ -814,7 +814,7 @@ void RenderViewHostManager::SwapInRenderViewHost(RenderViewHost* rvh) { // Remove old RenderWidgetHostView with mocked out methods so it can be // replaced with a new one that's a child of |delegate_|'s view. scoped_ptr<RenderWidgetHostView> old_view(render_view_host_->view()); - render_view_host_->set_view(NULL); + render_view_host_->SetView(NULL); delegate_->CreateViewAndSetSizeForRVH(render_view_host_); render_view_host_->ActivateDeferredPluginHandles(); // If the view is gone, then this RenderViewHost died while it was hidden. |