diff options
Diffstat (limited to 'content/common/gpu')
| -rw-r--r-- | content/common/gpu/gpu_channel.cc | 8 | ||||
| -rw-r--r-- | content/common/gpu/gpu_channel.h | 2 | ||||
| -rw-r--r-- | content/common/gpu/gpu_channel_manager.cc | 11 | ||||
| -rw-r--r-- | content/common/gpu/gpu_channel_manager.h | 2 | ||||
| -rw-r--r-- | content/common/gpu/gpu_command_buffer_stub.cc | 159 | ||||
| -rw-r--r-- | content/common/gpu/gpu_command_buffer_stub.h | 30 | ||||
| -rw-r--r-- | content/common/gpu/gpu_messages.h | 31 | ||||
| -rw-r--r-- | content/common/gpu/image_transport_surface.cc | 148 | ||||
| -rw-r--r-- | content/common/gpu/image_transport_surface.h | 123 | ||||
| -rw-r--r-- | content/common/gpu/image_transport_surface_linux.cc | 142 | ||||
| -rw-r--r-- | content/common/gpu/image_transport_surface_mac.cc | 476 |
11 files changed, 785 insertions, 347 deletions
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) |
