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 | |
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
38 files changed, 712 insertions, 699 deletions
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc index fc1f4bf..f0e8326 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/content/browser/browser_plugin/browser_plugin_guest.cc @@ -363,10 +363,6 @@ void BrowserPluginGuest::SetCompositingBufferData(int gpu_process_id, surface_handle_ = gfx::GLSurfaceHandle(gfx::kNullPluginWindow, true); surface_handle_.parent_gpu_process_id = gpu_process_id; surface_handle_.parent_client_id = client_id; - surface_handle_.parent_context_id = context_id; - surface_handle_.parent_texture_id[0] = texture_id_0; - surface_handle_.parent_texture_id[1] = texture_id_1; - surface_handle_.sync_point = sync_point; } bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const { diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 633f6d3..ac85420 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc @@ -100,7 +100,7 @@ void SendGpuProcessMessage(GpuProcessHost::GpuProcessKind kind, void AcceleratedSurfaceBuffersSwappedCompletedForGPU(int host_id, int route_id, bool alive, - bool did_swap) { + uint64 surface_handle) { if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { BrowserThread::PostTask( BrowserThread::IO, @@ -109,7 +109,7 @@ void AcceleratedSurfaceBuffersSwappedCompletedForGPU(int host_id, host_id, route_id, alive, - did_swap)); + surface_handle)); return; } @@ -117,7 +117,7 @@ void AcceleratedSurfaceBuffersSwappedCompletedForGPU(int host_id, if (host) { if (alive) host->Send(new AcceleratedSurfaceMsg_BufferPresented( - route_id, did_swap, 0)); + route_id, surface_handle, 0)); else host->ForceShutdown(); } @@ -159,11 +159,12 @@ void AcceleratedSurfaceBuffersSwappedCompletedForRenderer( void AcceleratedSurfaceBuffersSwappedCompleted(int host_id, int route_id, int surface_id, + uint64 surface_handle, bool alive, base::TimeTicks timebase, base::TimeDelta interval) { AcceleratedSurfaceBuffersSwappedCompletedForGPU(host_id, route_id, - alive, true /* presented */); + alive, surface_handle); AcceleratedSurfaceBuffersSwappedCompletedForRenderer(surface_id, timebase, interval); } @@ -762,7 +763,7 @@ void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped( base::ScopedClosureRunner scoped_completion_runner( base::Bind(&AcceleratedSurfaceBuffersSwappedCompletedForGPU, host_id_, params.route_id, - true /* alive */, false /* presented */)); + true /* alive */, params.surface_handle)); int render_process_id = 0; int render_widget_id = 0; @@ -797,8 +798,8 @@ void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped( base::ScopedClosureRunner scoped_completion_runner( base::Bind(&AcceleratedSurfaceBuffersSwappedCompleted, - host_id_, params.route_id, params.surface_id, - true, base::TimeTicks(), base::TimeDelta())); + host_id_, params.route_id, params.surface_id, params.surface_handle, + true, base::TimeTicks(), base::TimeDelta())); gfx::PluginWindowHandle handle = GpuSurfaceTracker::Get()->GetSurfaceWindowHandle(params.surface_id); @@ -830,7 +831,8 @@ void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped( base::Bind(&AcceleratedSurfaceBuffersSwappedCompleted, host_id_, params.route_id, - params.surface_id)); + params.surface_id, + params.surface_handle)); } void GpuProcessHost::OnAcceleratedSurfacePostSubBuffer( diff --git a/content/browser/gpu/gpu_process_host_ui_shim.cc b/content/browser/gpu/gpu_process_host_ui_shim.cc index 4a991e0..d1f35dd 100644 --- a/content/browser/gpu/gpu_process_host_ui_shim.cc +++ b/content/browser/gpu/gpu_process_host_ui_shim.cc @@ -31,6 +31,11 @@ #include <gdk/gdkx.h> // NOLINT #endif +// From gl2/gl2ext.h. +#ifndef GL_MAILBOX_SIZE_CHROMIUM +#define GL_MAILBOX_SIZE_CHROMIUM 64 +#endif + namespace content { namespace { @@ -302,8 +307,14 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceNew( params.surface_id); if (!view) return; + + if (params.mailbox_name.length() && + params.mailbox_name.length() != GL_MAILBOX_SIZE_CHROMIUM) + return; + view->AcceleratedSurfaceNew( - params.width, params.height, params.surface_handle); + params.width, params.height, params.surface_handle, + params.mailbox_name); } static base::TimeDelta GetSwapDelay() { @@ -323,7 +334,9 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped( ScopedSendOnIOThread delayed_send( host_id_, - new AcceleratedSurfaceMsg_BufferPresented(params.route_id, false, 0)); + new AcceleratedSurfaceMsg_BufferPresented(params.route_id, + params.surface_handle, + 0)); RenderWidgetHostViewPort* view = GetRenderWidgetHostViewFromSurfaceID( params.surface_id); @@ -347,7 +360,9 @@ void GpuProcessHostUIShim::OnAcceleratedSurfacePostSubBuffer( ScopedSendOnIOThread delayed_send( host_id_, - new AcceleratedSurfaceMsg_BufferPresented(params.route_id, false, 0)); + new AcceleratedSurfaceMsg_BufferPresented(params.route_id, + params.surface_handle, + 0)); RenderWidgetHostViewPort* view = GetRenderWidgetHostViewFromSurfaceID(params.surface_id); @@ -378,7 +393,7 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceRelease( params.surface_id); if (!view) return; - view->AcceleratedSurfaceRelease(params.identifier); + view->AcceleratedSurfaceRelease(); } void GpuProcessHostUIShim::OnVideoMemoryUsageStatsReceived( diff --git a/content/browser/renderer_host/image_transport_factory.cc b/content/browser/renderer_host/image_transport_factory.cc index 7e3e6e3..0a1dc2c 100644 --- a/content/browser/renderer_host/image_transport_factory.cc +++ b/content/browser/renderer_host/image_transport_factory.cc @@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/observer_list.h" #include "base/threading/non_thread_safe.h" #include "cc/output_surface.h" @@ -27,6 +28,8 @@ #include "content/public/common/content_switches.h" #include "gpu/ipc/command_buffer_proxy.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h" +#include "third_party/khronos/GLES2/gl2.h" +#include "third_party/khronos/GLES2/gl2ext.h" #include "ui/compositor/compositor.h" #include "ui/compositor/compositor_setup.h" #include "ui/compositor/test_web_graphics_context_3d.h" @@ -65,7 +68,7 @@ class DefaultTransportFactory virtual scoped_refptr<ui::Texture> CreateTransportClient( const gfx::Size& size, float device_scale_factor, - uint64 transport_handle) OVERRIDE { + const std::string& mailbox_name) OVERRIDE { return NULL; } @@ -97,40 +100,6 @@ class DefaultTransportFactory DISALLOW_COPY_AND_ASSIGN(DefaultTransportFactory); }; -class ImageTransportClientTexture : public ui::Texture { - public: - ImageTransportClientTexture( - WebKit::WebGraphicsContext3D* host_context, - const gfx::Size& size, - float device_scale_factor, - uint64 surface_id) - : ui::Texture(true, size, device_scale_factor), - host_context_(host_context), - texture_id_(surface_id) { - } - - // ui::Texture overrides: - virtual unsigned int PrepareTexture() OVERRIDE { - return texture_id_; - } - - virtual WebKit::WebGraphicsContext3D* HostContext3D() OVERRIDE { - return host_context_; - } - - protected: - virtual ~ImageTransportClientTexture() {} - - private: - // A raw pointer. This |ImageTransportClientTexture| will be destroyed - // before the |host_context_| via - // |ImageTransportFactoryObserver::OnLostContext()| handlers. - WebKit::WebGraphicsContext3D* host_context_; - unsigned texture_id_; - - DISALLOW_COPY_AND_ASSIGN(ImageTransportClientTexture); -}; - class OwnedTexture : public ui::Texture, ImageTransportFactoryObserver { public: OwnedTexture(WebKit::WebGraphicsContext3D* host_context, @@ -163,7 +132,7 @@ class OwnedTexture : public ui::Texture, ImageTransportFactoryObserver { DeleteTexture(); } - private: + protected: void DeleteTexture() { if (texture_id_) { host_context_->deleteTexture(texture_id_); @@ -180,6 +149,53 @@ class OwnedTexture : public ui::Texture, ImageTransportFactoryObserver { DISALLOW_COPY_AND_ASSIGN(OwnedTexture); }; +class ImageTransportClientTexture : public OwnedTexture { + public: + ImageTransportClientTexture( + WebKit::WebGraphicsContext3D* host_context, + const gfx::Size& size, + float device_scale_factor, + const std::string& mailbox_name) + : OwnedTexture(host_context, + size, + device_scale_factor, + host_context->createTexture()), + mailbox_name_(mailbox_name) { + DCHECK(mailbox_name.size() == GL_MAILBOX_SIZE_CHROMIUM); + } + + virtual void Consume(const gfx::Size& new_size) OVERRIDE { + if (!mailbox_name_.length()) + return; + + DCHECK(host_context_ && texture_id_); + host_context_->bindTexture(GL_TEXTURE_2D, texture_id_); + host_context_->consumeTextureCHROMIUM( + GL_TEXTURE_2D, + reinterpret_cast<const signed char*>(mailbox_name_.c_str())); + size_ = new_size; + host_context_->flush(); + } + + virtual void Produce() OVERRIDE { + if (!mailbox_name_.length()) + return; + + DCHECK(host_context_ && texture_id_); + host_context_->bindTexture(GL_TEXTURE_2D, texture_id_); + host_context_->produceTextureCHROMIUM( + GL_TEXTURE_2D, + reinterpret_cast<const signed char*>(mailbox_name_.c_str())); + } + + protected: + virtual ~ImageTransportClientTexture() {} + + private: + std::string mailbox_name_; + DISALLOW_COPY_AND_ASSIGN(ImageTransportClientTexture); +}; + class GpuProcessTransportFactory; class CompositorSwapClient @@ -409,40 +425,24 @@ class GpuProcessTransportFactory : gfx::kNullPluginWindow, true); handle.parent_gpu_process_id = shared_context_->GetGPUProcessID(); handle.parent_client_id = shared_context_->GetChannelID(); - handle.parent_context_id = shared_context_->GetContextID(); - handle.parent_texture_id[0] = shared_context_->createTexture(); - handle.parent_texture_id[1] = shared_context_->createTexture(); - handle.sync_point = shared_context_->insertSyncPoint(); return handle; } virtual void DestroySharedSurfaceHandle( gfx::GLSurfaceHandle surface) OVERRIDE { - if (!shared_context_.get()) - return; - uint32 channel_id = shared_context_->GetChannelID(); - uint32 context_id = shared_context_->GetContextID(); - if (surface.parent_gpu_process_id != shared_context_->GetGPUProcessID() || - surface.parent_client_id != channel_id || - surface.parent_context_id != context_id) - return; - - shared_context_->deleteTexture(surface.parent_texture_id[0]); - shared_context_->deleteTexture(surface.parent_texture_id[1]); - shared_context_->flush(); } virtual scoped_refptr<ui::Texture> CreateTransportClient( const gfx::Size& size, float device_scale_factor, - uint64 transport_handle) { + const std::string& mailbox_name) { if (!shared_context_.get()) return NULL; scoped_refptr<ImageTransportClientTexture> image( new ImageTransportClientTexture(shared_context_.get(), size, device_scale_factor, - transport_handle)); + mailbox_name)); return image; } diff --git a/content/browser/renderer_host/image_transport_factory.h b/content/browser/renderer_host/image_transport_factory.h index 415f9e5..f081e20 100644 --- a/content/browser/renderer_host/image_transport_factory.h +++ b/content/browser/renderer_host/image_transport_factory.h @@ -5,6 +5,8 @@ #ifndef CONTENT_BROWSER_RENDERER_HOST_IMAGE_TRANSPORT_FACTORY_H_ #define CONTENT_BROWSER_RENDERER_HOST_IMAGE_TRANSPORT_FACTORY_H_ +#include <string> + #include "base/memory/ref_counted.h" #include "ui/gfx/native_widget_types.h" @@ -73,7 +75,7 @@ class ImageTransportFactory { virtual scoped_refptr<ui::Texture> CreateTransportClient( const gfx::Size& size, float device_scale_factor, - uint64 transport_handle) = 0; + const std::string& mailbox_name) = 0; // Variant of CreateTransportClient() that deletes the texture on the GPU when // the returned value is deleted. diff --git a/content/browser/renderer_host/image_transport_factory_android.cc b/content/browser/renderer_host/image_transport_factory_android.cc index a2b8f10..558e485 100644 --- a/content/browser/renderer_host/image_transport_factory_android.cc +++ b/content/browser/renderer_host/image_transport_factory_android.cc @@ -11,6 +11,7 @@ #include "content/common/gpu/client/gl_helper.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h" +#include "third_party/khronos/GLES2/gl2.h" #include "webkit/gpu/webgraphicscontext3d_in_process_impl.h" namespace content { @@ -30,6 +31,16 @@ class DirectGLImageTransportFactory : public ImageTransportFactoryAndroid { virtual void DestroySharedSurfaceHandle( const gfx::GLSurfaceHandle& handle) OVERRIDE {} virtual uint32_t InsertSyncPoint() OVERRIDE { return 0; } + virtual uint32_t CreateTexture() OVERRIDE { + return context_->createTexture(); + } + virtual void DeleteTexture(uint32_t id) OVERRIDE { + context_->deleteTexture(id); + } + virtual void AcquireTexture( + uint32 texture_id, const signed char* mailbox_name) OVERRIDE {} + virtual void ReleaseTexture( + uint32 texture_id, const signed char* mailbox_name) OVERRIDE {} virtual WebKit::WebGraphicsContext3D* GetContext3D() OVERRIDE { return context_.get(); } @@ -64,6 +75,12 @@ class CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid { virtual void DestroySharedSurfaceHandle( const gfx::GLSurfaceHandle& handle) OVERRIDE; virtual uint32_t InsertSyncPoint() OVERRIDE; + virtual uint32_t CreateTexture() OVERRIDE; + virtual void DeleteTexture(uint32_t id) OVERRIDE; + virtual void AcquireTexture( + uint32 texture_id, const signed char* mailbox_name) OVERRIDE; + virtual void ReleaseTexture( + uint32 texture_id, const signed char* mailbox_name) OVERRIDE; virtual WebKit::WebGraphicsContext3D* GetContext3D() OVERRIDE { return context_.get(); } @@ -105,11 +122,6 @@ CmdBufferImageTransportFactory::CreateSharedSurfaceHandle() { gfx::GLSurfaceHandle handle = gfx::GLSurfaceHandle( gfx::kNullPluginWindow, true); handle.parent_gpu_process_id = context_->GetGPUProcessID(); - handle.parent_client_id = context_->GetChannelID(); - handle.parent_context_id = context_->GetContextID(); - handle.parent_texture_id[0] = context_->createTexture(); - handle.parent_texture_id[1] = context_->createTexture(); - handle.sync_point = context_->insertSyncPoint(); context_->flush(); return handle; } @@ -120,16 +132,33 @@ void CmdBufferImageTransportFactory::DestroySharedSurfaceHandle( NOTREACHED() << "Failed to make shared graphics context current"; return; } - - context_->deleteTexture(handle.parent_texture_id[0]); - context_->deleteTexture(handle.parent_texture_id[1]); - context_->finish(); } uint32_t CmdBufferImageTransportFactory::InsertSyncPoint() { return context_->insertSyncPoint(); } +uint32_t CmdBufferImageTransportFactory::CreateTexture() { + return context_->createTexture(); +} + +void CmdBufferImageTransportFactory::DeleteTexture(uint32_t id) { + context_->deleteTexture(id); +} + +void CmdBufferImageTransportFactory::AcquireTexture( + uint32 texture_id, const signed char* mailbox_name) { + context_->bindTexture(GL_TEXTURE_2D, texture_id); + context_->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox_name); + context_->flush(); +} + +void CmdBufferImageTransportFactory::ReleaseTexture( + uint32 texture_id, const signed char* mailbox_name) { + context_->bindTexture(GL_TEXTURE_2D, texture_id); + context_->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox_name); +} + GLHelper* CmdBufferImageTransportFactory::GetGLHelper() { if (!gl_helper_.get()) gl_helper_.reset(new GLHelper(GetContext3D(), NULL)); diff --git a/content/browser/renderer_host/image_transport_factory_android.h b/content/browser/renderer_host/image_transport_factory_android.h index 669d516..57fc5f6 100644 --- a/content/browser/renderer_host/image_transport_factory_android.h +++ b/content/browser/renderer_host/image_transport_factory_android.h @@ -30,6 +30,12 @@ class ImageTransportFactoryAndroid { const gfx::GLSurfaceHandle& handle) = 0; virtual uint32_t InsertSyncPoint() = 0; + virtual uint32_t CreateTexture() = 0; + virtual void DeleteTexture(uint32_t id) = 0; + virtual void AcquireTexture( + uint32 texture_id, const signed char* mailbox_name) = 0; + virtual void ReleaseTexture( + uint32 texture_id, const signed char* mailbox_name) = 0; virtual WebKit::WebGraphicsContext3D* GetContext3D() = 0; virtual GLHelper* GetGLHelper() = 0; diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index b943bde..d50a905 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -1590,7 +1590,7 @@ void RenderProcessHostImpl::OnCompositorSurfaceBuffersSwappedNoHost( "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwappedNoHost"); RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id, gpu_process_host_id, - false, + surface_handle, 0); } diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 45a1cf1..9ada9e8 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -1512,7 +1512,7 @@ void RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped( if (!view_) { RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id, gpu_process_host_id, - false, + surface_handle, 0); return; } @@ -2292,11 +2292,11 @@ bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed) { // static void RenderWidgetHostImpl::AcknowledgeBufferPresent( - int32 route_id, int gpu_host_id, bool presented, uint32 sync_point) { + int32 route_id, int gpu_host_id, uint64 surface_handle, uint32 sync_point) { GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(gpu_host_id); if (ui_shim) ui_shim->Send(new AcceleratedSurfaceMsg_BufferPresented(route_id, - presented, + surface_handle, sync_point)); } @@ -2319,18 +2319,6 @@ void RenderWidgetHostImpl::ParentChanged(gfx::NativeViewId new_parent) { #endif } -// static -void RenderWidgetHostImpl::SendFrontSurfaceIsProtected( - bool is_protected, - uint32 protection_state_id, - int32 route_id, - int gpu_host_id) { - GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(gpu_host_id); - if (ui_shim) { - ui_shim->Send(new AcceleratedSurfaceMsg_SetFrontSurfaceIsProtected( - route_id, is_protected, protection_state_id)); - } -} #endif void RenderWidgetHostImpl::DelayedAutoResized() { diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 228789d..7c335f4 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h @@ -397,7 +397,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost, static void AcknowledgeBufferPresent( int32 route_id, int gpu_host_id, - bool presented, + uint64 surface_handle, uint32 sync_point); // Called by the view in response to AcceleratedSurfaceBuffersSwapped for @@ -410,15 +410,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost, // Called by the view when the parent changes. If a parent isn't available, // NULL is used. void ParentChanged(gfx::NativeViewId new_parent); - - // Called by the view in response to visibility changes: - // 1. After the front surface is guarenteed to no longer be in use by the ui - // (protected false), - // 2. When the ui expects to have a valid front surface (protected true). - static void SendFrontSurfaceIsProtected(bool is_protected, - uint32 protection_state_id, - int32 route_id, - int gpu_host_id); #endif // Signals that the compositing surface was updated, e.g. after a lost context diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index e37df9c..b912373 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc @@ -56,7 +56,8 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid( content_view_core_(NULL), ime_adapter_android_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), cached_background_color_(SK_ColorWHITE), - texture_id_in_layer_(0) { + texture_id_in_layer_(0), + current_buffer_id_(0) { if (CompositorImpl::UsesDirectGL()) { surface_texture_transport_.reset(new SurfaceTextureTransportClient()); layer_ = surface_texture_transport_->Initialize(); @@ -78,6 +79,10 @@ RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() { ImageTransportFactoryAndroid::GetInstance()->DestroySharedSurfaceHandle( shared_surface_); } + if (texture_id_in_layer_) { + ImageTransportFactoryAndroid::GetInstance()->DeleteTexture( + texture_id_in_layer_); + } } void RenderWidgetHostViewAndroid::InitAsChild(gfx::NativeView parent_view) { @@ -388,19 +393,42 @@ void RenderWidgetHostViewAndroid::OnAcceleratedCompositingStateChange() { void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped( const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, int gpu_host_id) { - texture_layer_->setTextureId(params.surface_handle); - DCHECK(texture_layer_ == layer_); - layer_->setBounds(params.size); - texture_id_in_layer_ = params.surface_handle; - texture_size_in_layer_ = params.size; + ImageTransportFactoryAndroid* factory = + ImageTransportFactoryAndroid::GetInstance(); // TODO(sievers): When running the impl thread in the browser we - // need to delay the ACK until after commit. + // need to delay the ACK until after commit and use more than a single + // texture. DCHECK(!CompositorImpl::IsThreadingEnabled()); + + uint64 previous_buffer = current_buffer_id_; + if (previous_buffer && texture_id_in_layer_) { + DCHECK(id_to_mailbox_.find(previous_buffer) != id_to_mailbox_.end()); + ImageTransportFactoryAndroid::GetInstance()->ReleaseTexture( + texture_id_in_layer_, + reinterpret_cast<const signed char*>( + id_to_mailbox_[previous_buffer].c_str())); + } + + current_buffer_id_ = params.surface_handle; + if (!texture_id_in_layer_) { + texture_id_in_layer_ = factory->CreateTexture(); + texture_layer_->setTextureId(texture_id_in_layer_); + } + + DCHECK(id_to_mailbox_.find(current_buffer_id_) != id_to_mailbox_.end()); + ImageTransportFactoryAndroid::GetInstance()->AcquireTexture( + texture_id_in_layer_, + reinterpret_cast<const signed char*>( + id_to_mailbox_[current_buffer_id_].c_str())); + texture_layer_->setNeedsDisplay(); + texture_layer_->setBounds(params.size); + texture_size_in_layer_ = params.size; + uint32 sync_point = ImageTransportFactoryAndroid::GetInstance()->InsertSyncPoint(); RenderWidgetHostImpl::AcknowledgeBufferPresent( - params.route_id, gpu_host_id, true, sync_point); + params.route_id, gpu_host_id, previous_buffer, sync_point); } void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer( @@ -413,6 +441,23 @@ void RenderWidgetHostViewAndroid::AcceleratedSurfaceSuspend() { NOTREACHED(); } +void RenderWidgetHostViewAndroid::AcceleratedSurfaceNew( + int32 width_in_pixel, int32 height_in_pixel, uint64 surface_id, + const std::string& mailbox_name) { + DCHECK(surface_id == 1 || surface_id == 2); + id_to_mailbox_[surface_id] = mailbox_name; +} + +void RenderWidgetHostViewAndroid::AcceleratedSurfaceRelease() { + // This tells us we should free the frontbuffer. + if (texture_id_in_layer_) { + texture_layer_->setTextureId(0); + ImageTransportFactoryAndroid::GetInstance()->DeleteTexture( + texture_id_in_layer_); + texture_id_in_layer_ = 0; + } +} + bool RenderWidgetHostViewAndroid::HasAcceleratedSurface( const gfx::Size& desired_size) { NOTREACHED(); diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index 9c950af..967dadf 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h @@ -5,6 +5,8 @@ #ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_ANDROID_H_ #define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_ANDROID_H_ +#include <map> + #include "base/compiler_specific.h" #include "base/i18n/rtl.h" #include "base/memory/scoped_ptr.h" @@ -101,6 +103,12 @@ class RenderWidgetHostViewAndroid : public RenderWidgetHostViewBase { const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, int gpu_host_id) OVERRIDE; virtual void AcceleratedSurfaceSuspend() OVERRIDE; + virtual void AcceleratedSurfaceNew( + int32 width_in_pixel, + int32 height_in_pixel, + uint64 surface_id, + const std::string& mailbox_name) OVERRIDE; + virtual void AcceleratedSurfaceRelease() OVERRIDE; virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE; virtual void SetBackground(const SkBitmap& background) OVERRIDE; virtual void CopyFromCompositingSurface( @@ -193,6 +201,12 @@ class RenderWidgetHostViewAndroid : public RenderWidgetHostViewBase { // Used for image transport when needing to share resources across threads. scoped_ptr<SurfaceTextureTransportClient> surface_texture_transport_; + typedef std::map<uint64, std::string> MailboxMap; + MailboxMap id_to_mailbox_; + + // The identifier of the previously received frame + uint64 current_buffer_id_; + DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAndroid); }; diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index ea0a015..f244484 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -47,7 +47,6 @@ #include "ui/base/hit_test.h" #include "ui/base/ime/input_method.h" #include "ui/base/ui_base_types.h" -#include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" #include "ui/gfx/canvas.h" #include "ui/gfx/display.h" @@ -59,6 +58,9 @@ #include "ui/base/win/hidden_window.h" #endif +using gfx::RectToSkIRect; +using gfx::SkIRectToRect; + using WebKit::WebScreenInfo; using WebKit::WebTouchEvent; @@ -275,6 +277,18 @@ class RenderWidgetHostViewAura::ResizeLock { DISALLOW_COPY_AND_ASSIGN(ResizeLock); }; +RenderWidgetHostViewAura::BufferPresentedParams::BufferPresentedParams( + int route_id, + int gpu_host_id, + uint64 surface_handle) + : route_id(route_id), + gpu_host_id(gpu_host_id), + surface_handle(surface_handle) { +} + +RenderWidgetHostViewAura::BufferPresentedParams::~BufferPresentedParams() { +} + //////////////////////////////////////////////////////////////////////////////// // RenderWidgetHostViewAura, public: @@ -291,10 +305,6 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host) has_composition_text_(false), device_scale_factor_(1.0f), current_surface_(0), - current_surface_is_protected_(true), - current_surface_in_use_by_compositor_(true), - protection_state_id_(0), - surface_route_id_(0), paint_canvas_(NULL), synthetic_move_sent_(false), accelerated_compositing_state_changed_(false), @@ -395,8 +405,6 @@ void RenderWidgetHostViewAura::WasShown() { released_front_lock_ = GetCompositor()->GetCompositorLock(); } - AdjustSurfaceProtection(); - #if defined(OS_WIN) LPARAM lparam = reinterpret_cast<LPARAM>(this); EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam); @@ -410,14 +418,6 @@ void RenderWidgetHostViewAura::WasHidden() { released_front_lock_ = NULL; - if (ShouldReleaseFrontSurface() && - host_->is_accelerated_compositing_active()) { - current_surface_ = 0; - UpdateExternalTexture(); - } - - AdjustSurfaceProtection(); - #if defined(OS_WIN) aura::RootWindow* root_window = window_->GetRootWindow(); if (root_window) { @@ -725,7 +725,7 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurface( output->GetBitmap().getPixels()); scoped_callback_runner.Release(); // Wrap the callback with an internal handler so that we can inject our - // own completion handlers (where we can call AdjustSurfaceProtection). + // own completion handlers (where we can try to free the frontbuffer). base::Callback<void(bool)> wrapper_callback = base::Bind( &RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinished, AsWeakPtr(), @@ -758,16 +758,13 @@ void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() { accelerated_compositing_state_changed_ = true; } -bool RenderWidgetHostViewAura::ShouldFastACK(uint64 surface_id) { - ui::Texture* container = image_transport_clients_[surface_id]; - DCHECK(container); - +bool RenderWidgetHostViewAura::ShouldSkipFrame(const gfx::Size& size) { if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME || can_lock_compositor_ == NO_PENDING_COMMIT || resize_locks_.empty()) return false; - gfx::Size container_size = ConvertSizeToDIP(this, container->size()); + gfx::Size container_size = ConvertSizeToDIP(this, size); ResizeLockList::iterator it = resize_locks_.begin(); while (it != resize_locks_.end()) { if ((*it)->expected_size() == container_size) @@ -790,7 +787,6 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() { if (current_surface_ != 0 && host_->is_accelerated_compositing_active()) { ui::Texture* container = image_transport_clients_[current_surface_]; window_->SetExternalTexture(container); - current_surface_in_use_by_compositor_ = true; if (!container) { resize_locks_.clear(); @@ -826,120 +822,132 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() { } } else { window_->SetExternalTexture(NULL); - if (ShouldReleaseFrontSurface() && - host_->is_accelerated_compositing_active()) { - // We need to wait for a commit to clear to guarantee that all we - // will not issue any more GL referencing the previous surface. - ui::Compositor* compositor = GetCompositor(); - if (compositor) { - can_lock_compositor_ = NO_PENDING_COMMIT; - on_compositing_did_commit_callbacks_.push_back( - base::Bind(&RenderWidgetHostViewAura:: - SetSurfaceNotInUseByCompositor, - AsWeakPtr())); - if (!compositor->HasObserver(this)) - compositor->AddObserver(this); - } - } resize_locks_.clear(); } } -void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped( - const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel, - int gpu_host_id) { - surface_route_id_ = params_in_pixel.route_id; - // If protection state changed, then this swap is stale. We must still ACK but - // do not update current_surface_ since it may have been discarded. - if (params_in_pixel.protection_state_id && - params_in_pixel.protection_state_id != protection_state_id_) { - DCHECK(!current_surface_); - if (!params_in_pixel.skip_ack) - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL); - return; +bool RenderWidgetHostViewAura::SwapBuffersPrepare( + const gfx::Rect& surface_rect, + const gfx::Rect& damage_rect, + BufferPresentedParams* params) { + DCHECK(params->surface_handle); + DCHECK(!params->texture_to_produce); + + if (last_swapped_surface_size_ != surface_rect.size()) { + // The surface could have shrunk since we skipped an update, in which + // case we can expect a full update. + DLOG_IF(ERROR, damage_rect != surface_rect) << "Expected full damage rect"; + skipped_damage_.setEmpty(); + last_swapped_surface_size_ = surface_rect.size(); } - if (ShouldFastACK(params_in_pixel.surface_handle)) { - if (!params_in_pixel.skip_ack) - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL); - return; + if (ShouldSkipFrame(surface_rect.size())) { + skipped_damage_.op(RectToSkIRect(damage_rect), SkRegion::kUnion_Op); + InsertSyncPointAndACK(*params); + return false; } - current_surface_ = params_in_pixel.surface_handle; - // If we don't require an ACK that means the content is not a fresh updated - // new frame, rather we are just resetting our handle to some old content - // that we still hadn't discarded. Although we could display immediately, - // by not resetting the compositor lock here, we give us some time to get - // a fresh frame which means fewer content flashes. - if (!params_in_pixel.skip_ack) - released_front_lock_ = NULL; + DCHECK(!current_surface_ || image_transport_clients_.find(current_surface_) != + image_transport_clients_.end()); + if (current_surface_) + params->texture_to_produce = image_transport_clients_[current_surface_]; + + std::swap(current_surface_, params->surface_handle); + DCHECK(image_transport_clients_.find(current_surface_) != + image_transport_clients_.end()); + + image_transport_clients_[current_surface_]->Consume(surface_rect.size()); + released_front_lock_ = NULL; UpdateExternalTexture(); + return true; +} + +void RenderWidgetHostViewAura::SwapBuffersCompleted( + const BufferPresentedParams& params) { ui::Compositor* compositor = GetCompositor(); if (!compositor) { - if (!params_in_pixel.skip_ack) - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, true, NULL); + InsertSyncPointAndACK(params); } else { - DCHECK(image_transport_clients_.find(params_in_pixel.surface_handle) != - image_transport_clients_.end()); - gfx::Size surface_size_in_pixel = - image_transport_clients_[params_in_pixel.surface_handle]->size(); - gfx::Size surface_size = ConvertSizeToDIP(this, surface_size_in_pixel); - window_->SchedulePaintInRect(gfx::Rect(surface_size)); + // Add sending an ACK to the list of things to do OnCompositingDidCommit + can_lock_compositor_ = NO_PENDING_COMMIT; + on_compositing_did_commit_callbacks_.push_back( + base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK, params)); + if (!compositor->HasObserver(this)) + compositor->AddObserver(this); + } +} - if (!params_in_pixel.skip_ack) { - // Add sending an ACK to the list of things to do OnCompositingDidCommit - can_lock_compositor_ = NO_PENDING_COMMIT; - on_compositing_did_commit_callbacks_.push_back( - base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK, - params_in_pixel.route_id, - gpu_host_id, - true)); - if (!compositor->HasObserver(this)) - compositor->AddObserver(this); - } +void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped( + const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel, + int gpu_host_id) { + const gfx::Rect surface_rect = gfx::Rect(gfx::Point(), params_in_pixel.size); + BufferPresentedParams ack_params( + params_in_pixel.route_id, gpu_host_id, params_in_pixel.surface_handle); + if (!SwapBuffersPrepare(surface_rect, surface_rect, &ack_params)) + return; + + previous_damage_.setRect(RectToSkIRect(surface_rect)); + skipped_damage_.setEmpty(); + + ui::Compositor* compositor = GetCompositor(); + if (compositor) { + gfx::Size surface_size = ConvertSizeToDIP(this, params_in_pixel.size); + window_->SchedulePaintInRect(gfx::Rect(surface_size)); } + + SwapBuffersCompleted(ack_params); } void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer( const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel, int gpu_host_id) { - surface_route_id_ = params_in_pixel.route_id; - // If visible state changed, then this PSB is stale. We must still ACK but - // do not update current_surface_. - if (params_in_pixel.protection_state_id && - params_in_pixel.protection_state_id != protection_state_id_) { - DCHECK(!current_surface_); - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL); + const gfx::Rect surface_rect = + gfx::Rect(gfx::Point(), params_in_pixel.surface_size); + gfx::Rect damage_rect(params_in_pixel.x, + params_in_pixel.y, + params_in_pixel.width, + params_in_pixel.height); + BufferPresentedParams ack_params( + params_in_pixel.route_id, gpu_host_id, params_in_pixel.surface_handle); + if (!SwapBuffersPrepare(surface_rect, damage_rect, &ack_params)) return; - } - if (ShouldFastACK(params_in_pixel.surface_handle)) { - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL); - return; + SkRegion damage(RectToSkIRect(damage_rect)); + if (!skipped_damage_.isEmpty()) { + damage.op(skipped_damage_, SkRegion::kUnion_Op); + skipped_damage_.setEmpty(); } - current_surface_ = params_in_pixel.surface_handle; - released_front_lock_ = NULL; - DCHECK(current_surface_); - UpdateExternalTexture(); + DCHECK(surface_rect.Contains(SkIRectToRect(damage.getBounds()))); + ui::Texture* current_texture = image_transport_clients_[current_surface_]; - ui::Compositor* compositor = GetCompositor(); - if (!compositor) { - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, true, NULL); - } else { - DCHECK(image_transport_clients_.find(params_in_pixel.surface_handle) != - image_transport_clients_.end()); - gfx::Size surface_size_in_pixel = - image_transport_clients_[params_in_pixel.surface_handle]->size(); + const gfx::Size surface_size_in_pixel = params_in_pixel.surface_size; + DLOG_IF(ERROR, ack_params.texture_to_produce && + ack_params.texture_to_produce->size() != current_texture->size() && + SkIRectToRect(damage.getBounds()) != surface_rect) << + "Expected full damage rect after size change"; + if (ack_params.texture_to_produce && !previous_damage_.isEmpty() && + ack_params.texture_to_produce->size() == current_texture->size()) { + ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); + GLHelper* gl_helper = factory->GetGLHelper(); + gl_helper->CopySubBufferDamage( + current_texture->PrepareTexture(), + ack_params.texture_to_produce->PrepareTexture(), + damage, + previous_damage_); + } + previous_damage_ = damage; + ui::Compositor* compositor = GetCompositor(); + if (compositor) { // Co-ordinates come in OpenGL co-ordinate space. // We need to convert to layer space. gfx::Rect rect_to_paint = ConvertRectToDIP(this, gfx::Rect( params_in_pixel.x, surface_size_in_pixel.height() - params_in_pixel.y - - params_in_pixel.height, + params_in_pixel.height, params_in_pixel.width, params_in_pixel.height)); @@ -949,17 +957,9 @@ void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer( rect_to_paint.Intersect(window_->bounds()); window_->SchedulePaintInRect(rect_to_paint); - - // Add sending an ACK to the list of things to do OnCompositingDidCommit - can_lock_compositor_ = NO_PENDING_COMMIT; - on_compositing_did_commit_callbacks_.push_back( - base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK, - params_in_pixel.route_id, - gpu_host_id, - true)); - if (!compositor->HasObserver(this)) - compositor->AddObserver(this); } + + SwapBuffersCompleted(ack_params); } void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() { @@ -978,60 +978,45 @@ bool RenderWidgetHostViewAura::HasAcceleratedSurface( void RenderWidgetHostViewAura::AcceleratedSurfaceNew( int32 width_in_pixel, int32 height_in_pixel, - uint64 surface_handle) { + uint64 surface_handle, + const std::string& mailbox_name) { ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); scoped_refptr<ui::Texture> surface(factory->CreateTransportClient( gfx::Size(width_in_pixel, height_in_pixel), device_scale_factor_, - surface_handle)); + mailbox_name)); if (!surface) { LOG(ERROR) << "Failed to create ImageTransport texture"; return; } - image_transport_clients_[surface_handle] = surface; } -void RenderWidgetHostViewAura::AcceleratedSurfaceRelease( - uint64 surface_handle) { - DCHECK(image_transport_clients_.find(surface_handle) != - image_transport_clients_.end()); - if (current_surface_ == surface_handle) { +void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() { + // This really tells us to release the frontbuffer. + if (current_surface_ && ShouldReleaseFrontSurface()) { + ui::Compositor* compositor = GetCompositor(); + if (compositor) { + // We need to wait for a commit to clear to guarantee that all we + // will not issue any more GL referencing the previous surface. + can_lock_compositor_ = NO_PENDING_COMMIT; + scoped_refptr<ui::Texture> surface_ref = + image_transport_clients_[current_surface_]; + on_compositing_did_commit_callbacks_.push_back( + base::Bind(&RenderWidgetHostViewAura:: + SetSurfaceNotInUseByCompositor, + AsWeakPtr(), + surface_ref)); + if (!compositor->HasObserver(this)) + compositor->AddObserver(this); + } + image_transport_clients_.erase(current_surface_); current_surface_ = 0; UpdateExternalTexture(); } - image_transport_clients_.erase(surface_handle); } -void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor(ui::Compositor*) { - if (current_surface_ || !host_->is_hidden()) - return; - current_surface_in_use_by_compositor_ = false; - AdjustSurfaceProtection(); -} - -void RenderWidgetHostViewAura::AdjustSurfaceProtection() { - // If the current surface is non null, it is protected. - // If we are visible, it is protected. - // Otherwise, change to not proctected once done thumbnailing and compositing. - bool surface_is_protected = - current_surface_ || - !host_->is_hidden() || - (current_surface_is_protected_ && - (pending_thumbnail_tasks_ > 0 || - current_surface_in_use_by_compositor_)); - if (current_surface_is_protected_ == surface_is_protected) - return; - current_surface_is_protected_ = surface_is_protected; - ++protection_state_id_; - - if (!surface_route_id_ || !shared_surface_handle_.parent_gpu_process_id) - return; - - RenderWidgetHostImpl::SendFrontSurfaceIsProtected( - surface_is_protected, - protection_state_id_, - surface_route_id_, - shared_surface_handle_.parent_gpu_process_id); +void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor( + scoped_refptr<ui::Texture>) { } void RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinished( @@ -1043,7 +1028,6 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinished( if (!render_widget_host_view.get()) return; --render_widget_host_view->pending_thumbnail_tasks_; - render_widget_host_view->AdjustSurfaceProtection(); } void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) { @@ -1763,7 +1747,7 @@ void RenderWidgetHostViewAura::OnCompositingDidCommit( if ((*it)->GrabDeferredLock()) can_lock_compositor_ = YES_DID_LOCK; } - RunCompositingDidCommitCallbacks(compositor); + RunCompositingDidCommitCallbacks(); locks_pending_commit_.clear(); } @@ -1794,10 +1778,6 @@ void RenderWidgetHostViewAura::OnCompositingLockStateChanged( void RenderWidgetHostViewAura::OnLostResources() { image_transport_clients_.clear(); current_surface_ = 0; - protection_state_id_ = 0; - current_surface_is_protected_ = true; - current_surface_in_use_by_compositor_ = true; - surface_route_id_ = 0; UpdateExternalTexture(); locks_pending_commit_.clear(); @@ -1939,30 +1919,28 @@ bool RenderWidgetHostViewAura::ShouldMoveToCenter() { global_mouse_position_.y() > rect.bottom() - border_y; } -void RenderWidgetHostViewAura::RunCompositingDidCommitCallbacks( - ui::Compositor* compositor) { - for (std::vector< base::Callback<void(ui::Compositor*)> >::const_iterator +void RenderWidgetHostViewAura::RunCompositingDidCommitCallbacks() { + for (std::vector<base::Closure>::const_iterator it = on_compositing_did_commit_callbacks_.begin(); it != on_compositing_did_commit_callbacks_.end(); ++it) { - it->Run(compositor); + it->Run(); } on_compositing_did_commit_callbacks_.clear(); } // static void RenderWidgetHostViewAura::InsertSyncPointAndACK( - int32 route_id, int gpu_host_id, bool presented, - ui::Compositor* compositor) { + const BufferPresentedParams& params) { uint32 sync_point = 0; - // If we have no compositor, so we must still send the ACK. A zero - // sync point will not be waited for in the GPU process. - if (compositor) { - ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); - sync_point = factory->InsertSyncPoint(); + // If we produced a texture, we have to synchronize with the consumer of + // that texture. + if (params.texture_to_produce) { + params.texture_to_produce->Produce(); + sync_point = ImageTransportFactory::GetInstance()->InsertSyncPoint(); } RenderWidgetHostImpl::AcknowledgeBufferPresent( - route_id, gpu_host_id, presented, sync_point); + params.route_id, params.gpu_host_id, params.surface_handle, sync_point); } void RenderWidgetHostViewAura::AddingToRootWindow() { @@ -1979,7 +1957,7 @@ void RenderWidgetHostViewAura::RemovingFromRootWindow() { // frame though, because we will reissue a new frame right away without that // composited data. ui::Compositor* compositor = GetCompositor(); - RunCompositingDidCommitCallbacks(compositor); + RunCompositingDidCommitCallbacks(); locks_pending_commit_.clear(); if (compositor && compositor->HasObserver(this)) compositor->RemoveObserver(this); diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index 42e9fec..9a6fd26 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h @@ -12,13 +12,16 @@ #include "base/gtest_prod_util.h" #include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "content/browser/renderer_host/image_transport_factory.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/common/content_export.h" +#include "third_party/skia/include/core/SkRegion.h" #include "ui/aura/client/activation_delegate.h" #include "ui/aura/window_delegate.h" #include "ui/base/ime/text_input_client.h" +#include "ui/compositor/compositor.h" #include "ui/compositor/compositor_observer.h" #include "ui/gfx/display_observer.h" #include "ui/gfx/rect.h" @@ -121,11 +124,11 @@ class RenderWidgetHostViewAura int gpu_host_id) OVERRIDE; virtual void AcceleratedSurfaceSuspend() OVERRIDE; virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE; - virtual void AcceleratedSurfaceNew( - int32 width_in_pixel, - int32 height_in_pixel, - uint64 surface_id) OVERRIDE; - virtual void AcceleratedSurfaceRelease(uint64 surface_id) OVERRIDE; + virtual void AcceleratedSurfaceNew(int32 width_in_pixel, + int32 height_in_pixel, + uint64 surface_id, + const std::string& mailbox_name) OVERRIDE; + virtual void AcceleratedSurfaceRelease() OVERRIDE; virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE; virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE; virtual void ProcessAckedTouchEvent( @@ -231,7 +234,7 @@ class RenderWidgetHostViewAura virtual ~RenderWidgetHostViewAura(); void UpdateCursorIfOverSelf(); - bool ShouldFastACK(uint64 surface_id); + bool ShouldSkipFrame(const gfx::Size& size); void UpdateExternalTexture(); ui::InputMethod* GetInputMethod() const; @@ -255,14 +258,23 @@ class RenderWidgetHostViewAura bool ShouldMoveToCenter(); // Run the compositing callbacks. - void RunCompositingDidCommitCallbacks(ui::Compositor* compositor); + void RunCompositingDidCommitCallbacks(); + + struct BufferPresentedParams { + BufferPresentedParams(int route_id, + int gpu_host_id, + uint64 surface_handle); + ~BufferPresentedParams(); + + int32 route_id; + int gpu_host_id; + uint64 surface_handle; + scoped_refptr<ui::Texture> texture_to_produce; + }; // Insert a sync point into the compositor's command stream and acknowledge // that we have presented the accelerated surface buffer. - static void InsertSyncPointAndACK(int32 route_id, - int gpu_host_id, - bool presented, - ui::Compositor* compositor); + static void InsertSyncPointAndACK(const BufferPresentedParams& params); // Called when window_ gets added to a new window tree. void AddingToRootWindow(); @@ -270,15 +282,9 @@ class RenderWidgetHostViewAura // Called when window_ is removed from the window tree. void RemovingFromRootWindow(); - // After clearing |current_surface_|, and waiting for the compositor to finish - // using it, call this to inform the gpu process. - void SetSurfaceNotInUseByCompositor(ui::Compositor* compositor); - - // This is called every time |current_surface_| usage changes (by thumbnailer, - // compositor draws, and tab visibility). Every time usage of current surface - // changes between "may be used" and "certain to not be used" by the ui, we - // inform the gpu process. - void AdjustSurfaceProtection(); + // Called after commit for the last reference to the texture going away + // after it was released as the frontbuffer. + void SetSurfaceNotInUseByCompositor(scoped_refptr<ui::Texture>); // Called after async thumbnailer task completes. Used to call // AdjustSurfaceProtection. @@ -295,6 +301,12 @@ class RenderWidgetHostViewAura // Converts |rect| from window coordinate to screen coordinate. gfx::Rect ConvertRectToScreen(const gfx::Rect& rect); + bool SwapBuffersPrepare(const gfx::Rect& surface_rect, + const gfx::Rect& damage_rect, + BufferPresentedParams* params); + + void SwapBuffersCompleted(const BufferPresentedParams& params); + // The model object. RenderWidgetHostImpl* host_; @@ -347,27 +359,25 @@ class RenderWidgetHostViewAura // The scale factor of the display the renderer is currently on. float device_scale_factor_; - std::vector< base::Callback<void(ui::Compositor*)> > - on_compositing_did_commit_callbacks_; + std::vector<base::Closure> on_compositing_did_commit_callbacks_; - std::map<uint64, scoped_refptr<ui::Texture> > - image_transport_clients_; + std::map<uint64, scoped_refptr<ui::Texture> > image_transport_clients_; + // The identifier of the current frontbuffer. uint64 current_surface_; - // Protected means that the |current_surface_| may be in use by ui and cannot - // be safely discarded. Things to consider are thumbnailer, compositor draw, - // and tab visibility. - bool current_surface_is_protected_; - bool current_surface_in_use_by_compositor_; + // The damage in the previously presented buffer. + SkRegion previous_damage_; - int pending_thumbnail_tasks_; + // Pending damage from previous frames that we skipped. + SkRegion skipped_damage_; - // This id increments every time surface_is_protected changes. We tag IPC - // messages which rely on protection state with this id to stay in sync. - uint32 protection_state_id_; + // The size of the last frame that was swapped (even if we skipped it). + // Used to determine when the skipped_damage_ needs to be reset due to + // size changes between front- and backbuffer. + gfx::Size last_swapped_surface_size_; - int32 surface_route_id_; + int pending_thumbnail_tasks_; gfx::GLSurfaceHandle shared_surface_handle_; diff --git a/content/browser/renderer_host/render_widget_host_view_gtk.cc b/content/browser/renderer_host/render_widget_host_view_gtk.cc index 5120764..70ab67c 100644 --- a/content/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/content/browser/renderer_host/render_widget_host_view_gtk.cc @@ -1057,14 +1057,14 @@ void RenderWidgetHostViewGtk::AcceleratedSurfaceBuffersSwapped( const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, int gpu_host_id) { RenderWidgetHostImpl::AcknowledgeBufferPresent( - params.route_id, gpu_host_id, true, 0); + params.route_id, gpu_host_id, params.surface_handle, 0); } void RenderWidgetHostViewGtk::AcceleratedSurfacePostSubBuffer( const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params, int gpu_host_id) { RenderWidgetHostImpl::AcknowledgeBufferPresent( - params.route_id, gpu_host_id, true, 0); + params.route_id, gpu_host_id, params.surface_handle, 0); } void RenderWidgetHostViewGtk::AcceleratedSurfaceSuspend() { diff --git a/content/browser/renderer_host/render_widget_host_view_guest.cc b/content/browser/renderer_host/render_widget_host_view_guest.cc index b9adaff..fcad0fe 100644 --- a/content/browser/renderer_host/render_widget_host_view_guest.cc +++ b/content/browser/renderer_host/render_widget_host_view_guest.cc @@ -201,9 +201,11 @@ void RenderWidgetHostViewGuest::CopyFromCompositingSurface( NOTIMPLEMENTED(); } -void RenderWidgetHostViewGuest::AcceleratedSurfaceNew(int32 width_in_pixel, - int32 height_in_pixel, - uint64 surface_handle) { +void RenderWidgetHostViewGuest::AcceleratedSurfaceNew( + int32 width_in_pixel, + int32 height_in_pixel, + uint64 surface_handle, + const std::string& mailbox_name) { NOTIMPLEMENTED(); } diff --git a/content/browser/renderer_host/render_widget_host_view_guest.h b/content/browser/renderer_host/render_widget_host_view_guest.h index 2f2947a..b2b0088 100644 --- a/content/browser/renderer_host/render_widget_host_view_guest.h +++ b/content/browser/renderer_host/render_widget_host_view_guest.h @@ -104,7 +104,8 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE; virtual void AcceleratedSurfaceNew(int32 width_in_pixel, int32 height_in_pixel, - uint64 surface_id) OVERRIDE; + uint64 surface_id, + const std::string& mailbox_name) OVERRIDE; virtual void SetHasHorizontalScrollbar( bool has_horizontal_scrollbar) OVERRIDE; virtual void SetScrollOffsetPinning( diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 5c2244a..724884b 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm @@ -1088,7 +1088,7 @@ void RenderWidgetHostViewMac::AckPendingSwapBuffers() { RenderWidgetHostImpl::AcknowledgeBufferPresent( pending_swap_buffers_acks_.front().first, pending_swap_buffers_acks_.front().second, - true, + 0, 0); if (render_widget_host_) { render_widget_host_->AcknowledgeSwapBuffersToRenderer(); diff --git a/content/browser/renderer_host/test_render_view_host.h b/content/browser/renderer_host/test_render_view_host.h index 6d1c60d..d65f897 100644 --- a/content/browser/renderer_host/test_render_view_host.h +++ b/content/browser/renderer_host/test_render_view_host.h @@ -167,12 +167,6 @@ class TestRenderWidgetHostView : public RenderWidgetHostViewBase { virtual void SetScrollOffsetPinning( bool is_pinned_to_left, bool is_pinned_to_right) OVERRIDE { } -#if defined(USE_AURA) - virtual void AcceleratedSurfaceNew( - int32 width, int32 height, uint64 surface_id) OVERRIDE { } - virtual void AcceleratedSurfaceRelease(uint64 surface_id) OVERRIDE { } -#endif - #if defined(TOOLKIT_GTK) virtual void CreatePluginContainer(gfx::PluginWindowHandle id) OVERRIDE { } virtual void DestroyPluginContainer(gfx::PluginWindowHandle id) OVERRIDE { } 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); }; diff --git a/content/port/browser/render_widget_host_view_port.h b/content/port/browser/render_widget_host_view_port.h index 6d4806a..9fe93ac 100644 --- a/content/port/browser/render_widget_host_view_port.h +++ b/content/port/browser/render_widget_host_view_port.h @@ -244,8 +244,9 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView { virtual void AcceleratedSurfaceNew( int32 width_in_pixel, int32 height_in_pixel, - uint64 surface_id) {} - virtual void AcceleratedSurfaceRelease(uint64 surface_id) {} + uint64 surface_id, + const std::string& mailbox_name) {} + virtual void AcceleratedSurfaceRelease() {} #if defined(TOOLKIT_GTK) virtual void CreatePluginContainer(gfx::PluginWindowHandle id) = 0; diff --git a/gpu/command_buffer/service/mailbox_manager.cc b/gpu/command_buffer/service/mailbox_manager.cc index ec7ad94..9019393 100644 --- a/gpu/command_buffer/service/mailbox_manager.cc +++ b/gpu/command_buffer/service/mailbox_manager.cc @@ -4,6 +4,8 @@ #include "gpu/command_buffer/service/mailbox_manager.h" +#include <algorithm> + #include "base/rand_util.h" #include "crypto/hmac.h" #include "gpu/command_buffer/service/gl_utils.h" @@ -12,6 +14,11 @@ namespace gpu { namespace gles2 { +MailboxName::MailboxName() { + std::fill(key, key + sizeof(key), 0); + std::fill(signature, signature + sizeof(signature), 0); +} + MailboxManager::MailboxManager() : hmac_(crypto::HMAC::SHA256), textures_(std::ptr_fun(&MailboxManager::TargetNameLess)) { @@ -19,9 +26,11 @@ MailboxManager::MailboxManager() bool success = hmac_.Init( base::StringPiece(private_key_, sizeof(private_key_))); DCHECK(success); + DCHECK(!IsMailboxNameValid(MailboxName())); } MailboxManager::~MailboxManager() { + DCHECK(!textures_.size()); } void MailboxManager::GenerateMailboxName(MailboxName* name) { @@ -36,10 +45,8 @@ TextureDefinition* MailboxManager::ConsumeTexture(unsigned target, TextureDefinitionMap::iterator it = textures_.find(TargetName(target, name)); - if (it == textures_.end()) { - NOTREACHED(); + if (it == textures_.end()) return NULL; - } TextureDefinition* definition = it->second.definition.release(); textures_.erase(it); diff --git a/gpu/command_buffer/service/mailbox_manager.h b/gpu/command_buffer/service/mailbox_manager.h index 337998d..8f97dd4 100644 --- a/gpu/command_buffer/service/mailbox_manager.h +++ b/gpu/command_buffer/service/mailbox_manager.h @@ -30,7 +30,8 @@ class TextureManager; // Identifies a mailbox where a texture definition can be stored for // transferring textures between contexts that are not in the same context // group. It is a random key signed with a hash of a private key. -struct MailboxName { +struct GPU_EXPORT MailboxName { + MailboxName(); GLbyte key[GL_MAILBOX_SIZE_CHROMIUM / 2]; GLbyte signature[GL_MAILBOX_SIZE_CHROMIUM / 2]; }; diff --git a/gpu/command_buffer/service/texture_definition.cc b/gpu/command_buffer/service/texture_definition.cc index aba0dfa..e1c606f 100644 --- a/gpu/command_buffer/service/texture_definition.cc +++ b/gpu/command_buffer/service/texture_definition.cc @@ -27,6 +27,18 @@ TextureDefinition::LevelInfo::LevelInfo(GLenum target, cleared(cleared) { } +TextureDefinition::LevelInfo::LevelInfo() + : target(0), + internal_format(0), + width(0), + height(0), + depth(0), + border(0), + format(0), + type(0), + cleared(true) { +} + TextureDefinition::TextureDefinition(GLenum target, GLuint service_id, GLenum min_filter, diff --git a/gpu/command_buffer/service/texture_definition.h b/gpu/command_buffer/service/texture_definition.h index 0a9910b..7f7d3cd 100644 --- a/gpu/command_buffer/service/texture_definition.h +++ b/gpu/command_buffer/service/texture_definition.h @@ -19,7 +19,7 @@ namespace gles2 { // context using the same GLShareGroup with the corresponding service ID. class GPU_EXPORT TextureDefinition { public: - struct LevelInfo { + struct GPU_EXPORT LevelInfo { LevelInfo(GLenum target, GLenum internal_format, GLsizei width, @@ -29,6 +29,8 @@ class GPU_EXPORT TextureDefinition { GLenum format, GLenum type, bool cleared); + LevelInfo(); + GLenum target; GLenum internal_format; GLsizei width; diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index bc8491e..bdeea58 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc @@ -196,8 +196,8 @@ WebKit::WebGraphicsContext3D* DefaultContextFactory::CreateContextCommon( } Texture::Texture(bool flipped, const gfx::Size& size, float device_scale_factor) - : flipped_(flipped), - size_(size), + : size_(size), + flipped_(flipped), device_scale_factor_(device_scale_factor) { } diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index fa621a3..1a2324f 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h @@ -112,14 +112,17 @@ class COMPOSITOR_EXPORT Texture : public base::RefCounted<Texture> { virtual unsigned int PrepareTexture() = 0; virtual WebKit::WebGraphicsContext3D* HostContext3D() = 0; + virtual void Consume(const gfx::Size& new_size) {} + virtual void Produce() {} + protected: virtual ~Texture(); + gfx::Size size_; // in pixel private: friend class base::RefCounted<Texture>; bool flipped_; - gfx::Size size_; // in pixel float device_scale_factor_; DISALLOW_COPY_AND_ASSIGN(Texture); diff --git a/ui/gfx/native_widget_types.h b/ui/gfx/native_widget_types.h index 6dbc4e7..22a6756 100644 --- a/ui/gfx/native_widget_types.h +++ b/ui/gfx/native_widget_types.h @@ -278,30 +278,19 @@ struct GLSurfaceHandle { : handle(kNullPluginWindow), transport(false), parent_gpu_process_id(0), - parent_client_id(0), - parent_context_id(0), - sync_point(0) { - parent_texture_id[0] = 0; - parent_texture_id[1] = 0; + parent_client_id(0) { } GLSurfaceHandle(PluginWindowHandle handle_, bool transport_) : handle(handle_), transport(transport_), parent_gpu_process_id(0), - parent_client_id(0), - parent_context_id(0), - sync_point(0) { - parent_texture_id[0] = 0; - parent_texture_id[1] = 0; + parent_client_id(0) { } bool is_null() const { return handle == kNullPluginWindow && !transport; } PluginWindowHandle handle; bool transport; int parent_gpu_process_id; uint32 parent_client_id; - uint32 parent_context_id; - uint32 parent_texture_id[2]; - uint32 sync_point; }; // AcceleratedWidget provides a surface to compositors to paint pixels. |