summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/login/login_utils.cc1
-rw-r--r--content/browser/gpu/gpu_process_host.cc1
-rw-r--r--content/browser/gpu/gpu_process_host_ui_shim.cc6
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.cc15
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.h11
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.cc179
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.h37
-rw-r--r--content/browser/renderer_host/test_render_view_host.h2
-rw-r--r--content/common/gpu/gpu_memory_manager_unittest.cc4
-rw-r--r--content/common/gpu/gpu_messages.h8
-rw-r--r--content/common/gpu/image_transport_surface.cc11
-rw-r--r--content/common/gpu/image_transport_surface.h4
-rw-r--r--content/common/gpu/texture_image_transport_surface.cc107
-rw-r--r--content/common/gpu/texture_image_transport_surface.h10
-rw-r--r--content/port/browser/render_widget_host_view_port.h3
-rw-r--r--content/public/common/content_switches.cc4
-rw-r--r--content/public/common/content_switches.h1
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, &regions_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[];