diff options
21 files changed, 868 insertions, 417 deletions
diff --git a/content/browser/gpu/gpu_process_host_ui_shim.cc b/content/browser/gpu/gpu_process_host_ui_shim.cc index 488aa9a..b11fdab 100644 --- a/content/browser/gpu/gpu_process_host_ui_shim.cc +++ b/content/browser/gpu/gpu_process_host_ui_shim.cc @@ -25,6 +25,7 @@ #include "ui/base/x/x11_util.h" #include "ui/gfx/size.h" #endif + namespace { // One of the linux specific headers defines this as a macro. @@ -159,20 +160,14 @@ bool GpuProcessHostUIShim::OnControlMessageReceived( IPC_MESSAGE_HANDLER(GpuHostMsg_ResizeView, OnResizeView) #endif -#if defined(OS_MACOSX) - IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceNew, - OnAcceleratedSurfaceNew) -#endif - #if defined(OS_MACOSX) || defined(TOUCH_UI) IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped, OnAcceleratedSurfaceBuffersSwapped) -#endif - -#if defined(TOUCH_UI) IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceNew, OnAcceleratedSurfaceNew) +#endif +#if defined(TOUCH_UI) IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceRelease, OnAcceleratedSurfaceRelease) #endif @@ -249,21 +244,43 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceNew( RenderWidgetHostView* view = host->view(); if (!view) return; + + uint64 surface_id = params.surface_id; + TransportDIB::Handle surface_handle = TransportDIB::DefaultHandleValue(); + #if defined(OS_MACOSX) - view->AcceleratedSurfaceSetIOSurface(params.window, - params.width, - params.height, - params.identifier); + if (params.create_transport_dib) { + scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); + if (shared_memory->CreateAnonymous(params.width * params.height * 4)) { + // Create a local handle for RWHVMac to map the SHM. + TransportDIB::Handle local_handle; + if (!shared_memory->ShareToProcess(0 /* pid, not needed */, + &local_handle)) { + local_handle = TransportDIB::DefaultHandleValue(); + } else { + view->AcceleratedSurfaceSetTransportDIB(params.window, + params.width, + params.height, + local_handle); + // Create a remote handle for the GPU process to map the SHM. + if (!shared_memory->ShareToProcess(0 /* pid, not needed */, + &surface_handle)) { + surface_handle = TransportDIB::DefaultHandleValue(); + } + } + } + } else { + view->AcceleratedSurfaceSetIOSurface(params.window, + params.width, + params.height, + surface_id); + } #elif defined(TOUCH_UI) - uint64 surface_id = params.identifier; - TransportDIB::Handle surface_handle; - view->AcceleratedSurfaceNew( params.width, params.height, &surface_id, &surface_handle); - +#endif Send(new AcceleratedSurfaceMsg_NewACK( params.route_id, surface_id, surface_handle)); -#endif } void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped( @@ -285,8 +302,7 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped( // Parameters needed to formulate an acknowledgment. params.renderer_id, params.route_id, - host_id_, - params.swap_buffers_count); + host_id_); #elif defined(TOUCH_UI) // view must send ACK message after next composite view->AcceleratedSurfaceBuffersSwapped( diff --git a/content/browser/renderer_host/render_widget_host_mac.cc b/content/browser/renderer_host/render_widget_host_mac.cc index 38a8fac..e264b93 100644 --- a/content/browser/renderer_host/render_widget_host_mac.cc +++ b/content/browser/renderer_host/render_widget_host_mac.cc @@ -65,6 +65,6 @@ void RenderWidgetHost::OnAcceleratedSurfaceBuffersSwapped( // updating of accelerated plugins as well. However, if we add support // for composited plugins then this is not necessary. view_->AcceleratedSurfaceBuffersSwapped(window, surface_id, - 0, 0, 0, 0); + 0, 0, 0); } } diff --git a/content/browser/renderer_host/render_widget_host_view.h b/content/browser/renderer_host/render_widget_host_view.h index 84fac90..3d302ed 100644 --- a/content/browser/renderer_host/render_widget_host_view.h +++ b/content/browser/renderer_host/render_widget_host_view.h @@ -255,18 +255,16 @@ class RenderWidgetHostView { int32 height, TransportDIB::Handle transport_dib) = 0; // |window| and |surface_id| indicate which accelerated surface's - // buffers swapped. |renderer_id|, |route_id| and - // |swap_buffers_count| are used to formulate a reply to the GPU - // process to prevent it from getting too far ahead. They may all be - // zero, in which case no flow control is enforced; this case is - // currently used for accelerated plugins. + // buffers swapped. |renderer_id| and |route_id| are used to formulate + // a reply to the GPU process to prevent it from getting too far ahead. + // They may all be zero, in which case no flow control is enforced; + // this case is currently used for accelerated plugins. virtual void AcceleratedSurfaceBuffersSwapped( gfx::PluginWindowHandle window, uint64 surface_id, int renderer_id, int32 route_id, - int gpu_host_id, - uint64 swap_buffers_count) = 0; + int gpu_host_id) = 0; virtual void GpuRenderingStateDidChange() = 0; #endif diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 92e48c0..9cf7720 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h @@ -266,8 +266,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { uint64 surface_id, int renderer_id, int32 route_id, - int gpu_host_id, - uint64 swap_buffers_count) OVERRIDE; + int gpu_host_id) OVERRIDE; virtual void GpuRenderingStateDidChange() OVERRIDE; virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE; virtual gfx::Rect GetRootWindowBounds() OVERRIDE; @@ -317,8 +316,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { // process a notion of how quickly the browser is able to keep up with it. void AcknowledgeSwapBuffers(int renderer_id, int32 route_id, - int gpu_host_id, - uint64 swap_buffers_count); + int gpu_host_id); // These member variables should be private, but the associated ObjC class // needs access to them and can't be made a friend. @@ -362,6 +360,12 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { AcceleratedSurfaceContainerManagerMac plugin_container_manager_; private: + // If the window is at the root of the plugin container hierachy, + // we need to update the geometry manually. + void UpdatePluginGeometry(gfx::PluginWindowHandle window, + int32 width, + int32 height); + // Returns whether this render view is a popup (autocomplete window). bool IsPopup() const; diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 8f720a3..6b5ed4e 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm @@ -811,17 +811,10 @@ AcceleratedPluginView* RenderWidgetHostViewMac::ViewForPluginWindowHandle( return it->second; } -void RenderWidgetHostViewMac::AcceleratedSurfaceSetIOSurface( +void RenderWidgetHostViewMac::UpdatePluginGeometry( gfx::PluginWindowHandle window, int32 width, - int32 height, - uint64 io_surface_identifier) { - CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - plugin_container_manager_.SetSizeAndIOSurface(window, - width, - height, - io_surface_identifier); - + int32 height) { if (plugin_container_manager_.IsRootContainer(window)) { // Fake up a WebPluginGeometry for the root window to set the // container's size; we will never get a notification from the @@ -837,6 +830,19 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceSetIOSurface( } } +void RenderWidgetHostViewMac::AcceleratedSurfaceSetIOSurface( + gfx::PluginWindowHandle window, + int32 width, + int32 height, + uint64 io_surface_identifier) { + CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + plugin_container_manager_.SetSizeAndIOSurface(window, + width, + height, + io_surface_identifier); + UpdatePluginGeometry(window, width, height); +} + void RenderWidgetHostViewMac::AcceleratedSurfaceSetTransportDIB( gfx::PluginWindowHandle window, int32 width, @@ -847,6 +853,7 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceSetTransportDIB( width, height, transport_dib); + UpdatePluginGeometry(window, width, height); } void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( @@ -854,11 +861,9 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( uint64 surface_id, int renderer_id, int32 route_id, - int gpu_host_id, - uint64 swap_buffers_count) { - TRACE_EVENT1("browser", - "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped", - "frameNum", swap_buffers_count); + int gpu_host_id) { + TRACE_EVENT0("browser", + "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped"); CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); AcceleratedPluginView* view = ViewForPluginWindowHandle(window); DCHECK(view); @@ -874,8 +879,7 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( if (renderer_id != 0 || route_id != 0) { AcknowledgeSwapBuffers(renderer_id, route_id, - gpu_host_id, - swap_buffers_count); + gpu_host_id); } } @@ -911,10 +915,8 @@ void RenderWidgetHostViewMac::HandleDelayedGpuViewHiding() { void RenderWidgetHostViewMac::AcknowledgeSwapBuffers( int renderer_id, int32 route_id, - int gpu_host_id, - uint64 swap_buffers_count) { - TRACE_EVENT1("gpu", "RenderWidgetHostViewMac::AcknowledgeSwapBuffers", - "swap_buffers_count", swap_buffers_count); + int gpu_host_id) { + TRACE_EVENT0("gpu", "RenderWidgetHostViewMac::AcknowledgeSwapBuffers"); // Called on the display link thread. Hand actual work off to the IO thread, // because |GpuProcessHost::Get()| can only be called there. // Currently, this is never called for plugins. @@ -937,16 +939,13 @@ void RenderWidgetHostViewMac::AcknowledgeSwapBuffers( FROM_HERE, NewRunnableFunction(&GpuProcessHostUIShim::SendToGpuHost, gpu_host_id, - new GpuMsg_AcceleratedSurfaceBuffersSwappedACK( - renderer_id, - route_id, - swap_buffers_count))); + new AcceleratedSurfaceMsg_BuffersSwappedACK( + route_id))); } else { GpuProcessHost::SendOnIO( gpu_host_id, content::CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, - new GpuMsg_AcceleratedSurfaceBuffersSwappedACK( - renderer_id, route_id, swap_buffers_count)); + new AcceleratedSurfaceMsg_BuffersSwappedACK(route_id)); } } diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm index 43e5300..c09939f 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm @@ -55,7 +55,7 @@ class RenderWidgetHostViewMacTest : public RenderViewHostTestHarness { // The accelerated view isn't shown until it has a valid rect and has been // painted to. rwhv_mac_->AcceleratedSurfaceBuffersSwapped(accelerated_handle, - 0, 0, 0, 0, 0); + 0, 0, 0, 0); webkit::npapi::WebPluginGeometry geom; gfx::Rect rect(0, 0, w, h); geom.window = accelerated_handle; diff --git a/content/browser/renderer_host/test_render_view_host.cc b/content/browser/renderer_host/test_render_view_host.cc index e15018e..d64c046 100644 --- a/content/browser/renderer_host/test_render_view_host.cc +++ b/content/browser/renderer_host/test_render_view_host.cc @@ -227,8 +227,7 @@ void TestRenderWidgetHostView::AcceleratedSurfaceBuffersSwapped( uint64 surface_id, int renderer_id, int32 route_id, - int gpu_host_id, - uint64 swap_buffers_count) { + int gpu_host_id) { } void TestRenderWidgetHostView::GpuRenderingStateDidChange() { diff --git a/content/browser/renderer_host/test_render_view_host.h b/content/browser/renderer_host/test_render_view_host.h index d372a14..6ca1ba8 100644 --- a/content/browser/renderer_host/test_render_view_host.h +++ b/content/browser/renderer_host/test_render_view_host.h @@ -118,8 +118,7 @@ class TestRenderWidgetHostView : public RenderWidgetHostView { uint64 surface_id, int renderer_id, int32 route_id, - int gpu_host_id, - uint64 swap_buffers_count) OVERRIDE; + int gpu_host_id) OVERRIDE; virtual void GpuRenderingStateDidChange() OVERRIDE; #elif defined(OS_WIN) virtual void WillWmDestroy() OVERRIDE; diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc index 75836e2..6b426f2 100644 --- a/content/browser/tab_contents/tab_contents.cc +++ b/content/browser/tab_contents/tab_contents.cc @@ -1835,13 +1835,6 @@ WebPreferences TabContents::GetWebkitPrefs() { web_prefs.accelerated_2d_canvas_enabled = false; } -#if defined(OS_MACOSX) - // Disable accelerated compositing if IOSurface's are not supported, - // as is the case in 10.5. - if (!IOSurfaceSupport::Initialize()) - web_prefs.accelerated_compositing_enabled = false; -#endif - #if defined(TOUCH_UI) web_prefs.force_compositing_mode = true; #endif diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc index 3434c74..89f775d 100644 --- a/content/common/gpu/gpu_channel.cc +++ b/content/common/gpu/gpu_channel.cc @@ -223,14 +223,6 @@ GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32 route_id) { } #if defined(OS_MACOSX) -void GpuChannel::AcceleratedSurfaceBuffersSwapped( - int32 route_id, uint64 swap_buffers_count) { - GpuCommandBufferStub* stub = stubs_.Lookup(route_id); - if (stub == NULL) - return; - stub->AcceleratedSurfaceBuffersSwapped(swap_buffers_count); -} - void GpuChannel::DestroyCommandBufferByViewId(int32 render_view_id) { // This responds to a message from the browser process to destroy the command // buffer when the window with a GpuScheduler is closed (see diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h index e02c2d8..242b746 100644 --- a/content/common/gpu/gpu_channel.h +++ b/content/common/gpu/gpu_channel.h @@ -99,8 +99,6 @@ class GpuChannel : public IPC::Channel::Listener, GpuCommandBufferStub* LookupCommandBuffer(int32 route_id); #if defined(OS_MACOSX) - virtual void AcceleratedSurfaceBuffersSwapped( - int32 route_id, uint64 swap_buffers_count); void DestroyCommandBufferByViewId(int32 render_view_id); #endif diff --git a/content/common/gpu/gpu_channel_manager.cc b/content/common/gpu/gpu_channel_manager.cc index 5d3aba8..491fdd6b 100644 --- a/content/common/gpu/gpu_channel_manager.cc +++ b/content/common/gpu/gpu_channel_manager.cc @@ -65,8 +65,6 @@ bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(GpuMsg_ResizeViewACK, OnResizeViewACK); #endif #if defined(OS_MACOSX) - IPC_MESSAGE_HANDLER(GpuMsg_AcceleratedSurfaceBuffersSwappedACK, - OnAcceleratedSurfaceBuffersSwappedACK) IPC_MESSAGE_HANDLER(GpuMsg_DestroyCommandBuffer, OnDestroyCommandBuffer) #endif @@ -154,15 +152,6 @@ void GpuChannelManager::OnResizeViewACK(int32 renderer_id, } #if defined(OS_MACOSX) -void GpuChannelManager::OnAcceleratedSurfaceBuffersSwappedACK( - int renderer_id, int32 route_id, uint64 swap_buffers_count) { - GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); - if (iter == gpu_channels_.end()) - return; - scoped_refptr<GpuChannel> channel = iter->second; - channel->AcceleratedSurfaceBuffersSwapped(route_id, swap_buffers_count); -} - void GpuChannelManager::OnDestroyCommandBuffer( int renderer_id, int32 renderer_view_id) { GpuChannelMap::const_iterator iter = gpu_channels_.find(renderer_id); diff --git a/content/common/gpu/gpu_channel_manager.h b/content/common/gpu/gpu_channel_manager.h index e650a9c..517f02b 100644 --- a/content/common/gpu/gpu_channel_manager.h +++ b/content/common/gpu/gpu_channel_manager.h @@ -79,8 +79,6 @@ class GpuChannelManager : public IPC::Channel::Listener, void OnResizeViewACK(int32 renderer_id, int32 command_buffer_route_id); #if defined(OS_MACOSX) - void OnAcceleratedSurfaceBuffersSwappedACK( - int renderer_id, int32 route_id, uint64 swap_buffers_count); void OnDestroyCommandBuffer(int renderer_id, int32 renderer_view_id); #endif diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index 57a076e..a15dd3a 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 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. @@ -17,8 +17,8 @@ #include "gpu/command_buffer/common/constants.h" #include "ui/gfx/gl/gl_switches.h" -#if defined(TOUCH_UI) -#include "content/common/gpu/image_transport_surface_linux.h" +#if defined(OS_MACOSX) || defined(TOUCH_UI) +#include "content/common/gpu/image_transport_surface.h" #endif GpuCommandBufferStub::GpuCommandBufferStub( @@ -48,10 +48,6 @@ GpuCommandBufferStub::GpuCommandBufferStub( parent_stub_for_initialization_(), parent_texture_for_initialization_(0), watchdog_(watchdog), -#if defined(OS_MACOSX) - swap_buffers_count_(0), - acknowledged_swap_buffers_count_(0), -#endif task_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { if (share_group) { context_group_ = share_group->context_group_; @@ -124,21 +120,6 @@ bool GpuCommandBufferStub::IsScheduled() { return !scheduler_.get() || scheduler_->IsScheduled(); } -#if defined(OS_MACOSX) - -TransportDIB::Handle GpuCommandBufferStub::SetWindowSizeForTransportDIB( - const gfx::Size& size) { - return accelerated_surface_->SetTransportDIBSize(size); -} - -void GpuCommandBufferStub::SetTransportDIBAllocAndFree( - Callback2<size_t, TransportDIB::Handle*>::Type* allocator, - Callback1<TransportDIB::Id>::Type* deallocator) { - accelerated_surface_->SetTransportDIBAllocAndFree(allocator, deallocator); -} - -#endif // OS_MACOSX - void GpuCommandBufferStub::Destroy() { // The scheduler has raw references to the decoder and the command buffer so // destroy it before those. @@ -153,10 +134,6 @@ void GpuCommandBufferStub::Destroy() { context_ = NULL; surface_ = NULL; - -#if defined(OS_MACOSX) - accelerated_surface_.reset(); -#endif } void GpuCommandBufferStub::OnInitializeFailed(IPC::Message* reply_message) { @@ -199,7 +176,7 @@ void GpuCommandBufferStub::OnInitialize( decoder_->set_engine(scheduler_.get()); if (handle_) { -#if defined(TOUCH_UI) +#if defined(TOUCH_UI) || defined(OS_MACOSX) if (software_) { OnInitializeFailed(reply_message); return; @@ -209,12 +186,10 @@ void GpuCommandBufferStub::OnInitialize( channel_->gpu_channel_manager(), render_view_id_, renderer_id_, - route_id_); + route_id_, + handle_); #elif defined(OS_WIN) || defined(OS_LINUX) surface_ = gfx::GLSurface::CreateViewGLSurface(software_, handle_); -#elif defined(OS_MACOSX) - surface_ = gfx::GLSurface::CreateOffscreenGLSurface(software_, - gfx::Size(1, 1)); #endif } else { surface_ = gfx::GLSurface::CreateOffscreenGLSurface(software_, @@ -235,27 +210,6 @@ void GpuCommandBufferStub::OnInitialize( return; } -#if defined(OS_MACOSX) - // On Mac OS X since we can not render on-screen we don't even - // attempt to create a view based GLContext. The only difference - // between "on-screen" and "off-screen" rendering on this platform - // is whether we allocate an AcceleratedSurface, which transmits the - // rendering results back to the browser. - if (handle_) { - accelerated_surface_.reset(new AcceleratedSurface()); - - // Note that although the GLContext is passed to Initialize and the - // GLContext will later be owned by the decoder, AcceleratedSurface does - // not hold on to the reference. It simply extracts the underlying GL - // context in order to share the namespace with another context. - if (!accelerated_surface_->Initialize(context_.get(), false)) { - LOG(ERROR) << "Failed to initialize AcceleratedSurface."; - OnInitializeFailed(reply_message); - return; - } - } -#endif - // Initialize the decoder with either the view or pbuffer GLContext. if (!decoder_->Initialize(surface_.get(), context_.get(), @@ -281,15 +235,10 @@ void GpuCommandBufferStub::OnInitialize( scheduler_->SetScheduledCallback( NewCallback(channel_, &GpuChannel::OnScheduled)); -#if defined(OS_MACOSX) - decoder_->SetSwapBuffersCallback( - NewCallback(this, &GpuCommandBufferStub::OnSwapBuffers)); -#endif - - // On TOUCH_UI, the ImageTransportSurface handles co-ordinating the - // resize with the browser process. The ImageTransportSurface sets it's - // own resize callback, so we shouldn't do it here. -#if !defined(TOUCH_UI) + // On platforms that use an ImageTransportSurface, the surface + // handles co-ordinating the resize with the browser process. The + // surface sets it's own resize callback, so we shouldn't do it here. +#if !defined(TOUCH_UI) && !defined(OS_MACOSX) if (handle_ != gfx::kNullPluginWindow) { decoder_->SetResizeCallback( NewCallback(this, &GpuCommandBufferStub::OnResize)); @@ -490,100 +439,16 @@ void GpuCommandBufferStub::OnGetTransferBuffer( Send(reply_message); } -#if defined(OS_MACOSX) -void GpuCommandBufferStub::OnSwapBuffers() { - TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSwapBuffers"); - - DCHECK(decoder_.get()); - DCHECK(decoder_->GetGLContext()); - DCHECK(decoder_->GetGLContext()->IsCurrent(decoder_->GetGLSurface())); - - ++swap_buffers_count_; - - if (accelerated_surface_.get()) { - accelerated_surface_->SwapBuffers(); - } - - if (handle_) { - // To swap on OSX, we have to send a message to the browser to get the - // context put onscreen. - GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); - GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; - params.renderer_id = renderer_id_; - params.render_view_id = render_view_id_; - params.window = handle_; - params.surface_id = GetSurfaceId(); - params.route_id = route_id(); - params.swap_buffers_count = swap_buffers_count_; - gpu_channel_manager->Send( - new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params)); - scheduler_->SetScheduled(false); - } -} - -uint64 GpuCommandBufferStub::GetSurfaceId() { - if (!accelerated_surface_.get()) - return 0; - return accelerated_surface_->GetSurfaceId(); -} -#endif - void GpuCommandBufferStub::OnCommandProcessed() { if (watchdog_) watchdog_->CheckArmed(); } -#if defined(OS_MACOSX) -void GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped( - uint64 swap_buffers_count) { - TRACE_EVENT1("gpu", - "GpuCommandBufferStub::AcceleratedSurfaceBuffersSwapped", - "frame", swap_buffers_count); - DCHECK(handle_ != gfx::kNullPluginWindow); - - // Multiple swapbuffers may get consolidated together into a single - // AcceleratedSurfaceBuffersSwapped call. Upstream code listening to the - // GpuCommandBufferMsg_SwapBuffers expects to be called one time for every - // swap. So, send one SwapBuffers message for every outstanding swap. - uint64 delta = swap_buffers_count - acknowledged_swap_buffers_count_; - acknowledged_swap_buffers_count_ = swap_buffers_count; - - for(uint64 i = 0; i < delta; i++) { - // Wake up the GpuScheduler to start doing work again. When the scheduler - // wakes up, it will send any deferred echo acknowledgements, triggering - // associated swapbuffer callbacks. - scheduler_->SetScheduled(true); - } -} -#endif // defined(OS_MACOSX) - void GpuCommandBufferStub::OnResize(gfx::Size size) { if (handle_ == gfx::kNullPluginWindow) return; -#if defined(OS_MACOSX) - GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); - - // On Mac, we need to tell the browser about the new IOSurface handle, - // asynchronously. - uint64 new_backing_store = accelerated_surface_->SetSurfaceSize(size); - if (new_backing_store) { - GpuHostMsg_AcceleratedSurfaceNew_Params params; - params.renderer_id = renderer_id_; - params.render_view_id = render_view_id_; - params.window = handle_; - params.width = size.width(); - params.height = size.height(); - params.identifier = new_backing_store; - gpu_channel_manager->Send( - new GpuHostMsg_AcceleratedSurfaceNew(params)); - } else { - // TODO(kbr): figure out what to do here. It wouldn't be difficult - // to support the compositor on 10.5, but the performance would be - // questionable. - NOTREACHED(); - } -#elif defined(TOOLKIT_USES_GTK) && !defined(TOUCH_UI) || defined(OS_WIN) +#if defined(TOOLKIT_USES_GTK) && !defined(TOUCH_UI) || defined(OS_WIN) GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager(); // On Windows, Linux, we need to coordinate resizing of onscreen @@ -598,7 +463,7 @@ void GpuCommandBufferStub::OnResize(gfx::Size size) { size)); scheduler_->SetScheduled(false); -#endif // defined(OS_MACOSX) +#endif // defined(TOOLKIT_USES_GTK) && !defined(TOUCH_UI) || defined(OS_WIN) } void GpuCommandBufferStub::ViewResized() { diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h index 900e41f..d9d65a3 100644 --- a/content/common/gpu/gpu_command_buffer_stub.h +++ b/content/common/gpu/gpu_command_buffer_stub.h @@ -78,23 +78,6 @@ class GpuCommandBufferStub void ViewResized(); -#if defined(OS_MACOSX) - // Called only by the GpuChannel. - void AcceleratedSurfaceBuffersSwapped(uint64 swap_buffers_count); - - // Needed only on Mac OS X, which does not render into an on-screen - // window and therefore requires the backing store to be resized - // manually. Returns an opaque identifier for the new backing store. - // There are two versions of this method: one for use with the IOSurface - // available in Mac OS X 10.6; and, one for use with the - // TransportDIB-based version used on Mac OS X 10.5. - virtual TransportDIB::Handle SetWindowSizeForTransportDIB( - const gfx::Size& size); - virtual void SetTransportDIBAllocAndFree( - Callback2<size_t, TransportDIB::Handle*>::Type* allocator, - Callback1<TransportDIB::Id>::Type* deallocator); -#endif - private: void Destroy(); @@ -184,19 +167,6 @@ class GpuCommandBufferStub // decoder_route_id. IDMap<GpuVideoDecodeAccelerator, IDMapOwnPointer> video_decoders_; -#if defined(OS_MACOSX) - // To prevent the GPU process from overloading the browser process, - // we need to track the number of swap buffers calls issued and - // acknowledged per on-screen context, and keep the GPU from getting - // too far ahead of the browser. Note that this - // is also predicated on a flow control mechanism between the - // renderer and GPU processes. - uint64 swap_buffers_count_; - uint64 acknowledged_swap_buffers_count_; - scoped_ptr<AcceleratedSurface> accelerated_surface_; - scoped_ptr<Callback0::Type> wrapped_swap_buffers_callback_; -#endif - ScopedRunnableMethodFactory<GpuCommandBufferStub> task_factory_; DISALLOW_COPY_AND_ASSIGN(GpuCommandBufferStub); diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index a6b96e4..f884f29 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -20,6 +20,7 @@ #include "media/video/video_decode_accelerator.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/size.h" +#include "ui/gfx/surface/transport_dib.h" #define IPC_MESSAGE_START GpuMsgStart @@ -37,7 +38,9 @@ IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceNew_Params) IPC_STRUCT_MEMBER(gfx::PluginWindowHandle, window) IPC_STRUCT_MEMBER(int32, width) IPC_STRUCT_MEMBER(int32, height) - IPC_STRUCT_MEMBER(uint64, identifier) + IPC_STRUCT_MEMBER(uint64, surface_id) + IPC_STRUCT_MEMBER(bool, create_transport_dib) + IPC_STRUCT_MEMBER(int32, route_id) IPC_STRUCT_END() IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params) @@ -46,7 +49,14 @@ IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params) IPC_STRUCT_MEMBER(gfx::PluginWindowHandle, window) IPC_STRUCT_MEMBER(uint64, surface_id) IPC_STRUCT_MEMBER(int32, route_id) - IPC_STRUCT_MEMBER(uint64, swap_buffers_count) +IPC_STRUCT_END() + +IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceRelease_Params) + IPC_STRUCT_MEMBER(int32, renderer_id) + IPC_STRUCT_MEMBER(int32, render_view_id) + IPC_STRUCT_MEMBER(gfx::PluginWindowHandle, window) + IPC_STRUCT_MEMBER(uint64, identifier) + IPC_STRUCT_MEMBER(int32, route_id) IPC_STRUCT_END() #endif @@ -56,7 +66,7 @@ IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceNew_Params) IPC_STRUCT_MEMBER(int32, render_view_id) IPC_STRUCT_MEMBER(int32, width) IPC_STRUCT_MEMBER(int32, height) - IPC_STRUCT_MEMBER(uint64, identifier) + IPC_STRUCT_MEMBER(uint64, surface_id) IPC_STRUCT_MEMBER(int32, route_id) IPC_STRUCT_END() @@ -65,7 +75,6 @@ IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params) IPC_STRUCT_MEMBER(int32, render_view_id) IPC_STRUCT_MEMBER(uint64, surface_id) IPC_STRUCT_MEMBER(int32, route_id) - IPC_STRUCT_MEMBER(uint64, swap_buffers_count) IPC_STRUCT_END() IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceRelease_Params) @@ -156,7 +165,7 @@ IPC_MESSAGE_CONTROL2(GpuMsg_ResizeViewACK, int32 /* command_buffer_id */) #endif -#if defined(TOUCH_UI) +#if defined(OS_MACOSX) || defined(TOUCH_UI) // Tells the GPU process that it's safe to start rendering to the surface. IPC_MESSAGE_ROUTED2(AcceleratedSurfaceMsg_NewACK, uint64 /* surface_id */, @@ -168,16 +177,6 @@ IPC_MESSAGE_ROUTED0(AcceleratedSurfaceMsg_BuffersSwappedACK) #endif #if defined(OS_MACOSX) -// Tells the GPU process that the browser process handled the swap -// buffers request with the given number. Note that it is possible -// for the browser process to coalesce frames; it is not guaranteed -// that every GpuHostMsg_AcceleratedSurfaceBuffersSwapped message -// will result in a buffer swap on the browser side. -IPC_MESSAGE_CONTROL3(GpuMsg_AcceleratedSurfaceBuffersSwappedACK, - int /* renderer_id */, - int32 /* route_id */, - uint64 /* swap_buffers_count */) - // Requests the GPU process to destroy the command buffer and remove the // associated route. Further messages to this command buffer will result in a // channel error. @@ -263,9 +262,7 @@ IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceNew, // should cause the browser to redraw the compositor's contents. IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceBuffersSwapped, GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params) -#endif -#if defined(TOUCH_UI) // Tells the browser to release whatever resources are associated with // the given surface. The browser must send an ACK once this operation // is complete. diff --git a/content/common/gpu/image_transport_surface.cc b/content/common/gpu/image_transport_surface.cc new file mode 100644 index 0000000..8d4c076 --- /dev/null +++ b/content/common/gpu/image_transport_surface.cc @@ -0,0 +1,148 @@ +// 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. + +#if defined(ENABLE_GPU) + +#include "content/common/gpu/image_transport_surface.h" + +#include "base/callback.h" +#include "content/common/gpu/gpu_channel.h" +#include "content/common/gpu/gpu_channel_manager.h" +#include "content/common/gpu/gpu_command_buffer_stub.h" +#include "content/common/gpu/gpu_messages.h" +#include "gpu/command_buffer/service/gpu_scheduler.h" + +ImageTransportHelper::ImageTransportHelper(ImageTransportSurface* surface, + GpuChannelManager* manager, + int32 render_view_id, + int32 renderer_id, + int32 command_buffer_id, + gfx::PluginWindowHandle handle) + : surface_(surface), + manager_(manager), + render_view_id_(render_view_id), + renderer_id_(renderer_id), + command_buffer_id_(command_buffer_id), + handle_(handle) { + route_id_ = manager_->GenerateRouteID(); + manager_->AddRoute(route_id_, this); +} + +ImageTransportHelper::~ImageTransportHelper() { + manager_->RemoveRoute(route_id_); +} + +bool ImageTransportHelper::Initialize() { + gpu::gles2::GLES2Decoder* decoder = Decoder(); + + if (!decoder) + return false; + + decoder->SetResizeCallback( + NewCallback(this, &ImageTransportHelper::Resize)); + + return true; +} + +void ImageTransportHelper::Destroy() { +} + +bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message) + IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BuffersSwappedACK, + OnBuffersSwappedACK) + IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_NewACK, + OnNewSurfaceACK) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void ImageTransportHelper::SendAcceleratedSurfaceRelease( + GpuHostMsg_AcceleratedSurfaceRelease_Params params) { + params.renderer_id = renderer_id_; + params.render_view_id = render_view_id_; + params.route_id = route_id_; + manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params)); +} + +void ImageTransportHelper::SendAcceleratedSurfaceNew( + GpuHostMsg_AcceleratedSurfaceNew_Params params) { + params.renderer_id = renderer_id_; + params.render_view_id = render_view_id_; + params.route_id = route_id_; +#if defined(OS_MACOSX) + params.window = handle_; +#endif + manager_->Send(new GpuHostMsg_AcceleratedSurfaceNew(params)); +} + +void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped( + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params) { + params.renderer_id = renderer_id_; + params.render_view_id = render_view_id_; + params.route_id = route_id_; +#if defined(OS_MACOSX) + params.window = handle_; +#endif + manager_->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params)); +} + +void ImageTransportHelper::SetScheduled(bool is_scheduled) { + gpu::GpuScheduler* scheduler = Scheduler(); + if (!scheduler) + return; + + scheduler->SetScheduled(is_scheduled); +} + +void ImageTransportHelper::OnBuffersSwappedACK() { + surface_->OnBuffersSwappedACK(); +} + +void ImageTransportHelper::OnNewSurfaceACK( + uint64 surface_id, + TransportDIB::Handle shm_handle) { + surface_->OnNewSurfaceACK(surface_id, shm_handle); +} + +void ImageTransportHelper::Resize(gfx::Size size) { + surface_->OnResize(size); +} + +bool ImageTransportHelper::MakeCurrent() { + gpu::gles2::GLES2Decoder* decoder = Decoder(); + if (!decoder) + return false; + return decoder->MakeCurrent(); +} + +gpu::GpuScheduler* ImageTransportHelper::Scheduler() { + GpuChannel* channel = manager_->LookupChannel(renderer_id_); + if (!channel) + return NULL; + + GpuCommandBufferStub* stub = + channel->LookupCommandBuffer(command_buffer_id_); + if (!stub) + return NULL; + + return stub->scheduler(); +} + +gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() { + GpuChannel* channel = manager_->LookupChannel(renderer_id_); + if (!channel) + return NULL; + + GpuCommandBufferStub* stub = + channel->LookupCommandBuffer(command_buffer_id_); + if (!stub) + return NULL; + + return stub->decoder(); +} + +#endif // defined(ENABLE_GPU) diff --git a/content/common/gpu/image_transport_surface.h b/content/common/gpu/image_transport_surface.h new file mode 100644 index 0000000..044d8c3 --- /dev/null +++ b/content/common/gpu/image_transport_surface.h @@ -0,0 +1,123 @@ +// 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. + +#ifndef CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_H_ +#define CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_H_ +#pragma once + +#if defined(ENABLE_GPU) + +#include "base/memory/ref_counted.h" +#include "ipc/ipc_channel.h" +#include "ipc/ipc_message.h" +#include "ui/gfx/size.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gfx/surface/transport_dib.h" + +class GpuChannelManager; + +struct GpuHostMsg_AcceleratedSurfaceNew_Params; +struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params; +struct GpuHostMsg_AcceleratedSurfaceRelease_Params; + +namespace gfx { +class GLSurface; +} + +namespace gpu { +class GpuScheduler; + +namespace gles2 { +class GLES2Decoder; +} +} + +// The GPU process is agnostic as to how it displays results. On some platforms +// it renders directly to window. On others it renders offscreen and transports +// the results to the browser process to display. This file provides a simple +// framework for making the offscreen path seem more like the onscreen path. +// +// The ImageTransportSurface class defines an simple interface for events that +// should be responded to. The factory returns an offscreen surface that looks +// a lot like an onscreen surface to the GPU process. +// +// The ImageTransportSurfaceHelper provides some glue to the outside world: +// making sure outside events reach the ImageTransportSurface and +// allowing the ImageTransportSurface to send events to the outside world. + +class ImageTransportSurface { + public: + virtual void OnNewSurfaceACK( + uint64 surface_id, TransportDIB::Handle surface_handle) = 0; + virtual void OnBuffersSwappedACK() = 0; + virtual void OnResize(gfx::Size size) = 0; + + // Creates the appropriate surface depending on the GL implementation. + static scoped_refptr<gfx::GLSurface> + CreateSurface(GpuChannelManager* manager, + int32 render_view_id, + int32 renderer_id, + int32 command_buffer_id, + gfx::PluginWindowHandle handle); +}; + +class ImageTransportHelper : public IPC::Channel::Listener { + public: + // Takes weak pointers to objects that outlive the helper. + ImageTransportHelper(ImageTransportSurface* surface, + GpuChannelManager* manager, + int32 render_view_id, + int32 renderer_id, + int32 command_buffer_id, + gfx::PluginWindowHandle handle); + virtual ~ImageTransportHelper(); + + bool Initialize(); + void Destroy(); + + // IPC::Channel::Listener implementation: + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + + // Helper send functions. Caller fills in the surface specific params + // like size and surface id. The helper fills in the rest. + void SendAcceleratedSurfaceNew( + GpuHostMsg_AcceleratedSurfaceNew_Params params); + void SendAcceleratedSurfaceBuffersSwapped( + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params); + void SendAcceleratedSurfaceRelease( + GpuHostMsg_AcceleratedSurfaceRelease_Params params); + + // Whether or not we should execute more commands. + void SetScheduled(bool is_scheduled); + + // Make the surface's context current. + bool MakeCurrent(); + + private: + gpu::GpuScheduler* Scheduler(); + gpu::gles2::GLES2Decoder* Decoder(); + + // IPC::Message handlers. + void OnNewSurfaceACK(uint64 surface_id, TransportDIB::Handle surface_handle); + void OnBuffersSwappedACK(); + + // Backbuffer resize callback. + void Resize(gfx::Size size); + + // Weak pointers that point to objects that outlive this helper. + ImageTransportSurface* surface_; + GpuChannelManager* manager_; + + int32 render_view_id_; + int32 renderer_id_; + int32 command_buffer_id_; + int32 route_id_; + gfx::PluginWindowHandle handle_; + + DISALLOW_COPY_AND_ASSIGN(ImageTransportHelper); +}; + +#endif // defined(ENABLE_GPU) + +#endif // CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_H_ diff --git a/content/common/gpu/image_transport_surface_linux.cc b/content/common/gpu/image_transport_surface_linux.cc index e7f304d..3389160 100644 --- a/content/common/gpu/image_transport_surface_linux.cc +++ b/content/common/gpu/image_transport_surface_linux.cc @@ -4,7 +4,7 @@ #if defined(ENABLE_GPU) -#include "content/common/gpu/image_transport_surface_linux.h" +#include "content/common/gpu/image_transport_surface.h" // This conflicts with the defines in Xlib.h and must come first. #include "content/common/gpu/gpu_messages.h" @@ -167,7 +167,8 @@ EGLImageTransportSurface::EGLImageTransportSurface( manager, render_view_id, renderer_id, - command_buffer_id)); + command_buffer_id, + gfx::kNullPluginWindow)); } EGLImageTransportSurface::~EGLImageTransportSurface() { @@ -239,7 +240,7 @@ void EGLImageTransportSurface::OnResize(gfx::Size size) { GpuHostMsg_AcceleratedSurfaceNew_Params params; params.width = size.width(); params.height = size.height(); - params.identifier = back_surface_->pixmap(); + params.surface_id = back_surface_->pixmap(); helper_->SendAcceleratedSurfaceNew(params); helper_->SetScheduled(false); @@ -296,7 +297,8 @@ GLXImageTransportSurface::GLXImageTransportSurface( manager, render_view_id, renderer_id, - command_buffer_id)); + command_buffer_id, + gfx::kNullPluginWindow)); } GLXImageTransportSurface::~GLXImageTransportSurface() { @@ -381,7 +383,7 @@ void GLXImageTransportSurface::OnResize(gfx::Size size) { GpuHostMsg_AcceleratedSurfaceNew_Params params; params.width = size_.width(); params.height = size_.height(); - params.identifier = window_; + params.surface_id = window_; helper_->SendAcceleratedSurfaceNew(params); helper_->SetScheduled(false); @@ -432,7 +434,8 @@ OSMesaImageTransportSurface::OSMesaImageTransportSurface( manager, render_view_id, renderer_id, - command_buffer_id)); + command_buffer_id, + gfx::kNullPluginWindow)); } OSMesaImageTransportSurface::~OSMesaImageTransportSurface() { @@ -484,7 +487,7 @@ void OSMesaImageTransportSurface::OnResize(gfx::Size size) { GpuHostMsg_AcceleratedSurfaceNew_Params params; params.width = size_.width(); params.height = size_.height(); - params.identifier = 0; // id comes from the browser with the shared mem + params.surface_id = 0; // id comes from the browser with the shared mem helper_->SendAcceleratedSurfaceNew(params); helper_->SetScheduled(false); @@ -539,7 +542,8 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface( GpuChannelManager* manager, int32 render_view_id, int32 renderer_id, - int32 command_buffer_id) { + int32 command_buffer_id, + gfx::PluginWindowHandle /* handle */) { scoped_refptr<gfx::GLSurface> surface; switch (gfx::GetGLImplementation()) { case gfx::kGLImplementationDesktopGL: @@ -570,126 +574,4 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface( return NULL; } -ImageTransportHelper::ImageTransportHelper(ImageTransportSurface* surface, - GpuChannelManager* manager, - int32 render_view_id, - int32 renderer_id, - int32 command_buffer_id) - : surface_(surface), - manager_(manager), - render_view_id_(render_view_id), - renderer_id_(renderer_id), - command_buffer_id_(command_buffer_id) { - route_id_ = manager_->GenerateRouteID(); - manager_->AddRoute(route_id_, this); -} - -ImageTransportHelper::~ImageTransportHelper() { - manager_->RemoveRoute(route_id_); -} - -bool ImageTransportHelper::Initialize() { - gpu::gles2::GLES2Decoder* decoder = Decoder(); - if (!decoder) - return false; - - decoder->SetResizeCallback( - NewCallback(this, &ImageTransportHelper::Resize)); - - return true; -} - -void ImageTransportHelper::Destroy() { -} - -bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message) - IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_NewACK, - OnNewSurfaceACK) - IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BuffersSwappedACK, - OnBuffersSwappedACK) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -void ImageTransportHelper::SendAcceleratedSurfaceRelease( - GpuHostMsg_AcceleratedSurfaceRelease_Params params) { - params.renderer_id = renderer_id_; - params.render_view_id = render_view_id_; - params.route_id = route_id_; - manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params)); -} - -void ImageTransportHelper::SendAcceleratedSurfaceNew( - GpuHostMsg_AcceleratedSurfaceNew_Params params) { - params.renderer_id = renderer_id_; - params.render_view_id = render_view_id_; - params.route_id = route_id_; - manager_->Send(new GpuHostMsg_AcceleratedSurfaceNew(params)); -} - -void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped( - GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params) { - params.renderer_id = renderer_id_; - params.render_view_id = render_view_id_; - params.route_id = route_id_; - manager_->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params)); -} - -void ImageTransportHelper::SetScheduled(bool is_scheduled) { - gpu::GpuScheduler* scheduler = Scheduler(); - if (!scheduler) - return; - - scheduler->SetScheduled(is_scheduled); -} - -void ImageTransportHelper::OnNewSurfaceACK( - uint64 surface_id, TransportDIB::Handle surface_handle) { - surface_->OnNewSurfaceACK(surface_id, surface_handle); -} - -void ImageTransportHelper::OnBuffersSwappedACK() { - surface_->OnBuffersSwappedACK(); -} - -void ImageTransportHelper::Resize(gfx::Size size) { - surface_->OnResize(size); -} - -bool ImageTransportHelper::MakeCurrent() { - gpu::gles2::GLES2Decoder* decoder = Decoder(); - if (!decoder) - return false; - return decoder->MakeCurrent(); -} - -gpu::GpuScheduler* ImageTransportHelper::Scheduler() { - GpuChannel* channel = manager_->LookupChannel(renderer_id_); - if (!channel) - return NULL; - - GpuCommandBufferStub* stub = - channel->LookupCommandBuffer(command_buffer_id_); - if (!stub) - return NULL; - - return stub->scheduler(); -} - -gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() { - GpuChannel* channel = manager_->LookupChannel(renderer_id_); - if (!channel) - return NULL; - - GpuCommandBufferStub* stub = - channel->LookupCommandBuffer(command_buffer_id_); - if (!stub) - return NULL; - - return stub->decoder(); -} - #endif // defined(USE_GPU) diff --git a/content/common/gpu/image_transport_surface_mac.cc b/content/common/gpu/image_transport_surface_mac.cc new file mode 100644 index 0000000..44e72e0 --- /dev/null +++ b/content/common/gpu/image_transport_surface_mac.cc @@ -0,0 +1,476 @@ +// 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. + +#if defined(ENABLE_GPU) + +#include "content/common/gpu/image_transport_surface.h" + +#include "base/mac/scoped_cftyperef.h" +#include "base/memory/scoped_ptr.h" +#include "content/common/gpu/gpu_messages.h" +#include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_implementation.h" +#include "ui/gfx/gl/gl_surface_cgl.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gfx/surface/io_surface_support_mac.h" + +namespace { + +// We are backed by an Pbuffer offscreen surface for the purposes of creating a +// context, but use FBOs to render to texture backed IOSurface +class IOSurfaceImageTransportSurface : public gfx::PbufferGLSurfaceCGL, + public ImageTransportSurface { + public: + IOSurfaceImageTransportSurface(GpuChannelManager* manager, + int32 render_view_id, + int32 renderer_id, + int32 command_buffer_id, + gfx::PluginWindowHandle handle); + + // GLSurface implementation + virtual bool Initialize() OVERRIDE; + virtual void Destroy() OVERRIDE; + virtual bool IsOffscreen() OVERRIDE; + virtual bool SwapBuffers() OVERRIDE; + virtual gfx::Size GetSize() OVERRIDE; + virtual void OnMakeCurrent(gfx::GLContext* context) OVERRIDE; + virtual unsigned int GetBackingFrameBufferObject() OVERRIDE; + + protected: + // ImageTransportSurface implementation + virtual void OnNewSurfaceACK(uint64 surface_id, + TransportDIB::Handle shm_handle) OVERRIDE; + virtual void OnBuffersSwappedACK() OVERRIDE; + virtual void OnResize(gfx::Size size) OVERRIDE; + + private: + virtual ~IOSurfaceImageTransportSurface() OVERRIDE; + + uint32 fbo_id_; + GLuint texture_id_; + + base::mac::ScopedCFTypeRef<CFTypeRef> io_surface_; + + // The id of |io_surface_| or 0 if that's NULL. + uint64 io_surface_id_; + + // Weak pointer to the context that this was last made current to. + gfx::GLContext* context_; + + gfx::Size size_; + + scoped_ptr<ImageTransportHelper> helper_; + + DISALLOW_COPY_AND_ASSIGN(IOSurfaceImageTransportSurface); +}; + +// We are backed by an Pbuffer offscreen surface for the purposes of creating a +// context, but use FBOs to render offscreen. +class TransportDIBImageTransportSurface : public gfx::PbufferGLSurfaceCGL, + public ImageTransportSurface { + public: + TransportDIBImageTransportSurface(GpuChannelManager* manager, + int32 render_view_id, + int32 renderer_id, + int32 command_buffer_id, + gfx::PluginWindowHandle handle); + + // GLSurface implementation + virtual bool Initialize() OVERRIDE; + virtual void Destroy() OVERRIDE; + virtual bool IsOffscreen() OVERRIDE; + virtual bool SwapBuffers() OVERRIDE; + virtual gfx::Size GetSize() OVERRIDE; + virtual void OnMakeCurrent(gfx::GLContext* context) OVERRIDE; + virtual unsigned int GetBackingFrameBufferObject() OVERRIDE; + + protected: + // ImageTransportSurface implementation + virtual void OnBuffersSwappedACK() OVERRIDE; + virtual void OnNewSurfaceACK(uint64 surface_id, + TransportDIB::Handle shm_handle) OVERRIDE; + virtual void OnResize(gfx::Size size) OVERRIDE; + + private: + virtual ~TransportDIBImageTransportSurface() OVERRIDE; + + uint32 fbo_id_; + GLuint render_buffer_id_; + + scoped_ptr<TransportDIB> shared_mem_; + + gfx::Size size_; + + static uint32 next_id_; + + scoped_ptr<ImageTransportHelper> helper_; + + DISALLOW_COPY_AND_ASSIGN(TransportDIBImageTransportSurface); +}; + +uint32 TransportDIBImageTransportSurface::next_id_ = 1; + +void AddBooleanValue(CFMutableDictionaryRef dictionary, + const CFStringRef key, + bool value) { + CFDictionaryAddValue(dictionary, key, + (value ? kCFBooleanTrue : kCFBooleanFalse)); +} + +void AddIntegerValue(CFMutableDictionaryRef dictionary, + const CFStringRef key, + int32 value) { + base::mac::ScopedCFTypeRef<CFNumberRef> number( + CFNumberCreate(NULL, kCFNumberSInt32Type, &value)); + CFDictionaryAddValue(dictionary, key, number.get()); +} + +IOSurfaceImageTransportSurface::IOSurfaceImageTransportSurface( + GpuChannelManager* manager, + int32 render_view_id, + int32 renderer_id, + int32 command_buffer_id, + gfx::PluginWindowHandle handle) + : gfx::PbufferGLSurfaceCGL(gfx::Size(1, 1)), + fbo_id_(0), + texture_id_(0), + io_surface_id_(0), + context_(NULL) { + helper_.reset(new ImageTransportHelper(this, + manager, + render_view_id, + renderer_id, + command_buffer_id, + handle)); + +} + +IOSurfaceImageTransportSurface::~IOSurfaceImageTransportSurface() { + Destroy(); +} + +bool IOSurfaceImageTransportSurface::Initialize() { + // Only support IOSurfaces if the GL implementation is the native desktop GL. + // IO surfaces will not work with, for example, OSMesa software renderer + // GL contexts. + if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) + return false; + + if (!helper_->Initialize()) + return false; + return PbufferGLSurfaceCGL::Initialize(); +} + +void IOSurfaceImageTransportSurface::Destroy() { + if (fbo_id_) { + glDeleteFramebuffersEXT(1, &fbo_id_); + fbo_id_ = 0; + } + + if (texture_id_) { + glDeleteTextures(1, &texture_id_); + texture_id_ = 0; + } + + helper_->Destroy(); + PbufferGLSurfaceCGL::Destroy(); +} + +bool IOSurfaceImageTransportSurface::IsOffscreen() { + return false; +} + +void IOSurfaceImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { + context_ = context; + + if (fbo_id_) + return; + + glGenFramebuffersEXT(1, &fbo_id_); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_); + OnResize(gfx::Size(1, 1)); + + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + if (status != GL_FRAMEBUFFER_COMPLETE) { + LOG(ERROR) << "Framebuffer incomplete."; + } +} + +unsigned int IOSurfaceImageTransportSurface::GetBackingFrameBufferObject() { + return fbo_id_; +} + +bool IOSurfaceImageTransportSurface::SwapBuffers() { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_); + glFlush(); + + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; + params.surface_id = io_surface_id_; + helper_->SendAcceleratedSurfaceBuffersSwapped(params); + + helper_->SetScheduled(false); + return true; +} + +gfx::Size IOSurfaceImageTransportSurface::GetSize() { + return size_; +} + +void IOSurfaceImageTransportSurface::OnBuffersSwappedACK() { + helper_->SetScheduled(true); +} + +void IOSurfaceImageTransportSurface::OnNewSurfaceACK( + uint64 surface_id, + TransportDIB::Handle /* shm_handle */) { + DCHECK_EQ(io_surface_id_, surface_id); + helper_->SetScheduled(true); +} + +void IOSurfaceImageTransportSurface::OnResize(gfx::Size size) { + IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); + + // Caching |context_| from OnMakeCurrent. It should still be current. + DCHECK(context_->IsCurrent(this)); + + size_ = size; + + if (texture_id_) + glDeleteTextures(1, &texture_id_); + + glGenTextures(1, &texture_id_); + + // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on + // Mac OS X and is required for IOSurface interoperability. + GLenum target = GL_TEXTURE_RECTANGLE_ARB; + glBindTexture(target, texture_id_); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + target, + texture_id_, + 0); + + // Allocate a new IOSurface, which is the GPU resource that can be + // shared across processes. + base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> properties; + properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + AddIntegerValue(properties, + io_surface_support->GetKIOSurfaceWidth(), + size_.width()); + AddIntegerValue(properties, + io_surface_support->GetKIOSurfaceHeight(), + size_.height()); + AddIntegerValue(properties, + io_surface_support->GetKIOSurfaceBytesPerElement(), 4); + AddBooleanValue(properties, + io_surface_support->GetKIOSurfaceIsGlobal(), true); + // I believe we should be able to unreference the IOSurfaces without + // synchronizing with the browser process because they are + // ultimately reference counted by the operating system. + io_surface_.reset(io_surface_support->IOSurfaceCreate(properties)); + + // Don't think we need to identify a plane. + GLuint plane = 0; + io_surface_support->CGLTexImageIOSurface2D( + static_cast<CGLContextObj>(context_->GetHandle()), + target, + GL_RGBA, + size_.width(), + size_.height(), + GL_BGRA, + GL_UNSIGNED_INT_8_8_8_8_REV, + io_surface_.get(), + plane); + + io_surface_id_ = io_surface_support->IOSurfaceGetID(io_surface_); + glFlush(); + + GpuHostMsg_AcceleratedSurfaceNew_Params params; + params.width = size_.width(); + params.height = size_.height(); + params.surface_id = io_surface_id_; + params.create_transport_dib = false; + helper_->SendAcceleratedSurfaceNew(params); + + helper_->SetScheduled(false); +} + +TransportDIBImageTransportSurface::TransportDIBImageTransportSurface( + GpuChannelManager* manager, + int32 render_view_id, + int32 renderer_id, + int32 command_buffer_id, + gfx::PluginWindowHandle handle) + : gfx::PbufferGLSurfaceCGL(gfx::Size(1, 1)), + fbo_id_(0), + render_buffer_id_(0) { + helper_.reset(new ImageTransportHelper(this, + manager, + render_view_id, + renderer_id, + command_buffer_id, + handle)); + +} + +TransportDIBImageTransportSurface::~TransportDIBImageTransportSurface() { + Destroy(); +} + +bool TransportDIBImageTransportSurface::Initialize() { + if (!helper_->Initialize()) + return false; + return PbufferGLSurfaceCGL::Initialize(); +} + +void TransportDIBImageTransportSurface::Destroy() { + if (fbo_id_) { + glDeleteFramebuffersEXT(1, &fbo_id_); + fbo_id_ = 0; + } + + if (render_buffer_id_) { + glDeleteRenderbuffersEXT(1, &render_buffer_id_); + render_buffer_id_ = 0; + } + + helper_->Destroy(); + PbufferGLSurfaceCGL::Destroy(); +} + +bool TransportDIBImageTransportSurface::IsOffscreen() { + return false; +} + +void TransportDIBImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { + if (fbo_id_) + return; + + glGenFramebuffersEXT(1, &fbo_id_); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_); + OnResize(gfx::Size(1, 1)); + + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + if (status != GL_FRAMEBUFFER_COMPLETE) { + LOG(ERROR) << "Framebuffer incomplete."; + } +} + +unsigned int TransportDIBImageTransportSurface::GetBackingFrameBufferObject() { + return fbo_id_; +} + +bool TransportDIBImageTransportSurface::SwapBuffers() { + DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL)); + + GLint current_alignment; + glGetIntegerv(GL_PACK_ALIGNMENT, ¤t_alignment); + glPixelStorei(GL_PACK_ALIGNMENT, 4); + glReadPixels(0, 0, + size_.width(), size_.height(), + GL_BGRA, // This pixel format should have no conversion. + GL_UNSIGNED_INT_8_8_8_8_REV, + shared_mem_->memory()); + glPixelStorei(GL_PACK_ALIGNMENT, current_alignment); + + GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; + params.surface_id = next_id_; + helper_->SendAcceleratedSurfaceBuffersSwapped(params); + + helper_->SetScheduled(false); + return true; +} + +gfx::Size TransportDIBImageTransportSurface::GetSize() { + return size_; +} + +void TransportDIBImageTransportSurface::OnBuffersSwappedACK() { + helper_->SetScheduled(true); +} + +void TransportDIBImageTransportSurface::OnNewSurfaceACK( + uint64 surface_id, + TransportDIB::Handle shm_handle) { + helper_->SetScheduled(true); + + shared_mem_.reset(TransportDIB::Map(shm_handle)); + DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL)); +} + +void TransportDIBImageTransportSurface::OnResize(gfx::Size size) { + size_ = size; + + if (!render_buffer_id_) + glGenRenderbuffersEXT(1, &render_buffer_id_); + + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_buffer_id_); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, + GL_RGBA, + size_.width(), size_.height()); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_RENDERBUFFER_EXT, + render_buffer_id_); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + + GpuHostMsg_AcceleratedSurfaceNew_Params params; + params.width = size_.width(); + params.height = size_.height(); + params.surface_id = next_id_++; + params.create_transport_dib = true; + helper_->SendAcceleratedSurfaceNew(params); + + helper_->SetScheduled(false); +} + +} // namespace + +// static +scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface( + GpuChannelManager* manager, + int32 render_view_id, + int32 renderer_id, + int32 command_buffer_id, + gfx::PluginWindowHandle handle) { + scoped_refptr<gfx::GLSurface> surface; + IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); + + switch (gfx::GetGLImplementation()) { + case gfx::kGLImplementationDesktopGL: + if (!io_surface_support) { + surface = new TransportDIBImageTransportSurface(manager, + render_view_id, + renderer_id, + command_buffer_id, + handle); + } else { + surface = new IOSurfaceImageTransportSurface(manager, + render_view_id, + renderer_id, + command_buffer_id, + handle); + } + break; + default: + NOTREACHED(); + return NULL; + } + if (surface->Initialize()) + return surface; + else + return NULL; +} + +#endif // defined(USE_GPU) diff --git a/content/content_common.gypi b/content/content_common.gypi index 0f6952d..3147112 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -119,6 +119,7 @@ 'common/gpu/gpu_messages.h', 'common/gpu/gpu_process_launch_causes.h', 'common/gpu/gpu_watchdog.h', + 'common/gpu/image_transport_surface.h', 'common/gpu/media/gpu_video_decode_accelerator.cc', 'common/gpu/media/gpu_video_decode_accelerator.h', 'common/gpu/transport_texture.cc', @@ -275,6 +276,10 @@ 'sources!': [ 'common/process_watcher_posix.cc', ], + 'sources': [ + 'common/gpu/image_transport_surface.cc', + 'common/gpu/image_transport_surface_mac.cc', + ], 'link_settings': { 'mac_bundle_resources': [ 'common/common.sb', @@ -294,7 +299,7 @@ }], ['touchui==1', { 'sources': [ - 'common/gpu/image_transport_surface_linux.h', + 'common/gpu/image_transport_surface.cc', 'common/gpu/image_transport_surface_linux.cc', ], 'include_dirs': [ |
