diff options
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); }; |