diff options
17 files changed, 344 insertions, 60 deletions
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc index 636605d..d8f6d4b 100644 --- a/chrome/browser/chromeos/login/login_utils.cc +++ b/chrome/browser/chromeos/login/login_utils.cc @@ -724,6 +724,7 @@ std::string LoginUtilsImpl::GetOffTheRecordCommandLine( ::switches::kEnableGView, ::switches::kEnableLogging, ::switches::kEnablePartialSwap, + ::switches::kEnableUIReleaseFrontSurface, ::switches::kEnablePinch, ::switches::kEnableSmoothScrolling, ::switches::kEnableThreadedCompositing, diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index b81e494..ac48efc 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc @@ -756,6 +756,7 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) { switches::kTraceStartup, switches::kV, switches::kVModule, + switches::kEnableUIReleaseFrontSurface, #if defined(USE_AURA) switches::kUIPrioritizeInGpuProcess, #endif diff --git a/content/browser/gpu/gpu_process_host_ui_shim.cc b/content/browser/gpu/gpu_process_host_ui_shim.cc index e8cd609..edef780 100644 --- a/content/browser/gpu/gpu_process_host_ui_shim.cc +++ b/content/browser/gpu/gpu_process_host_ui_shim.cc @@ -309,7 +309,11 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceNew( TransportDIB::Handle shm_handle = TransportDIB::DefaultHandleValue(); view->AcceleratedSurfaceNew( - params.width, params.height, &surface_handle, &shm_handle); + params.width, + params.height, + &surface_handle, + &shm_handle, + params.route_id); delayed_send.Cancel(); Send(new AcceleratedSurfaceMsg_NewACK( params.route_id, surface_handle, shm_handle)); diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 5cc4cf5..41544a1 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -1836,6 +1836,21 @@ void RenderWidgetHostImpl::AcknowledgePostSubBuffer(int32 route_id, ui_shim->Send(new AcceleratedSurfaceMsg_PostSubBufferACK(route_id)); } +#if defined(USE_AURA) +// 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() { gfx::Size new_size = new_auto_size_; // Clear the new_auto_size_ since the empty value is used as a flag to diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 4be8960..e1202bf 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h @@ -153,6 +153,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost, // having been hidden. void WasHidden(); void WasRestored(); + bool IsHidden() const { return is_hidden_; } // Called to notify the RenderWidget that its associated native window got // focused. @@ -357,6 +358,16 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost, static void AcknowledgeSwapBuffers(int32 route_id, int gpu_host_id); static void AcknowledgePostSubBuffer(int32 route_id, int gpu_host_id); +#if defined(USE_AURA) + // Called by the view in response to visibility changes once the front surface + // is no longer in use by the ui (false), or when we expect to have a valid + // front surface for use by the ui (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 // event. void CompositingSurfaceUpdated(); 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 a2a3608..50389eb 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -9,7 +9,6 @@ #include "base/command_line.h" #include "base/debug/trace_event.h" #include "base/logging.h" -#include "base/memory/weak_ptr.h" #include "base/message_loop.h" #include "base/string_number_conversions.h" #include "content/browser/renderer_host/backing_store_aura.h" @@ -134,6 +133,13 @@ bool ShouldSendPinchGesture() { return pinch_allowed; } +bool ShouldReleaseFrontSurface() { + static bool release_front_surface_allowed = + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableUIReleaseFrontSurface); + return release_front_surface_allowed; +} + } // namespace // We have to implement the WindowObserver interface on a separate object @@ -215,6 +221,11 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host) can_compose_inline_(true), has_composition_text_(false), current_surface_(0), + current_surface_is_protected_(true), + current_surface_in_use_by_compositor_(true), + pending_thumbnail_tasks_(0), + protection_state_id_(0), + surface_route_id_(0), paint_canvas_(NULL), synthetic_move_sent_(false), needs_update_texture_(false) { @@ -271,15 +282,32 @@ RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const { } void RenderWidgetHostViewAura::DidBecomeSelected() { + if (!host_->IsHidden()) + return; + host_->WasRestored(); + if (!current_surface_ && host_->is_accelerated_compositing_active() && !released_front_lock_.get()) released_front_lock_ = window_->GetRootWindow()->GetCompositorLock(); + + AdjustSurfaceProtection(); } void RenderWidgetHostViewAura::WasHidden() { + if (host_->IsHidden()) + return; + host_->WasHidden(); + released_front_lock_ = NULL; + + if (ShouldReleaseFrontSurface()) { + current_surface_ = 0; + UpdateExternalTexture(); + } + + AdjustSurfaceProtection(); } void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) { @@ -473,11 +501,18 @@ void RenderWidgetHostViewAura::CopyFromCompositingSurface( unsigned char* addr = static_cast<unsigned char*>( output->getTopDevice()->accessBitmap(true).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). + base::Callback<void(bool)> wrapper_callback = base::Bind( + &RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinished, + AsWeakPtr(), + callback); + ++pending_thumbnail_tasks_; gl_helper->CopyTextureTo(container->texture_id(), container->size(), size_in_pixel, addr, - callback); + wrapper_callback); } void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() { @@ -494,14 +529,14 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() { needs_update_texture_ = false; if (current_surface_ != 0 && host_->is_accelerated_compositing_active()) { - + DCHECK(image_transport_clients_.find(current_surface_) != + image_transport_clients_.end()); ImageTransportClient* container = image_transport_clients_[current_surface_]; if (container) container->Update(); window_->SetExternalTexture(container); - - released_front_lock_ = NULL; + current_surface_in_use_by_compositor_ = true; if (!container) { resize_locks_.clear(); @@ -538,6 +573,18 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() { } } else { window_->SetExternalTexture(NULL); + ui::Compositor* compositor = GetCompositor(); + if (!compositor->DrawPending()) { + current_surface_in_use_by_compositor_ = false; + AdjustSurfaceProtection(); + } else { + on_compositing_ended_callbacks_.push_back( + base::Bind(&RenderWidgetHostViewAura:: + SetSurfaceNotInUseByCompositor, + AsWeakPtr())); + if (!compositor->HasObserver(this)) + compositor->AddObserver(this); + } resize_locks_.clear(); } } @@ -545,36 +592,63 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() { void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped( const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel, int gpu_host_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.require_ack) { + RenderWidgetHostImpl::AcknowledgeSwapBuffers( + params_in_pixel.route_id, gpu_host_id); + } + return; + } 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.require_ack) + released_front_lock_ = NULL; + + DCHECK(current_surface_); UpdateExternalTexture(); ui::Compositor* compositor = GetCompositor(); if (!compositor) { // We have no compositor, so we have no way to display the surface. // Must still send the ACK. - RenderWidgetHostImpl::AcknowledgeSwapBuffers(params_in_pixel.route_id, - gpu_host_id); + if (params_in_pixel.require_ack) { + RenderWidgetHostImpl::AcknowledgeSwapBuffers(params_in_pixel.route_id, + gpu_host_id); + } } 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 = content::ConvertSizeToDIP(this, surface_size_in_pixel); window_->SchedulePaintInRect(gfx::Rect(surface_size)); - if (!resize_locks_.empty() && !compositor->DrawPending()) { - // If we are waiting for the resize, fast-track the ACK. - // However only do so if we're not between the Draw() and the - // OnCompositingEnded(), because out-of-order execution in the GPU process - // might corrupt the "front buffer" for the currently issued frame. - RenderWidgetHostImpl::AcknowledgeSwapBuffers( - params_in_pixel.route_id, gpu_host_id); - } else { - // Add sending an ACK to the list of things to do OnCompositingEnded - on_compositing_ended_callbacks_.push_back( - base::Bind(&RenderWidgetHostImpl::AcknowledgeSwapBuffers, - params_in_pixel.route_id, gpu_host_id)); - if (!compositor->HasObserver(this)) - compositor->AddObserver(this); + if (params_in_pixel.require_ack) { + if (!resize_locks_.empty() && !compositor->DrawPending()) { + // If we are waiting for the resize, fast-track the ACK. + // However only do so if we're not between the Draw() and the + // OnCompositingEnded(), because out-of-order execution in the GPU + // process might corrupt the "front buffer" for the currently issued + // frame. + RenderWidgetHostImpl::AcknowledgeSwapBuffers( + params_in_pixel.route_id, gpu_host_id); + } else { + // Add sending an ACK to the list of things to do OnCompositingEnded + on_compositing_ended_callbacks_.push_back( + base::Bind(&RenderWidgetHostImpl::AcknowledgeSwapBuffers, + params_in_pixel.route_id, gpu_host_id)); + if (!compositor->HasObserver(this)) + compositor->AddObserver(this); + } } } } @@ -582,7 +656,18 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped( void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer( const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel, int gpu_host_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_); + RenderWidgetHostImpl::AcknowledgePostSubBuffer(params_in_pixel.route_id, + gpu_host_id); + return; + } current_surface_ = params_in_pixel.surface_handle; + released_front_lock_ = NULL; + DCHECK(current_surface_); UpdateExternalTexture(); ui::Compositor* compositor = GetCompositor(); @@ -592,6 +677,8 @@ void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer( RenderWidgetHostImpl::AcknowledgePostSubBuffer( params_in_pixel.route_id, gpu_host_id); } 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(); @@ -638,7 +725,8 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceNew( int32 width_in_pixel, int32 height_in_pixel, uint64* surface_handle, - TransportDIB::Handle* shm_handle) { + TransportDIB::Handle* shm_handle, + int32 route_id) { ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); scoped_refptr<ImageTransportClient> surface(factory->CreateTransportClient( gfx::Size(width_in_pixel, height_in_pixel), surface_handle)); @@ -649,10 +737,14 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceNew( *shm_handle = surface->Handle(); image_transport_clients_[*surface_handle] = surface; + + surface_route_id_ = route_id; } void RenderWidgetHostViewAura::AcceleratedSurfaceRelease( uint64 surface_handle) { + DCHECK(image_transport_clients_.find(surface_handle) != + image_transport_clients_.end()); if (current_surface_ == surface_handle) { current_surface_ = 0; UpdateExternalTexture(); @@ -660,6 +752,45 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceRelease( image_transport_clients_.erase(surface_handle); } +void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor() { + if (current_surface_ || !host_->IsHidden()) + 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. + // If we are not visible and current surface is null, still stay protected + // until we finish thumbnailing and compositing. + bool surface_is_protected = + current_surface_ || + !host_->IsHidden() || + (current_surface_is_protected_ && + (pending_thumbnail_tasks_ || 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::CopyFromCompositingSurfaceFinished( + base::Callback<void(bool)> callback, bool result) { + --pending_thumbnail_tasks_; + AdjustSurfaceProtection(); + callback.Run(result); +} + void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) { content::RenderWidgetHostViewBase::SetBackground(background); host_->SetBackground(background); @@ -1206,6 +1337,10 @@ void RenderWidgetHostViewAura::OnCompositingAborted( void RenderWidgetHostViewAura::OnLostResources(ui::Compositor* compositor) { 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_draw_.clear(); 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 53268d3..2157b6e 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h @@ -12,6 +12,7 @@ #include "base/callback.h" #include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.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" @@ -52,7 +53,8 @@ class RenderWidgetHostViewAura public ui::TextInputClient, public aura::WindowDelegate, public aura::client::ActivationDelegate, - public ImageTransportFactoryObserver { + public ImageTransportFactoryObserver, + public base::SupportsWeakPtr<RenderWidgetHostViewAura> { public: // RenderWidgetHostView implementation. virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE; @@ -116,7 +118,8 @@ class RenderWidgetHostViewAura int32 width_in_pixel, int32 height_in_pixel, uint64* surface_id, - TransportDIB::Handle* surface_handle) OVERRIDE; + TransportDIB::Handle* surface_handle, + int32 route_id) OVERRIDE; virtual void AcceleratedSurfaceRelease(uint64 surface_id) OVERRIDE; virtual void GetScreenInfo(WebKit::WebScreenInfo* results) OVERRIDE; virtual gfx::Rect GetRootWindowBounds() OVERRIDE; @@ -228,6 +231,22 @@ class RenderWidgetHostViewAura // Called when window_ is removed from the window tree. void RemovingFromRootWindow(); + // After resetting |current_surface_|, we must wait for any compositor pending + // draws finish to be sure the old surface is not in use. This is the callback + // that waits for OnCompositingEnded in such a case. + void SetSurfaceNotInUseByCompositor(); + + // 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 async thumbnailer task completes. Used to call + // AdjustSurfaceProtection. + void CopyFromCompositingSurfaceFinished(base::Callback<void(bool)> callback, + bool result); + ui::Compositor* GetCompositor(); // Detaches |this| from the input method object. @@ -289,6 +308,20 @@ class RenderWidgetHostViewAura 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 + // pending, and tab visibility. + bool current_surface_is_protected_; + bool current_surface_in_use_by_compositor_; + + int pending_thumbnail_tasks_; + + // This id increments every time surface_is_protected changes. + // Keeps gpu/browser IPC messages relying on protection state in sync. + uint32 protection_state_id_; + + int32 surface_route_id_; + gfx::GLSurfaceHandle shared_surface_handle_; // If non-NULL we're in OnPaint() and this is the supplied canvas. diff --git a/content/browser/renderer_host/test_render_view_host.h b/content/browser/renderer_host/test_render_view_host.h index 56f474f..c0a9e03 100644 --- a/content/browser/renderer_host/test_render_view_host.h +++ b/content/browser/renderer_host/test_render_view_host.h @@ -148,7 +148,7 @@ class TestRenderWidgetHostView : public RenderWidgetHostViewBase { #if defined(USE_AURA) virtual void AcceleratedSurfaceNew( int32 width, int32 height, uint64* surface_id, - TransportDIB::Handle* surface_handle) OVERRIDE { } + TransportDIB::Handle* surface_handle, int32 route_id) OVERRIDE { } virtual void AcceleratedSurfaceRelease(uint64 surface_id) OVERRIDE { } #endif diff --git a/content/common/gpu/gpu_memory_manager_unittest.cc b/content/common/gpu/gpu_memory_manager_unittest.cc index 0e861aa..8a9a4fd 100644 --- a/content/common/gpu/gpu_memory_manager_unittest.cc +++ b/content/common/gpu/gpu_memory_manager_unittest.cc @@ -41,8 +41,6 @@ class FakeCommandBufferStub : public GpuCommandBufferStubBase { const GpuCommandBufferStubBase& stub) const { return false; } - virtual void SendMemoryAllocationToProxy(const GpuMemoryAllocation& alloc) { - } virtual void SetMemoryAllocation(const GpuMemoryAllocation& alloc) { allocation_ = alloc; } @@ -77,8 +75,6 @@ class FakeCommandBufferStubWithoutSurface : public GpuCommandBufferStubBase { share_group_.end(), &stub) != share_group_.end(); } - virtual void SendMemoryAllocationToProxy(const GpuMemoryAllocation& alloc) { - } virtual void SetMemoryAllocation(const GpuMemoryAllocation& alloc) { allocation_ = alloc; } diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index 3d61a72..cab9be7 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h @@ -58,6 +58,8 @@ IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params) #elif defined(OS_MACOSX) IPC_STRUCT_MEMBER(gfx::PluginWindowHandle, window) #endif + IPC_STRUCT_MEMBER(uint32, protection_state_id) + IPC_STRUCT_MEMBER(bool, require_ack) IPC_STRUCT_END() #undef IPC_MESSAGE_EXPORT #define IPC_MESSAGE_EXPORT @@ -73,6 +75,7 @@ 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) @@ -201,6 +204,11 @@ IPC_MESSAGE_ROUTED2(AcceleratedSurfaceMsg_NewACK, uint64 /* surface_handle */, TransportDIB::Handle /* shared memory buffer */) +// 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 handled the swap // buffers request. IPC_MESSAGE_ROUTED0(AcceleratedSurfaceMsg_BuffersSwappedACK) diff --git a/content/common/gpu/image_transport_surface.cc b/content/common/gpu/image_transport_surface.cc index 7e49b9f..4ab12d4 100644 --- a/content/common/gpu/image_transport_surface.cc +++ b/content/common/gpu/image_transport_surface.cc @@ -21,6 +21,10 @@ 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, @@ -96,6 +100,8 @@ bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) { OnPostSubBufferACK) IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_NewACK, OnNewSurfaceACK) + IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_SetFrontSurfaceIsProtected, + OnSetFrontSurfaceIsProtected) IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_ResizeViewACK, OnResizeViewACK); IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -201,6 +207,11 @@ void ImageTransportHelper::OnNewSurfaceACK( surface_->OnNewSurfaceACK(surface_handle, shm_handle); } +void ImageTransportHelper::OnSetFrontSurfaceIsProtected( + bool is_protected, uint32 protection_state_id) { + surface_->OnSetFrontSurfaceIsProtected(is_protected, protection_state_id); +} + void ImageTransportHelper::OnBuffersSwappedACK() { surface_->OnBuffersSwappedACK(); } diff --git a/content/common/gpu/image_transport_surface.h b/content/common/gpu/image_transport_surface.h index 019aa50..936f40d 100644 --- a/content/common/gpu/image_transport_surface.h +++ b/content/common/gpu/image_transport_surface.h @@ -67,6 +67,8 @@ class ImageTransportSurface { virtual void OnPostSubBufferACK() = 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> @@ -138,6 +140,8 @@ class ImageTransportHelper : public IPC::Channel::Listener { void OnBuffersSwappedACK(); void OnPostSubBufferACK(); void OnResizeViewACK(); + void OnSetFrontSurfaceIsProtected(bool is_protected, + uint32 protection_state_id); // Backbuffer resize callback. void Resize(gfx::Size size); diff --git a/content/common/gpu/texture_image_transport_surface.cc b/content/common/gpu/texture_image_transport_surface.cc index ec81bbc..ef053e1 100644 --- a/content/common/gpu/texture_image_transport_surface.cc +++ b/content/common/gpu/texture_image_transport_surface.cc @@ -69,6 +69,8 @@ TextureImageTransportSurface::TextureImageTransportSurface( stub_destroyed_(false), backbuffer_suggested_allocation_(true), frontbuffer_suggested_allocation_(true), + frontbuffer_is_protected_(true), + protection_state_id_(0), handle_(handle), parent_stub_(NULL) { helper_.reset(new ImageTransportHelper(this, @@ -182,16 +184,36 @@ void TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) { if (!helper_->MakeCurrent()) return; - if (backbuffer_suggested_allocation_) + if (backbuffer_suggested_allocation_) { + DCHECK(!textures_[back()].info->service_id() || + !textures_[back()].sent_to_client); CreateBackTexture(textures_[back()].size); - else - ReleaseBackTexture(); + } else { + ReleaseTexture(back()); + } } 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; + } + } } void* TextureImageTransportSurface::GetShareHandle() { @@ -232,7 +254,7 @@ void TextureImageTransportSurface::OnWillDestroyStub( bool TextureImageTransportSurface::SwapBuffers() { DCHECK(backbuffer_suggested_allocation_); - if (!frontbuffer_suggested_allocation_) + if (!frontbuffer_suggested_allocation_ || !frontbuffer_is_protected_) return true; if (!parent_stub_) { LOG(ERROR) << "SwapBuffers failed because no parent stub."; @@ -241,12 +263,14 @@ bool TextureImageTransportSurface::SwapBuffers() { glFlush(); front_ = back(); - previous_damage_rect_ = gfx::Rect(textures_[front_].size); + previous_damage_rect_ = gfx::Rect(textures_[front()].size); - DCHECK(textures_[front_].client_id != 0); + DCHECK(textures_[front()].client_id != 0); GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; - params.surface_handle = textures_[front_].client_id; + params.surface_handle = textures_[front()].client_id; + params.protection_state_id = protection_state_id_; + params.require_ack = true; helper_->SendAcceleratedSurfaceBuffersSwapped(params); helper_->SetScheduled(false); return true; @@ -255,32 +279,30 @@ bool TextureImageTransportSurface::SwapBuffers() { bool TextureImageTransportSurface::PostSubBuffer( int x, int y, int width, int height) { DCHECK(backbuffer_suggested_allocation_); - if (!frontbuffer_suggested_allocation_) + DCHECK(textures_[back()].info->service_id()); + if (!frontbuffer_suggested_allocation_ || !frontbuffer_is_protected_) 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() || + 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; } - DCHECK(textures_[back()].info); - int back_texture_service_id = textures_[back()].info->service_id(); - - DCHECK(textures_[front_].info); - 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; - const gfx::Rect new_damage_rect(x, y, width, height); // 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); @@ -307,17 +329,19 @@ bool TextureImageTransportSurface::PostSubBuffer( glFlush(); front_ = back(); + previous_damage_rect_ = new_damage_rect; + + DCHECK(textures_[front()].client_id); GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; - params.surface_handle = textures_[front_].client_id; + params.surface_handle = textures_[front()].client_id; params.x = x; params.y = y; params.width = width; params.height = height; + params.protection_state_id = protection_state_id_; helper_->SendAcceleratedSurfacePostSubBuffer(params); helper_->SetScheduled(false); - - previous_damage_rect_ = new_damage_rect; return true; } @@ -342,10 +366,35 @@ void TextureImageTransportSurface::OnNewSurfaceACK( uint64 surface_handle, TransportDIB::Handle /*shm_handle*/) { } +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.protection_state_id = protection_state_id_; + params.require_ack = false; + helper_->SendAcceleratedSurfaceBuffersSwapped(params); + } +} + void TextureImageTransportSurface::OnBuffersSwappedACK() { if (helper_->MakeCurrent()) { - if (textures_[front_].size != textures_[back()].size) { - CreateBackTexture(textures_[front_].size); + if (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 { AttachBackTextureToFBO(); } @@ -364,10 +413,11 @@ void TextureImageTransportSurface::OnResizeViewACK() { NOTREACHED(); } -void TextureImageTransportSurface::ReleaseBackTexture() { +void TextureImageTransportSurface::ReleaseTexture(int id) { if (!parent_stub_) return; - TextureInfo* info = textures_[back()].info; + Texture& texture = textures_[id]; + TextureInfo* info = texture.info; DCHECK(info); GLuint service_id = info->service_id(); @@ -392,7 +442,7 @@ void TextureImageTransportSurface::CreateBackTexture(const gfx::Size& size) { GLuint service_id = info->service_id(); - if (service_id && texture.size == size) + if (service_id && texture.size == size && texture.sent_to_client) return; if (!service_id) { @@ -443,13 +493,14 @@ void TextureImageTransportSurface::CreateBackTexture(const gfx::Size& size) { void TextureImageTransportSurface::AttachBackTextureToFBO() { if (!parent_stub_) return; - DCHECK(textures_[back()].info); + TextureInfo* info = textures_[back()].info; + DCHECK(info); ScopedFrameBufferBinder fbo_binder(fbo_id_); glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - textures_[back()].info->service_id(), + info->service_id(), 0); glFlush(); CHECK_GL_ERROR(); diff --git a/content/common/gpu/texture_image_transport_surface.h b/content/common/gpu/texture_image_transport_surface.h index 907bfa4..82869e7 100644 --- a/content/common/gpu/texture_image_transport_surface.h +++ b/content/common/gpu/texture_image_transport_surface.h @@ -48,6 +48,9 @@ class TextureImageTransportSurface : virtual void OnBuffersSwappedACK() OVERRIDE; virtual void OnPostSubBufferACK() 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. @@ -74,9 +77,11 @@ class TextureImageTransportSurface : virtual ~TextureImageTransportSurface(); void CreateBackTexture(const gfx::Size& size); - void ReleaseBackTexture(); void AttachBackTextureToFBO(); + void ReleaseTexture(int id); void ReleaseParentStub(); + void AdjustFrontBufferAllocation(); + int front() const { return front_; } int back() const { return 1 - front_; } // The framebuffer that represents this surface (service id). Allocated lazily @@ -97,6 +102,9 @@ 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_; diff --git a/content/port/browser/render_widget_host_view_port.h b/content/port/browser/render_widget_host_view_port.h index 3578a96..7cac201 100644 --- a/content/port/browser/render_widget_host_view_port.h +++ b/content/port/browser/render_widget_host_view_port.h @@ -220,7 +220,8 @@ class CONTENT_EXPORT RenderWidgetHostViewPort : public RenderWidgetHostView { int32 width_in_pixel, int32 height_in_pixel, uint64* surface_id, - TransportDIB::Handle* surface_handle) = 0; + TransportDIB::Handle* surface_handle, + int32 route_id) = 0; virtual void AcceleratedSurfaceRelease(uint64 surface_id) = 0; #endif diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 1ae248c..c279c76 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc @@ -303,6 +303,10 @@ const char kEnableOriginBoundCerts[] = "enable-origin-bound-certs"; // Enables partial swaps in the WK compositor on platforms that support it. const char kEnablePartialSwap[] = "enable-partial-swap"; +// Enables UI releasing handle to front surface for background tabs on platforms +// that support it. +const char kEnableUIReleaseFrontSurface[] = "enable-ui-release-front-surface"; + // Enables touch-screen pinch gestures. const char kEnablePinch[] = "enable-pinch"; diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index b9dfd35..ae7e1f3 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h @@ -103,6 +103,7 @@ extern const char kEnablePeerConnection[]; extern const char kEnableMonitorProfile[]; extern const char kEnableOriginBoundCerts[]; extern const char kEnablePartialSwap[]; +extern const char kEnableUIReleaseFrontSurface[]; extern const char kEnablePinch[]; extern const char kEnablePreparsedJsCaching[]; CONTENT_EXPORT extern const char kEnablePrivilegedWebGLExtensions[]; |