diff options
author | sievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-10 18:00:34 +0000 |
---|---|---|
committer | sievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-10 18:00:34 +0000 |
commit | 34466d02f35920cfbe0f1a3441a2a2c0724e0424 (patch) | |
tree | a5991a68e582b9b7be194742f20954569c36b42d /content/common | |
parent | 120cf540da701f19e9017cf7e603b2946aa88530 (diff) | |
download | chromium_src-34466d02f35920cfbe0f1a3441a2a2c0724e0424.zip chromium_src-34466d02f35920cfbe0f1a3441a2a2c0724e0424.tar.gz chromium_src-34466d02f35920cfbe0f1a3441a2a2c0724e0424.tar.bz2 |
Implement TextureImageTransportSurface using texture mailbox
This has a couple of advantages:
- allow tearing down and recreating the UI parent context without
losing the renderer contexts
- do not require a context to be able to generate textures when
creating the GLSurfaceHandle
- clearer ownership semantics that potentially allows for more
robust and easier lost context handling/thumbnailing/etc., since a texture is at
any given time owned by either: UI parent, mailbox, or
TextureImageTransportSurface
- simplify frontbuffer protection logic;
the frontbuffer textures are now owned by RWHV where they are refcounted
The TextureImageTransportSurface informs RenderWidgetHostView of the
mailbox names for the front- and backbuffer textures by
associating them with a surface_handle (1 or 2) in the AcceleratedSurfaceNew message.
During SwapBuffers() or PostSubBuffer() cycles, it then uses
produceTextureCHROMIUM() and consumeTextureCHROMIUM()
to transfer ownership between renderer and browser compositor.
RWHV sends back the surface_handle of the buffer being returned with the Swap ACK
(or 0 if no buffer is being returned in which case TextureImageTransportSurface will
allocate a new texture - note that this could be used to
simply keep textures for thumbnailing).
BUG=154815,139616
TBR=sky@chromium.org
NOTRY=True
Review URL: https://chromiumcodereview.appspot.com/11194042
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@172087 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/common')
-rw-r--r-- | content/common/gpu/client/gl_helper.cc | 27 | ||||
-rw-r--r-- | content/common/gpu/client/gl_helper.h | 8 | ||||
-rw-r--r-- | content/common/gpu/gpu_command_buffer_stub.cc | 2 | ||||
-rw-r--r-- | content/common/gpu/gpu_messages.h | 19 | ||||
-rw-r--r-- | content/common/gpu/image_transport_surface.cc | 17 | ||||
-rw-r--r-- | content/common/gpu/image_transport_surface.h | 10 | ||||
-rw-r--r-- | content/common/gpu/image_transport_surface_android.cc | 1 | ||||
-rw-r--r-- | content/common/gpu/image_transport_surface_mac.cc | 4 | ||||
-rw-r--r-- | content/common/gpu/image_transport_surface_win.cc | 5 | ||||
-rw-r--r-- | content/common/gpu/texture_image_transport_surface.cc | 449 | ||||
-rw-r--r-- | content/common/gpu/texture_image_transport_surface.h | 69 |
11 files changed, 268 insertions, 343 deletions
diff --git a/content/common/gpu/client/gl_helper.cc b/content/common/gpu/client/gl_helper.cc index 645ee43..8843695 100644 --- a/content/common/gpu/client/gl_helper.cc +++ b/content/common/gpu/client/gl_helper.cc @@ -17,6 +17,7 @@ #include "base/threading/thread_restrictions.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" +#include "third_party/skia/include/core/SkRegion.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" #include "ui/gl/gl_bindings.h" @@ -791,4 +792,30 @@ void GLHelper::InitCopyTextToImpl() { } +void GLHelper::CopySubBufferDamage(WebKit::WebGLId texture, + WebKit::WebGLId previous_texture, + const SkRegion& new_damage, + const SkRegion& old_damage) { + SkRegion region(old_damage); + if (region.op(new_damage, SkRegion::kDifference_Op)) { + ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); + ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder( + context_, dst_framebuffer); + ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); + context_->framebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + previous_texture, + 0); + for (SkRegion::Iterator it(region); !it.done(); it.next()) { + const SkIRect& rect = it.rect(); + context_->copyTexSubImage2D(GL_TEXTURE_2D, 0, + rect.x(), rect.y(), + rect.x(), rect.y(), + rect.width(), rect.height()); + } + context_->flush(); + } +} + } // namespace content diff --git a/content/common/gpu/client/gl_helper.h b/content/common/gpu/client/gl_helper.h index 41360b9..c7f161b 100644 --- a/content/common/gpu/client/gl_helper.h +++ b/content/common/gpu/client/gl_helper.h @@ -16,6 +16,8 @@ class Rect; class Size; } +class SkRegion; + namespace content { // Provides higher level operations on top of the WebKit::WebGraphicsContext3D @@ -66,6 +68,12 @@ class GLHelper { WebKit::WebGLId CompileShaderFromSource(const WebKit::WGC3Dchar* source, WebKit::WGC3Denum type); + // Copies all pixels from |previous_texture| into |texture| that are + // inside the region covered by |old_damage| but not part of |new_damage|. + void CopySubBufferDamage(WebKit::WebGLId texture, + WebKit::WebGLId previous_texture, + const SkRegion& new_damage, + const SkRegion& old_damage); private: class CopyTextureToImpl; diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index 8eefd15..0fb6c6e 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -136,8 +136,6 @@ GpuCommandBufferStub::GpuCommandBufferStub( new GpuCommandBufferMemoryTracker(channel), true); } - if (handle_.sync_point) - OnWaitSyncPoint(handle_.sync_point); } GpuCommandBufferStub::~GpuCommandBufferStub() { diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index d72bf05..38d2156 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -46,6 +46,7 @@ IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceNew_Params) IPC_STRUCT_MEMBER(int32, width) IPC_STRUCT_MEMBER(int32, height) IPC_STRUCT_MEMBER(uint64, surface_handle) + IPC_STRUCT_MEMBER(std::string, mailbox_name) IPC_STRUCT_MEMBER(int32, route_id) #if defined(OS_MACOSX) IPC_STRUCT_MEMBER(gfx::PluginWindowHandle, window) @@ -63,8 +64,6 @@ IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params) #if defined(OS_MACOSX) IPC_STRUCT_MEMBER(gfx::PluginWindowHandle, window) #endif - IPC_STRUCT_MEMBER(uint32, protection_state_id) - IPC_STRUCT_MEMBER(bool, skip_ack) IPC_STRUCT_END() #undef IPC_MESSAGE_EXPORT #define IPC_MESSAGE_EXPORT @@ -81,12 +80,10 @@ IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params) #if defined(OS_MACOSX) IPC_STRUCT_MEMBER(gfx::PluginWindowHandle, window) #endif - IPC_STRUCT_MEMBER(uint32, protection_state_id) IPC_STRUCT_END() IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceRelease_Params) IPC_STRUCT_MEMBER(int32, surface_id) - IPC_STRUCT_MEMBER(uint64, identifier) IPC_STRUCT_MEMBER(int32, route_id) #if defined(OS_MACOSX) IPC_STRUCT_MEMBER(gfx::PluginWindowHandle, window) @@ -197,10 +194,6 @@ IPC_STRUCT_TRAITS_BEGIN(gfx::GLSurfaceHandle) IPC_STRUCT_TRAITS_MEMBER(transport) IPC_STRUCT_TRAITS_MEMBER(parent_gpu_process_id) IPC_STRUCT_TRAITS_MEMBER(parent_client_id) - IPC_STRUCT_TRAITS_MEMBER(parent_context_id) - IPC_STRUCT_TRAITS_MEMBER(parent_texture_id[0]) - IPC_STRUCT_TRAITS_MEMBER(parent_texture_id[1]) - IPC_STRUCT_TRAITS_MEMBER(sync_point) IPC_STRUCT_TRAITS_END() IPC_ENUM_TRAITS(content::CauseForGpuLaunch) @@ -280,16 +273,12 @@ IPC_MESSAGE_CONTROL1(GpuMsg_SetVideoMemoryWindowCount, // view. IPC_MESSAGE_ROUTED0(AcceleratedSurfaceMsg_ResizeViewACK) -// Tells the GPU process if it's worth suggesting release of the front surface. -IPC_MESSAGE_ROUTED2(AcceleratedSurfaceMsg_SetFrontSurfaceIsProtected, - bool /* is_protected */, - uint32 /* protection_state_id */) - // Tells the GPU process that the browser process has handled the swap // buffers or post sub-buffer request. A non-zero sync point means -// that we should wait for the sync point. +// that we should wait for the sync point. The surface_handle identifies +// that buffer that has finished presented, i.e. the buffer being returned. IPC_MESSAGE_ROUTED2(AcceleratedSurfaceMsg_BufferPresented, - bool /* presented */, + uint64 /* surface_handle */, uint32 /* sync_point */) // Tells the GPU process to remove all contexts. diff --git a/content/common/gpu/image_transport_surface.cc b/content/common/gpu/image_transport_surface.cc index d9ea02e..96240c7 100644 --- a/content/common/gpu/image_transport_surface.cc +++ b/content/common/gpu/image_transport_surface.cc @@ -24,10 +24,6 @@ ImageTransportSurface::ImageTransportSurface() {} ImageTransportSurface::~ImageTransportSurface() {} -void ImageTransportSurface::OnSetFrontSurfaceIsProtected( - bool is_protected, uint32 protection_state_id) { -} - void ImageTransportSurface::GetRegionsToCopy( const gfx::Rect& previous_damage_rect, const gfx::Rect& new_damage_rect, @@ -100,8 +96,6 @@ bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message) IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented, OnBufferPresented) - IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_SetFrontSurfaceIsProtected, - OnSetFrontSurfaceIsProtected) IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_ResizeViewACK, OnResizeViewACK); IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -212,14 +206,9 @@ gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() { return stub_->decoder(); } -void ImageTransportHelper::OnSetFrontSurfaceIsProtected( - bool is_protected, uint32 protection_state_id) { - surface_->OnSetFrontSurfaceIsProtected(is_protected, protection_state_id); -} - -void ImageTransportHelper::OnBufferPresented(bool presented, +void ImageTransportHelper::OnBufferPresented(uint64 surface_handle, uint32 sync_point) { - surface_->OnBufferPresented(presented, sync_point); + surface_->OnBufferPresented(surface_handle, sync_point); } void ImageTransportHelper::OnResizeViewACK() { @@ -322,7 +311,7 @@ bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { } void PassThroughImageTransportSurface::OnBufferPresented( - bool /* presented */, + uint64 /* surface_handle */, uint32 /* sync_point */) { DCHECK(transport_); helper_->SetScheduled(true); diff --git a/content/common/gpu/image_transport_surface.h b/content/common/gpu/image_transport_surface.h index 2036fa5..17a2be6 100644 --- a/content/common/gpu/image_transport_surface.h +++ b/content/common/gpu/image_transport_surface.h @@ -60,11 +60,9 @@ class ImageTransportSurface { public: ImageTransportSurface(); - virtual void OnBufferPresented(bool presented, uint32 sync_point) = 0; + virtual void OnBufferPresented(uint64 surface_handle, uint32 sync_point) = 0; virtual void OnResizeViewACK() = 0; virtual void OnResize(gfx::Size size) = 0; - virtual void OnSetFrontSurfaceIsProtected(bool is_protected, - uint32 protection_state_id); // Creates the appropriate surface depending on the GL implementation. static scoped_refptr<gfx::GLSurface> @@ -143,10 +141,8 @@ class ImageTransportHelper gpu::gles2::GLES2Decoder* Decoder(); // IPC::Message handlers. - void OnBufferPresented(bool presented, uint32 sync_point); + void OnBufferPresented(uint64 surface_handle, uint32 sync_point); void OnResizeViewACK(); - void OnSetFrontSurfaceIsProtected(bool is_protected, - uint32 protection_state_id); // Backbuffer resize callback. void Resize(gfx::Size size); @@ -181,7 +177,7 @@ class PassThroughImageTransportSurface virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE; // ImageTransportSurface implementation. - virtual void OnBufferPresented(bool presented, + virtual void OnBufferPresented(uint64 surface_handle, uint32 sync_point) OVERRIDE; virtual void OnResizeViewACK() OVERRIDE; virtual void OnResize(gfx::Size size) OVERRIDE; diff --git a/content/common/gpu/image_transport_surface_android.cc b/content/common/gpu/image_transport_surface_android.cc index 045a4c8..f476f755 100644 --- a/content/common/gpu/image_transport_surface_android.cc +++ b/content/common/gpu/image_transport_surface_android.cc @@ -18,7 +18,6 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface( const gfx::GLSurfaceHandle& handle) { scoped_refptr<gfx::GLSurface> surface; if (!handle.handle && handle.transport) { - DCHECK(handle.parent_client_id); surface = new TextureImageTransportSurface(manager, stub, handle); } else if (handle.handle == gfx::kDummyPluginWindow && !handle.transport) { DCHECK(GpuSurfaceLookup::GetInstance()); diff --git a/content/common/gpu/image_transport_surface_mac.cc b/content/common/gpu/image_transport_surface_mac.cc index 5046912..4f888db 100644 --- a/content/common/gpu/image_transport_surface_mac.cc +++ b/content/common/gpu/image_transport_surface_mac.cc @@ -57,7 +57,7 @@ class IOSurfaceImageTransportSurface : public gfx::NoOpGLSurfaceCGL, protected: // ImageTransportSurface implementation - virtual void OnBufferPresented(bool presented, + virtual void OnBufferPresented(uint64 surface_handle, uint32 sync_point) OVERRIDE; virtual void OnResizeViewACK() OVERRIDE; virtual void OnResize(gfx::Size size) OVERRIDE; @@ -268,7 +268,7 @@ gfx::Size IOSurfaceImageTransportSurface::GetSize() { return size_; } -void IOSurfaceImageTransportSurface::OnBufferPresented(bool presented, +void IOSurfaceImageTransportSurface::OnBufferPresented(uint64 surface_handle, uint32 sync_point) { DCHECK(is_swap_buffers_pending_); is_swap_buffers_pending_ = false; diff --git a/content/common/gpu/image_transport_surface_win.cc b/content/common/gpu/image_transport_surface_win.cc index 9c8eed4..62296a7 100644 --- a/content/common/gpu/image_transport_surface_win.cc +++ b/content/common/gpu/image_transport_surface_win.cc @@ -50,7 +50,8 @@ class PbufferImageTransportSurface protected: // ImageTransportSurface implementation - virtual void OnBufferPresented(bool presented, uint32 sync_point) OVERRIDE; + virtual void OnBufferPresented(uint64 surface_handle, + uint32 sync_point) OVERRIDE; virtual void OnResizeViewACK() OVERRIDE; virtual void OnResize(gfx::Size size) OVERRIDE; virtual gfx::Size GetSize() OVERRIDE; @@ -206,7 +207,7 @@ void PbufferImageTransportSurface::SendBuffersSwapped() { is_swap_buffers_pending_ = true; } -void PbufferImageTransportSurface::OnBufferPresented(bool presented, +void PbufferImageTransportSurface::OnBufferPresented(uint64 surface_handle, uint32 sync_point) { is_swap_buffers_pending_ = false; if (did_unschedule_) { diff --git a/content/common/gpu/texture_image_transport_surface.cc b/content/common/gpu/texture_image_transport_surface.cc index 64848fe..7fa2690 100644 --- a/content/common/gpu/texture_image_transport_surface.cc +++ b/content/common/gpu/texture_image_transport_surface.cc @@ -16,17 +16,19 @@ #include "content/public/common/content_switches.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/gpu_scheduler.h" -#include "gpu/command_buffer/service/texture_manager.h" +#include "gpu/command_buffer/service/texture_definition.h" using gpu::gles2::ContextGroup; +using gpu::gles2::MailboxManager; +using gpu::gles2::MailboxName; +using gpu::gles2::TextureDefinition; using gpu::gles2::TextureManager; -typedef TextureManager::TextureInfo TextureInfo; namespace content { TextureImageTransportSurface::Texture::Texture() - : client_id(0), - sent_to_client(false) { + : service_id(0), + surface_handle(0) { } TextureImageTransportSurface::Texture::~Texture() { @@ -37,17 +39,12 @@ TextureImageTransportSurface::TextureImageTransportSurface( GpuCommandBufferStub* stub, const gfx::GLSurfaceHandle& handle) : fbo_id_(0), - front_(0), stub_destroyed_(false), backbuffer_suggested_allocation_(true), frontbuffer_suggested_allocation_(true), - frontbuffer_is_protected_(true), - protection_state_id_(0), handle_(handle), - parent_stub_(NULL), is_swap_buffers_pending_(false), - did_unschedule_(false), - did_flip_(false) { + did_unschedule_(false) { helper_.reset(new ImageTransportHelper(this, manager, stub, @@ -60,39 +57,12 @@ TextureImageTransportSurface::~TextureImageTransportSurface() { } bool TextureImageTransportSurface::Initialize() { - GpuChannelManager* manager = helper_->manager(); - GpuChannel* parent_channel = manager->LookupChannel(handle_.parent_client_id); - if (!parent_channel) - return false; + mailbox_manager_ = + helper_->stub()->decoder()->GetContextGroup()->mailbox_manager(); - parent_stub_ = parent_channel->LookupCommandBuffer(handle_.parent_context_id); - if (!parent_stub_) - return false; - - parent_stub_->AddDestructionObserver(this); - TextureManager* texture_manager = - parent_stub_->decoder()->GetContextGroup()->texture_manager(); - DCHECK(texture_manager); - - for (int i = 0; i < 2; ++i) { - Texture& texture = textures_[i]; - texture.client_id = handle_.parent_texture_id[i]; - texture.info = texture_manager->GetTextureInfo(texture.client_id); - if (!texture.info) - return false; - - if (!texture.info->target()) - texture_manager->SetInfoTarget(texture.info, GL_TEXTURE_2D); - texture_manager->SetParameter( - texture.info, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - texture_manager->SetParameter( - texture.info, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - texture_manager->SetParameter( - texture.info, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - texture_manager->SetParameter( - texture.info, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } + backbuffer_.surface_handle = 1; + GpuChannelManager* manager = helper_->manager(); surface_ = manager->GetDefaultOffscreenSurface(); if (!surface_.get()) return false; @@ -100,19 +70,17 @@ bool TextureImageTransportSurface::Initialize() { if (!helper_->Initialize()) return false; - const CommandLine* command_line = CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess)) - helper_->SetPreemptByCounter(parent_channel->MessagesPendingCount()); + GpuChannel* parent_channel = manager->LookupChannel(handle_.parent_client_id); + if (parent_channel) { + const CommandLine* command_line = CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess)) + helper_->SetPreemptByCounter(parent_channel->MessagesPendingCount()); + } return true; } void TextureImageTransportSurface::Destroy() { - if (parent_stub_) { - parent_stub_->decoder()->MakeCurrent(); - ReleaseParentStub(); - } - if (surface_.get()) surface_ = NULL; @@ -149,10 +117,23 @@ bool TextureImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { return true; } + if (!context_.get()) { + DCHECK(helper_->stub()); + context_ = helper_->stub()->decoder()->GetGLContext(); + } + if (!fbo_id_) { glGenFramebuffersEXT(1, &fbo_id_); glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_); - CreateBackTexture(gfx::Size(1, 1)); + current_size_ = gfx::Size(1, 1); + helper_->stub()->AddDestructionObserver(this); + } + + // We could be receiving non-deferred GL commands, that is anything that does + // not need a framebuffer. + if (!backbuffer_.service_id && !is_swap_buffers_pending_ && + backbuffer_suggested_allocation_) { + CreateBackTexture(); #ifndef NDEBUG GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); @@ -163,10 +144,7 @@ bool TextureImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { return false; } #endif - DCHECK(helper_->stub()); - helper_->stub()->AddDestructionObserver(this); } - return true; } @@ -180,15 +158,11 @@ void TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { return; backbuffer_suggested_allocation_ = allocation; - if (!helper_->MakeCurrent()) - return; - if (backbuffer_suggested_allocation_) { - DCHECK(!textures_[back()].info->service_id() || - !textures_[back()].sent_to_client); - CreateBackTexture(textures_[back()].size); + DCHECK(!backbuffer_.service_id); + CreateBackTexture(); } else { - ReleaseTexture(back()); + ReleaseBackTexture(); } } @@ -196,22 +170,10 @@ void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) { if (frontbuffer_suggested_allocation_ == allocation) return; frontbuffer_suggested_allocation_ = allocation; - AdjustFrontBufferAllocation(); -} -void TextureImageTransportSurface::AdjustFrontBufferAllocation() { - if (!helper_->MakeCurrent()) - return; - - if (!frontbuffer_suggested_allocation_ && !frontbuffer_is_protected_ && - textures_[front()].info->service_id()) { - ReleaseTexture(front()); - if (textures_[front()].sent_to_client) { - GpuHostMsg_AcceleratedSurfaceRelease_Params params; - params.identifier = textures_[front()].client_id; - helper_->SendAcceleratedSurfaceRelease(params); - textures_[front()].sent_to_client = false; - } + if (!frontbuffer_suggested_allocation_) { + GpuHostMsg_AcceleratedSurfaceRelease_Params params; + helper_->SendAcceleratedSurfaceRelease(params); } } @@ -228,50 +190,47 @@ void* TextureImageTransportSurface::GetConfig() { } void TextureImageTransportSurface::OnResize(gfx::Size size) { - CreateBackTexture(size); + current_size_ = size; + CreateBackTexture(); } void TextureImageTransportSurface::OnWillDestroyStub( GpuCommandBufferStub* stub) { - if (stub == parent_stub_) { - ReleaseParentStub(); - helper_->SetPreemptByCounter(NULL); - } else { - DCHECK(stub == helper_->stub()); - stub->RemoveDestructionObserver(this); + DCHECK(stub == helper_->stub()); + stub->RemoveDestructionObserver(this); - // We are losing the stub owning us, this is our last chance to clean up the - // resources we allocated in the stub's context. - if (fbo_id_) { - glDeleteFramebuffersEXT(1, &fbo_id_); - CHECK_GL_ERROR(); - fbo_id_ = 0; - } + GpuHostMsg_AcceleratedSurfaceRelease_Params params; + helper_->SendAcceleratedSurfaceRelease(params); - stub_destroyed_ = true; + ReleaseBackTexture(); + + // We are losing the stub owning us, this is our last chance to clean up the + // resources we allocated in the stub's context. + if (fbo_id_) { + glDeleteFramebuffersEXT(1, &fbo_id_); + CHECK_GL_ERROR(); + fbo_id_ = 0; } + + stub_destroyed_ = true; } bool TextureImageTransportSurface::SwapBuffers() { DCHECK(backbuffer_suggested_allocation_); - if (!frontbuffer_suggested_allocation_ || !frontbuffer_is_protected_) + if (!frontbuffer_suggested_allocation_) return true; - if (!parent_stub_) { - LOG(ERROR) << "SwapBuffers failed because no parent stub."; - return false; - } glFlush(); - front_ = back(); - previous_damage_rect_ = gfx::Rect(textures_[front()].size); + ProduceTexture(backbuffer_); - DCHECK(textures_[front()].client_id != 0); + // Do not allow destruction while we are still waiting for a swap ACK, + // so we do not leak a texture in the mailbox. + AddRef(); + DCHECK(backbuffer_.size == current_size_); GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; - params.surface_handle = textures_[front()].client_id; - params.size = textures_[front()].size; - params.protection_state_id = protection_state_id_; - params.skip_ack = false; + params.surface_handle = backbuffer_.surface_handle; + params.size = backbuffer_.size; helper_->SendAcceleratedSurfaceBuffersSwapped(params); DCHECK(!is_swap_buffers_pending_); @@ -282,68 +241,31 @@ bool TextureImageTransportSurface::SwapBuffers() { bool TextureImageTransportSurface::PostSubBuffer( int x, int y, int width, int height) { DCHECK(backbuffer_suggested_allocation_); - DCHECK(textures_[back()].info->service_id()); - if (!frontbuffer_suggested_allocation_ || !frontbuffer_is_protected_) + if (!frontbuffer_suggested_allocation_) return true; - // If we are recreating the frontbuffer with this swap, make sure we are - // drawing a full frame. - DCHECK(textures_[front()].info->service_id() || - (!x && !y && gfx::Size(width, height) == textures_[back()].size)); - if (!parent_stub_) { - LOG(ERROR) << "PostSubBuffer failed because no parent stub."; - return false; - } - const gfx::Rect new_damage_rect(x, y, width, height); + DCHECK(gfx::Rect(gfx::Point(), current_size_).Contains(new_damage_rect)); // An empty damage rect is a successful no-op. if (new_damage_rect.IsEmpty()) return true; - int back_texture_service_id = textures_[back()].info->service_id(); - int front_texture_service_id = textures_[front()].info->service_id(); - - gfx::Size expected_size = textures_[back()].size; - bool surfaces_same_size = textures_[front()].size == expected_size; - - if (surfaces_same_size) { - std::vector<gfx::Rect> regions_to_copy; - GetRegionsToCopy(previous_damage_rect_, new_damage_rect, ®ions_to_copy); - - ScopedFrameBufferBinder fbo_binder(fbo_id_); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - front_texture_service_id, - 0); - ScopedTextureBinder texture_binder(back_texture_service_id); - - for (size_t i = 0; i < regions_to_copy.size(); ++i) { - const gfx::Rect& region_to_copy = regions_to_copy[i]; - if (!region_to_copy.IsEmpty()) { - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, region_to_copy.x(), - region_to_copy.y(), region_to_copy.x(), region_to_copy.y(), - region_to_copy.width(), region_to_copy.height()); - } - } - } else if (!surfaces_same_size && did_flip_) { - DCHECK(new_damage_rect == gfx::Rect(expected_size)); - } - glFlush(); - front_ = back(); - previous_damage_rect_ = new_damage_rect; + ProduceTexture(backbuffer_); + + // Do not allow destruction while we are still waiting for a swap ACK, + // so we do not leak a texture in the mailbox. + AddRef(); - DCHECK(textures_[front()].client_id); + DCHECK(current_size_ == backbuffer_.size); GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; - params.surface_handle = textures_[front()].client_id; - params.surface_size = textures_[front()].size; + params.surface_handle = backbuffer_.surface_handle; + params.surface_size = backbuffer_.size; params.x = x; params.y = y; params.width = width; params.height = height; - params.protection_state_id = protection_state_id_; helper_->SendAcceleratedSurfacePostSubBuffer(params); DCHECK(!is_swap_buffers_pending_); @@ -360,7 +282,7 @@ std::string TextureImageTransportSurface::GetExtensions() { } gfx::Size TextureImageTransportSurface::GetSize() { - gfx::Size size = textures_[back()].size; + gfx::Size size = current_size_; // OSMesa expects a non-zero size. return gfx::Size(size.width() == 0 ? 1 : size.width(), @@ -375,70 +297,60 @@ unsigned TextureImageTransportSurface::GetFormat() { return surface_.get() ? surface_->GetFormat() : 0; } -void TextureImageTransportSurface::OnSetFrontSurfaceIsProtected( - bool is_protected, uint32 protection_state_id) { - protection_state_id_ = protection_state_id; - if (frontbuffer_is_protected_ == is_protected) - return; - frontbuffer_is_protected_ = is_protected; - AdjustFrontBufferAllocation(); - - // If surface is set to protected, and we haven't actually released it yet, - // we can set the ui surface handle now just by sending a swap message. - if (is_protected && textures_[front()].info->service_id() && - textures_[front()].sent_to_client) { - GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; - params.surface_handle = textures_[front()].client_id; - params.size = textures_[front()].size; - params.protection_state_id = protection_state_id_; - params.skip_ack = true; - helper_->SendAcceleratedSurfaceBuffersSwapped(params); - } -} - -void TextureImageTransportSurface::OnBufferPresented(bool presented, +void TextureImageTransportSurface::OnBufferPresented(uint64 surface_handle, uint32 sync_point) { if (sync_point == 0) { - BufferPresentedImpl(presented); + BufferPresentedImpl(surface_handle); } else { helper_->manager()->sync_point_manager()->AddSyncPointCallback( sync_point, base::Bind(&TextureImageTransportSurface::BufferPresentedImpl, - this->AsWeakPtr(), - presented)); + this, + surface_handle)); } -} -void TextureImageTransportSurface::BufferPresentedImpl(bool presented) { - DCHECK(is_swap_buffers_pending_); - is_swap_buffers_pending_ = false; + // Careful, we might get deleted now if we were only waiting for + // a final swap ACK. + Release(); +} - if (presented) { - // If we had not flipped, the two frame damage tracking is inconsistent. - // So conservatively take the whole frame. - if (!did_flip_) - previous_damage_rect_ = gfx::Rect(textures_[front()].size); +void TextureImageTransportSurface::BufferPresentedImpl(uint64 surface_handle) { + DCHECK(!backbuffer_.service_id); + if (surface_handle) { + DCHECK(surface_handle == 1 || surface_handle == 2); + backbuffer_.surface_handle = surface_handle; + ConsumeTexture(backbuffer_); } else { - front_ = back(); - previous_damage_rect_ = gfx::Rect(0, 0, 0, 0); + // We didn't get back a texture, so allocate 'the other' buffer. + backbuffer_.surface_handle = (backbuffer_.surface_handle == 1) ? 2 : 1; + mailbox_name(backbuffer_.surface_handle) = MailboxName(); + } + + if (stub_destroyed_ && backbuffer_.service_id) { + // TODO(sievers): Remove this after changes to the mailbox to take ownership + // of the service ids. + DCHECK(context_.get() && surface_.get()); + if (context_->MakeCurrent(surface_.get())) + glDeleteTextures(1, &backbuffer_.service_id); + + return; } - did_flip_ = presented; + DCHECK(is_swap_buffers_pending_); + is_swap_buffers_pending_ = false; + + // We should not have allowed the backbuffer to be discarded while the ack + // was pending. + DCHECK(backbuffer_suggested_allocation_); // We're relying on the fact that the parent context is // finished with it's context when it inserts the sync point that // triggers this callback. if (helper_->MakeCurrent()) { - if ((presented && textures_[front()].size != textures_[back()].size) || - !textures_[back()].info->service_id() || - !textures_[back()].sent_to_client) { - // We may get an ACK from a stale swap just to reschedule. In that case, - // we may not have a backbuffer suggestion and should not recreate one. - if (backbuffer_suggested_allocation_) - CreateBackTexture(textures_[front()].size); - } else { + if (backbuffer_.size != current_size_ || !backbuffer_.service_id) + CreateBackTexture(); + else AttachBackTextureToFBO(); - } } // Even if MakeCurrent fails, schedule anyway, to trigger the lost context @@ -453,94 +365,69 @@ void TextureImageTransportSurface::OnResizeViewACK() { NOTREACHED(); } -void TextureImageTransportSurface::ReleaseTexture(int id) { - if (!parent_stub_) - return; - Texture& texture = textures_[id]; - TextureInfo* info = texture.info; - DCHECK(info); - - GLuint service_id = info->service_id(); - if (!service_id) +void TextureImageTransportSurface::ReleaseBackTexture() { + if (!backbuffer_.service_id) return; - info->SetServiceId(0); - { - ScopedFrameBufferBinder fbo_binder(fbo_id_); - glDeleteTextures(1, &service_id); - } + glDeleteTextures(1, &backbuffer_.service_id); + backbuffer_.service_id = 0; + mailbox_name(backbuffer_.surface_handle) = MailboxName(); glFlush(); CHECK_GL_ERROR(); } -void TextureImageTransportSurface::CreateBackTexture(const gfx::Size& size) { - if (!parent_stub_) - return; - Texture& texture = textures_[back()]; - TextureInfo* info = texture.info; - DCHECK(info); - - GLuint service_id = info->service_id(); +void TextureImageTransportSurface::CreateBackTexture() { + // If |is_swap_buffers_pending| we are waiting for our backbuffer + // in the mailbox, so we shouldn't be reallocating it now. + DCHECK(!is_swap_buffers_pending_); - if (service_id && texture.size == size && texture.sent_to_client) + if (backbuffer_.service_id && backbuffer_.size == current_size_) return; - if (!service_id) { - glGenTextures(1, &service_id); - info->SetServiceId(service_id); + if (!backbuffer_.service_id) { + MailboxName new_mailbox_name; + MailboxName& name = mailbox_name(backbuffer_.surface_handle); + // This slot should be uninitialized. + DCHECK(!memcmp(&name, &new_mailbox_name, sizeof(MailboxName))); + mailbox_manager_->GenerateMailboxName(&new_mailbox_name); + name = new_mailbox_name; + glGenTextures(1, &backbuffer_.service_id); } - if (size != texture.size) { - texture.size = size; - TextureManager* texture_manager = - parent_stub_->decoder()->GetContextGroup()->texture_manager(); - texture_manager->SetLevelInfo( - info, - GL_TEXTURE_2D, - 0, - GL_RGBA, - size.width(), - size.height(), - 1, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - true); - } + backbuffer_.size = current_size_; { - ScopedTextureBinder texture_binder(service_id); + ScopedTextureBinder texture_binder(backbuffer_.service_id); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - size.width(), size.height(), 0, + current_size_.width(), current_size_.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); CHECK_GL_ERROR(); } AttachBackTextureToFBO(); + const MailboxName& name = mailbox_name(backbuffer_.surface_handle); + GpuHostMsg_AcceleratedSurfaceNew_Params params; - params.width = size.width(); - params.height = size.height(); - params.surface_handle = texture.client_id; + params.width = current_size_.width(); + params.height = current_size_.height(); + params.surface_handle = backbuffer_.surface_handle; + params.mailbox_name.append( + reinterpret_cast<const char*>(&name), sizeof(name)); helper_->SendAcceleratedSurfaceNew(params); - texture.sent_to_client = true; } void TextureImageTransportSurface::AttachBackTextureToFBO() { - if (!parent_stub_) - return; - TextureInfo* info = textures_[back()].info; - DCHECK(info); - + DCHECK(backbuffer_.service_id); ScopedFrameBufferBinder fbo_binder(fbo_id_); glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - info->service_id(), + backbuffer_.service_id, 0); glFlush(); CHECK_GL_ERROR(); @@ -548,24 +435,58 @@ void TextureImageTransportSurface::AttachBackTextureToFBO() { #ifndef NDEBUG GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { - DLOG(ERROR) << "Framebuffer incomplete."; + DLOG(FATAL) << "Framebuffer incomplete: " << status; } #endif } -void TextureImageTransportSurface::ReleaseParentStub() { - DCHECK(parent_stub_); - parent_stub_->RemoveDestructionObserver(this); - for (int i = 0; i < 2; ++i) { - Texture& texture = textures_[i]; - texture.info = NULL; - if (!texture.sent_to_client) - continue; - GpuHostMsg_AcceleratedSurfaceRelease_Params params; - params.identifier = texture.client_id; - helper_->SendAcceleratedSurfaceRelease(params); +void TextureImageTransportSurface::ConsumeTexture(Texture& texture) { + DCHECK(!texture.service_id); + DCHECK(texture.surface_handle == 1 || texture.surface_handle == 2); + + scoped_ptr<TextureDefinition> definition(mailbox_manager_->ConsumeTexture( + GL_TEXTURE_2D, mailbox_name(texture.surface_handle))); + if (definition.get()) { + texture.service_id = definition->ReleaseServiceId(); + texture.size = gfx::Size(definition->level_infos()[0][0].width, + definition->level_infos()[0][0].height); } - parent_stub_ = NULL; +} + +void TextureImageTransportSurface::ProduceTexture(Texture& texture) { + DCHECK(texture.service_id); + DCHECK(texture.surface_handle == 1 || texture.surface_handle == 2); + TextureManager* texture_manager = + helper_->stub()->decoder()->GetContextGroup()->texture_manager(); + DCHECK(texture.size.width() > 0 && texture.size.height() > 0); + TextureDefinition::LevelInfo info( + GL_TEXTURE_2D, GL_RGBA, texture.size.width(), texture.size.height(), 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, true); + + TextureDefinition::LevelInfos level_infos; + level_infos.resize(1); + level_infos[0].resize(texture_manager->MaxLevelsForTarget(GL_TEXTURE_2D)); + level_infos[0][0] = info; + scoped_ptr<TextureDefinition> definition(new TextureDefinition( + GL_TEXTURE_2D, + texture.service_id, + GL_LINEAR, + GL_LINEAR, + GL_CLAMP_TO_EDGE, + GL_CLAMP_TO_EDGE, + GL_NONE, + true, + level_infos)); + // Pass NULL as |owner| here to avoid errors from glConsumeTextureCHROMIUM() + // when the renderer context group goes away before the RWHV handles a pending + // ACK. We avoid leaking a texture in the mailbox by waiting for the final ACK + // at which point we consume the correct texture back. + mailbox_manager_->ProduceTexture( + GL_TEXTURE_2D, + mailbox_name(texture.surface_handle), + definition.release(), + NULL); + texture.service_id = 0; } } // namespace content diff --git a/content/common/gpu/texture_image_transport_surface.h b/content/common/gpu/texture_image_transport_surface.h index 150b585..4501347 100644 --- a/content/common/gpu/texture_image_transport_surface.h +++ b/content/common/gpu/texture_image_transport_surface.h @@ -6,10 +6,11 @@ #define CONTENT_COMMON_GPU_TEXTURE_IMAGE_TRANSPORT_SURFACE_H_ #include "base/basictypes.h" -#include "base/memory/weak_ptr.h" #include "content/common/gpu/gpu_command_buffer_stub.h" #include "content/common/gpu/image_transport_surface.h" +#include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/texture_manager.h" +#include "ui/gl/gl_context.h" #include "ui/gl/gl_surface.h" namespace content { @@ -18,8 +19,7 @@ class GpuChannelManager; class TextureImageTransportSurface : public ImageTransportSurface, public GpuCommandBufferStub::DestructionObserver, - public gfx::GLSurface, - public base::SupportsWeakPtr<TextureImageTransportSurface> { + public gfx::GLSurface { public: TextureImageTransportSurface(GpuChannelManager* manager, GpuCommandBufferStub* stub, @@ -48,57 +48,53 @@ class TextureImageTransportSurface : protected: // ImageTransportSurface implementation. virtual void OnBufferPresented( - bool presented, + uint64 surface_handle, uint32 sync_point) OVERRIDE; virtual void OnResizeViewACK() OVERRIDE; - virtual void OnSetFrontSurfaceIsProtected( - bool is_protected, - uint32 protection_state_id) OVERRIDE; virtual void OnResize(gfx::Size size) OVERRIDE; // GpuCommandBufferStub::DestructionObserver implementation. virtual void OnWillDestroyStub(GpuCommandBufferStub* stub) OVERRIDE; private: - // A texture backing the front/back buffer in the parent stub. + // A texture backing the front/back buffer. struct Texture { Texture(); ~Texture(); - // The client-side id in the parent stub. - uint32 client_id; - // The currently allocated size. gfx::Size size; - // Whether or not that texture has been sent to the client yet. - bool sent_to_client; + // The actual GL texture id. + uint32 service_id; - // The texture info in the parent stub. - gpu::gles2::TextureManager::TextureInfo::Ref info; + // The surface handle for this texture (only 1 and 2 are valid). + uint64 surface_handle; }; virtual ~TextureImageTransportSurface(); - void CreateBackTexture(const gfx::Size& size); + void CreateBackTexture(); void AttachBackTextureToFBO(); - void ReleaseTexture(int id); - void ReleaseParentStub(); - void AdjustFrontBufferAllocation(); - void BufferPresentedImpl(bool presented); - int front() const { return front_; } - int back() const { return 1 - front_; } + void ReleaseBackTexture(); + void BufferPresentedImpl(uint64 surface_handle); + void ProduceTexture(Texture& texture); + void ConsumeTexture(Texture& texture); + + gpu::gles2::MailboxName& mailbox_name(uint64 surface_handle) { + DCHECK(surface_handle == 1 || surface_handle == 2); + return mailbox_names_[surface_handle - 1]; + } // The framebuffer that represents this surface (service id). Allocated lazily // in OnMakeCurrent. uint32 fbo_id_; - // The front and back buffers. - Texture textures_[2]; - - gfx::Rect previous_damage_rect_; + // The current backbuffer. + Texture backbuffer_; - // Indicates which of the 2 above is the front buffer. - int front_; + // The current size of the GLSurface. Used to disambiguate from the current + // texture size which might be outdated (since we use two buffers). + gfx::Size current_size_; // Whether or not the command buffer stub has been destroyed. bool stub_destroyed_; @@ -106,16 +102,15 @@ class TextureImageTransportSurface : bool backbuffer_suggested_allocation_; bool frontbuffer_suggested_allocation_; - bool frontbuffer_is_protected_; - uint32 protection_state_id_; - scoped_ptr<ImageTransportHelper> helper_; gfx::GLSurfaceHandle handle_; - GpuCommandBufferStub* parent_stub_; // The offscreen surface used to make the context current. However note that // the actual rendering is always redirected to an FBO. - scoped_refptr<GLSurface> surface_; + scoped_refptr<gfx::GLSurface> surface_; + + // Holds a reference to the underlying context for cleanup. + scoped_refptr<gfx::GLContext> context_; // Whether a SwapBuffers is pending. bool is_swap_buffers_pending_; @@ -123,9 +118,11 @@ class TextureImageTransportSurface : // Whether we unscheduled command buffer because of pending SwapBuffers. bool did_unschedule_; - // Whether or not the buffer flip went through browser side on the last - // swap or post sub buffer. - bool did_flip_; + // The mailbox names used for texture exchange. Uses surface_handle as key. + gpu::gles2::MailboxName mailbox_names_[2]; + + // Holds a reference to the mailbox manager for cleanup. + scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_; DISALLOW_COPY_AND_ASSIGN(TextureImageTransportSurface); }; |