summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpdr@chromium.org <pdr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-06 08:11:02 +0000
committerpdr@chromium.org <pdr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-06 08:11:02 +0000
commit146e2db0cb9745cd26b0a965ff4abc44fbe637d2 (patch)
tree12560240fb0386dbbc3561575b5ae541a5dab098
parent720d780cecbec1829239d3448b50f1542a7a3f7c (diff)
downloadchromium_src-146e2db0cb9745cd26b0a965ff4abc44fbe637d2.zip
chromium_src-146e2db0cb9745cd26b0a965ff4abc44fbe637d2.tar.gz
chromium_src-146e2db0cb9745cd26b0a965ff4abc44fbe637d2.tar.bz2
Revert of aura: Remove old GL paths from RenderWidgetHostViewAura. (https://codereview.chromium.org/131443007/)
Reason for revert: This patch is causing hundreds of layouttest timouts in Blink (see: http://goo.gl/6tX16t). My investigation is at crbug.com/341344. I'm going to roll this out for now to try to green the Blink tree. BUG=341344 Original issue's description: > aura: Remove old GL paths from RenderWidgetHostViewAura. > > Frames from the renderer are either legacy software, > software compositing, or ubercomp. Remove the old GL composited > paths that are no longer in use. > > R=piman > BUG=332998 > > Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=249226 TBR=piman@chromium.org,fsamuel@chromium.org,phajdan.jr@chromium.org,danakj@chromium.org NOTREECHECKS=true NOTRY=true BUG=332998 Review URL: https://codereview.chromium.org/150153003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249298 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/about_flags.cc17
-rw-r--r--chrome/browser/apps/web_view_browsertest.cc6
-rw-r--r--content/browser/browser_plugin/browser_plugin_host_browsertest.cc5
-rw-r--r--content/browser/renderer_host/input/touch_input_browsertest.cc3
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.cc379
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.h51
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura_unittest.cc71
7 files changed, 469 insertions, 63 deletions
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index be9f301..6a7af22 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -215,7 +215,6 @@ const Experiment::Choice kLCDTextChoices[] = {
{ IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED, cc::switches::kDisableLCDText, ""}
};
-#ifndef USE_AURA
const Experiment::Choice kDelegatedRendererChoices[] = {
{ IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
{ IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED,
@@ -223,7 +222,6 @@ const Experiment::Choice kDelegatedRendererChoices[] = {
{ IDS_GENERIC_EXPERIMENT_CHOICE_DISABLED,
switches::kDisableDelegatedRenderer, ""}
};
-#endif
const Experiment::Choice kMaxTilesForInterestAreaChoices[] = {
{ IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" },
@@ -450,11 +448,7 @@ const Experiment kExperiments[] = {
"force-compositing-mode-2",
IDS_FLAGS_FORCE_COMPOSITING_MODE_NAME,
IDS_FLAGS_FORCE_COMPOSITING_MODE_DESCRIPTION,
-#if !defined(USE_AURA)
kOsLinux,
-#else
- 0,
-#endif
ENABLE_DISABLE_VALUE_TYPE(switches::kForceCompositingMode,
switches::kDisableForceCompositingMode)
},
@@ -462,11 +456,7 @@ const Experiment kExperiments[] = {
"threaded-compositing-mode",
IDS_FLAGS_THREADED_COMPOSITING_MODE_NAME,
IDS_FLAGS_THREADED_COMPOSITING_MODE_DESCRIPTION,
-#if !defined(USE_AURA)
kOsLinux,
-#else
- 0,
-#endif
ENABLE_DISABLE_VALUE_TYPE(switches::kEnableThreadedCompositing,
switches::kDisableThreadedCompositing)
},
@@ -1465,15 +1455,16 @@ const Experiment kExperiments[] = {
kOsDesktop,
MULTI_VALUE_TYPE(kLCDTextChoices)
},
-#ifndef USE_AURA
{
"delegated-renderer",
IDS_FLAGS_DELEGATED_RENDERER_NAME,
IDS_FLAGS_DELEGATED_RENDERER_DESCRIPTION,
- kOsAndroid,
+#ifdef USE_AURA
+ kOsWin | kOsLinux |
+#endif
+ kOsAndroid | kOsCrOS,
MULTI_VALUE_TYPE(kDelegatedRendererChoices)
},
-#endif
{
"enable-websocket-experimental-implementation",
IDS_FLAGS_ENABLE_EXPERIMENTAL_WEBSOCKET_NAME,
diff --git a/chrome/browser/apps/web_view_browsertest.cc b/chrome/browser/apps/web_view_browsertest.cc
index 22263f1..a5ed016 100644
--- a/chrome/browser/apps/web_view_browsertest.cc
+++ b/chrome/browser/apps/web_view_browsertest.cc
@@ -632,7 +632,8 @@ IN_PROC_BROWSER_TEST_F(WebViewTest, AutoSize) {
#if !defined(OS_CHROMEOS)
// This test ensures <webview> doesn't crash in SW rendering when autosize is
// turned on.
-#if defined(OS_MACOSX) || defined(USE_AURA)
+// Flaky on Windows http://crbug.com/299507
+#if defined(OS_WIN) || defined(OS_MACOSX)
#define MAYBE_AutoSizeSW DISABLED_AutoSizeSW
#else
#define MAYBE_AutoSizeSW AutoSizeSW
@@ -1859,12 +1860,9 @@ IN_PROC_BROWSER_TEST_P(WebViewCaptureTest,
TestHelper("testScreenshotCapture", "web_view/shim", NO_TEST_SERVER);
}
-// Threaded compositing is always enabled on Aura.
-#if !defined(USE_AURA)
INSTANTIATE_TEST_CASE_P(WithoutThreadedCompositor,
WebViewCaptureTest,
::testing::Values(std::string(switches::kDisableThreadedCompositing)));
-#endif
// http://crbug.com/171744
#if !defined(OS_MACOSX)
diff --git a/content/browser/browser_plugin/browser_plugin_host_browsertest.cc b/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
index af56f31..fd69553 100644
--- a/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
+++ b/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
@@ -895,9 +895,8 @@ static void CompareSkBitmapAndRun(const base::Closure& callback,
callback.Run();
}
-// Mac: http://crbug.com/171744
-// Under ubercomp, GetBackingStore is not possible in the guest renderer.
-#if defined(OS_MACOSX) || defined(USE_AURA)
+// http://crbug.com/171744
+#if defined(OS_MACOSX)
#define MAYBE_GetBackingStore DISABLED_GetBackingStore
#else
#define MAYBE_GetBackingStore GetBackingStore
diff --git a/content/browser/renderer_host/input/touch_input_browsertest.cc b/content/browser/renderer_host/input/touch_input_browsertest.cc
index c499607..4889b49 100644
--- a/content/browser/renderer_host/input/touch_input_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_input_browsertest.cc
@@ -283,11 +283,8 @@ IN_PROC_BROWSER_TEST_P(TouchInputBrowserTest, MAYBE_MultiPointTouchPress) {
EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state());
}
-// Threaded compositing is always enabled on Aura.
-#if !defined(USE_AURA)
INSTANTIATE_TEST_CASE_P(WithoutInputHandlerProxy, TouchInputBrowserTest,
::testing::Values(std::string(switches::kDisableThreadedCompositing)));
-#endif
#if !defined(OS_MACOSX)
INSTANTIATE_TEST_CASE_P(WithInputHandlerProxy, TouchInputBrowserTest,
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 c05f2b0..599f976 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -308,6 +308,61 @@ bool PointerEventActivates(const ui::Event& event) {
return false;
}
+// Swap ack for the renderer when kCompositeToMailbox is enabled.
+void SendCompositorFrameAck(
+ int32 route_id,
+ uint32 output_surface_id,
+ int renderer_host_id,
+ const gpu::Mailbox& received_mailbox,
+ const gfx::Size& received_size,
+ bool skip_frame,
+ const scoped_refptr<ui::Texture>& texture_to_produce) {
+ cc::CompositorFrameAck ack;
+ ack.gl_frame_data.reset(new cc::GLFrameData());
+ DCHECK(!texture_to_produce.get() || !skip_frame);
+ if (texture_to_produce.get()) {
+ GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
+ std::string mailbox_name = texture_to_produce->Produce();
+ std::copy(mailbox_name.data(),
+ mailbox_name.data() + mailbox_name.length(),
+ reinterpret_cast<char*>(ack.gl_frame_data->mailbox.name));
+ ack.gl_frame_data->size = texture_to_produce->size();
+ ack.gl_frame_data->sync_point =
+ gl_helper ? gl_helper->InsertSyncPoint() : 0;
+ } else if (skip_frame) {
+ // Skip the frame, i.e. tell the producer to reuse the same buffer that
+ // we just received.
+ ack.gl_frame_data->size = received_size;
+ ack.gl_frame_data->mailbox = received_mailbox;
+ }
+
+ RenderWidgetHostImpl::SendSwapCompositorFrameAck(
+ route_id, output_surface_id, renderer_host_id, ack);
+}
+
+void AcknowledgeBufferForGpu(
+ int32 route_id,
+ int gpu_host_id,
+ const std::string& received_mailbox,
+ bool skip_frame,
+ const scoped_refptr<ui::Texture>& texture_to_produce) {
+ AcceleratedSurfaceMsg_BufferPresented_Params ack;
+ uint32 sync_point = 0;
+ DCHECK(!texture_to_produce.get() || !skip_frame);
+ if (texture_to_produce.get()) {
+ GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
+ ack.mailbox_name = texture_to_produce->Produce();
+ sync_point = gl_helper ? gl_helper->InsertSyncPoint() : 0;
+ } else if (skip_frame) {
+ ack.mailbox_name = received_mailbox;
+ ack.sync_point = 0;
+ }
+
+ ack.sync_point = sync_point;
+ RenderWidgetHostImpl::AcknowledgeBufferPresent(
+ route_id, gpu_host_id, ack);
+}
+
} // namespace
// We need to watch for mouse events outside a Web Popup or its parent
@@ -413,9 +468,10 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
last_output_surface_id_(0),
pending_delegated_ack_count_(0),
skipped_frames_(false),
- last_swapped_software_frame_scale_factor_(1.f),
+ last_swapped_surface_scale_factor_(1.f),
paint_canvas_(NULL),
synthetic_move_sent_(false),
+ accelerated_compositing_state_changed_(false),
can_lock_compositor_(YES),
cursor_visibility_state_in_renderer_(UNKNOWN),
touch_editing_client_(NULL),
@@ -554,7 +610,7 @@ void RenderWidgetHostViewAura::WasShown() {
NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
}
- if (host_->is_accelerated_compositing_active() &&
+ if (!current_surface_.get() && host_->is_accelerated_compositing_active() &&
!released_front_lock_.get()) {
ui::Compositor* compositor = GetCompositor();
if (compositor)
@@ -663,7 +719,7 @@ bool RenderWidgetHostViewAura::ShouldCreateResizeLock() {
return false;
gfx::Size desired_size = window_->bounds().size();
- if (desired_size == current_frame_size_in_dip_)
+ if (desired_size == current_frame_size_)
return false;
aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher();
@@ -894,6 +950,9 @@ void RenderWidgetHostViewAura::DidUpdateBackingStore(
const gfx::Vector2d& scroll_delta,
const std::vector<gfx::Rect>& copy_rects,
const std::vector<ui::LatencyInfo>& latency_info) {
+ if (accelerated_compositing_state_changed_)
+ UpdateExternalTexture();
+
for (size_t i = 0; i < latency_info.size(); i++)
software_latency_info_.push_back(latency_info[i]);
@@ -901,6 +960,8 @@ void RenderWidgetHostViewAura::DidUpdateBackingStore(
// differ. In particular if the window is hidden but the renderer isn't and we
// ignore the update and the window is made visible again the layer isn't
// marked as dirty and we show the wrong thing.
+ // We do this after UpdateExternalTexture() so that when we become visible
+ // we're not drawing a stale texture.
if (host_->is_hidden())
return;
@@ -1113,6 +1174,15 @@ void RenderWidgetHostViewAura::EndFrameSubscription() {
}
void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
+ // Delay processing the state change until we either get a software frame if
+ // switching to software mode or receive a buffers swapped notification
+ // if switching to accelerated mode.
+ // Sometimes (e.g. on a page load) the renderer will spuriously disable then
+ // re-enable accelerated compositing, causing us to flash.
+ // TODO(piman): factor the enable/disable accelerated compositing message into
+ // the UpdateRect/AcceleratedSurfaceBuffersSwapped messages so that we have
+ // fewer inconsistent temporary states.
+ accelerated_compositing_state_changed_ = true;
}
void RenderWidgetHostViewAura::AcceleratedSurfaceInitialized(int host_id,
@@ -1168,8 +1238,7 @@ void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
}
void RenderWidgetHostViewAura::CheckResizeLock() {
- if (!resize_lock_ ||
- resize_lock_->expected_size() != current_frame_size_in_dip_)
+ if (!resize_lock_ || resize_lock_->expected_size() != current_frame_size_)
return;
// Since we got the size we were looking for, unlock the compositor. But delay
@@ -1183,6 +1252,92 @@ void RenderWidgetHostViewAura::CheckResizeLock() {
}
}
+void RenderWidgetHostViewAura::UpdateExternalTexture() {
+ // Delay processing accelerated compositing state change till here where we
+ // act upon the state change. (Clear the external texture if switching to
+ // software mode or set the external texture if going to accelerated mode).
+ if (accelerated_compositing_state_changed_)
+ accelerated_compositing_state_changed_ = false;
+
+ bool is_compositing_active = host_->is_accelerated_compositing_active();
+ if (is_compositing_active && current_surface_.get()) {
+ window_->layer()->SetExternalTexture(current_surface_.get());
+ current_frame_size_ = ConvertSizeToDIP(
+ current_surface_->device_scale_factor(), current_surface_->size());
+ CheckResizeLock();
+ software_frame_manager_->DiscardCurrentFrame();
+ } else if (is_compositing_active &&
+ software_frame_manager_->HasCurrentFrame()) {
+ cc::TextureMailbox mailbox;
+ scoped_ptr<cc::SingleReleaseCallback> callback;
+ software_frame_manager_->GetCurrentFrameMailbox(&mailbox, &callback);
+ window_->layer()->SetTextureMailbox(mailbox,
+ callback.Pass(),
+ last_swapped_surface_scale_factor_);
+ current_frame_size_ = ConvertSizeToDIP(last_swapped_surface_scale_factor_,
+ mailbox.shared_memory_size());
+ CheckResizeLock();
+ } else {
+ window_->layer()->SetShowPaintedContent();
+ resize_lock_.reset();
+ host_->WasResized();
+ software_frame_manager_->DiscardCurrentFrame();
+ }
+}
+
+bool RenderWidgetHostViewAura::SwapBuffersPrepare(
+ const gfx::Rect& surface_rect,
+ float surface_scale_factor,
+ const gfx::Rect& damage_rect,
+ const std::string& mailbox_name,
+ const BufferPresentedCallback& ack_callback) {
+ 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();
+ last_swapped_surface_scale_factor_ = surface_scale_factor;
+ }
+
+ if (ShouldSkipFrame(ConvertSizeToDIP(surface_scale_factor,
+ surface_rect.size())) ||
+ mailbox_name.empty()) {
+ skipped_damage_.op(RectToSkIRect(damage_rect), SkRegion::kUnion_Op);
+ ack_callback.Run(true, scoped_refptr<ui::Texture>());
+ return false;
+ }
+
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ current_surface_ =
+ factory->CreateTransportClient(surface_scale_factor);
+ if (!current_surface_.get()) {
+ LOG(ERROR) << "Failed to create ImageTransport texture";
+ ack_callback.Run(true, scoped_refptr<ui::Texture>());
+ return false;
+ }
+
+ current_surface_->Consume(mailbox_name, surface_rect.size());
+ released_front_lock_ = NULL;
+ UpdateExternalTexture();
+
+ return true;
+}
+
+void RenderWidgetHostViewAura::SwapBuffersCompleted(
+ const BufferPresentedCallback& ack_callback,
+ const scoped_refptr<ui::Texture>& texture_to_return) {
+ ui::Compositor* compositor = GetCompositor();
+ if (!compositor) {
+ ack_callback.Run(false, texture_to_return);
+ } else {
+ AddOnCommitCallbackAndDisableLocks(
+ base::Bind(ack_callback, false, texture_to_return));
+ }
+
+ DidReceiveFrameFromRenderer();
+}
+
void RenderWidgetHostViewAura::DidReceiveFrameFromRenderer() {
if (frame_subscriber() && CanCopyToVideoFrame()) {
const base::TimeTicks present_time = base::TimeTicks::Now();
@@ -1191,7 +1346,7 @@ void RenderWidgetHostViewAura::DidReceiveFrameFromRenderer() {
if (frame_subscriber()->ShouldCaptureFrame(present_time,
&frame, &callback)) {
CopyFromCompositingSurfaceToVideoFrame(
- gfx::Rect(current_frame_size_in_dip_),
+ gfx::Rect(current_frame_size_),
frame,
base::Bind(callback, present_time));
}
@@ -1224,7 +1379,17 @@ void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
int gpu_host_id) {
- // Oldschool composited mode is no longer supported.
+ BufferPresentedCallback ack_callback = base::Bind(
+ &AcknowledgeBufferForGpu,
+ params_in_pixel.route_id,
+ gpu_host_id,
+ params_in_pixel.mailbox_name);
+ BuffersSwapped(params_in_pixel.size,
+ gfx::Rect(params_in_pixel.size),
+ params_in_pixel.scale_factor,
+ params_in_pixel.mailbox_name,
+ params_in_pixel.latency_info,
+ ack_callback);
}
void RenderWidgetHostViewAura::SwapDelegatedFrame(
@@ -1304,7 +1469,7 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame(
// this by making a new |frame_provider_| also to ensure the scale change
// is presented in sync with the new frame content.
if (!frame_provider_.get() || frame_size != frame_provider_->frame_size() ||
- frame_size_in_dip != current_frame_size_in_dip_) {
+ frame_size_in_dip != current_frame_size_) {
frame_provider_ = new cc::DelegatedFrameProvider(
resource_collection_.get(), frame_data.Pass());
window_->layer()->SetShowDelegatedContent(frame_provider_.get(),
@@ -1314,7 +1479,7 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame(
}
}
released_front_lock_ = NULL;
- current_frame_size_in_dip_ = frame_size_in_dip;
+ current_frame_size_ = frame_size_in_dip;
CheckResizeLock();
window_->SchedulePaintInRect(damage_rect_in_dip);
@@ -1403,21 +1568,18 @@ void RenderWidgetHostViewAura::SwapSoftwareFrame(
return;
}
- frame_provider_ = NULL;
- delegated_frame_evictor_->DiscardedFrame();
-
- if (last_swapped_software_frame_size_ != frame_size) {
+ if (last_swapped_surface_size_ != frame_size) {
DLOG_IF(ERROR, damage_rect != gfx::Rect(frame_size))
<< "Expected full damage rect";
}
- last_swapped_software_frame_size_ = frame_size;
- last_swapped_software_frame_scale_factor_ = frame_device_scale_factor;
+ last_swapped_surface_size_ = frame_size;
+ last_swapped_surface_scale_factor_ = frame_device_scale_factor;
cc::TextureMailbox mailbox;
scoped_ptr<cc::SingleReleaseCallback> callback;
software_frame_manager_->GetCurrentFrameMailbox(&mailbox, &callback);
DCHECK(mailbox.IsSharedMemory());
- current_frame_size_in_dip_ = frame_size_in_dip;
+ current_frame_size_ = frame_size_in_dip;
released_front_lock_ = NULL;
CheckResizeLock();
@@ -1488,12 +1650,43 @@ void RenderWidgetHostViewAura::OnSwapCompositorFrame(
frame->delegated_frame_data.Pass(),
frame->metadata.device_scale_factor,
frame->metadata.latency_info);
- } else if (frame->software_frame_data) {
+ return;
+ }
+
+ if (frame->software_frame_data) {
SwapSoftwareFrame(output_surface_id,
frame->software_frame_data.Pass(),
frame->metadata.device_scale_factor,
frame->metadata.latency_info);
+ return;
}
+
+ if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero())
+ return;
+
+ BufferPresentedCallback ack_callback = base::Bind(
+ &SendCompositorFrameAck,
+ host_->GetRoutingID(), output_surface_id, host_->GetProcess()->GetID(),
+ frame->gl_frame_data->mailbox, frame->gl_frame_data->size);
+
+ if (!frame->gl_frame_data->sync_point) {
+ LOG(ERROR) << "CompositorFrame without sync point. Skipping frame...";
+ ack_callback.Run(true, scoped_refptr<ui::Texture>());
+ return;
+ }
+
+ GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
+ gl_helper->WaitSyncPoint(frame->gl_frame_data->sync_point);
+
+ std::string mailbox_name(
+ reinterpret_cast<const char*>(frame->gl_frame_data->mailbox.name),
+ sizeof(frame->gl_frame_data->mailbox.name));
+ BuffersSwapped(frame->gl_frame_data->size,
+ frame->gl_frame_data->sub_buffer_rect,
+ frame->metadata.device_scale_factor,
+ mailbox_name,
+ frame->metadata.latency_info,
+ ack_callback);
}
#if defined(OS_WIN)
@@ -1511,16 +1704,115 @@ gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
}
#endif
+void RenderWidgetHostViewAura::BuffersSwapped(
+ const gfx::Size& surface_size,
+ const gfx::Rect& damage_rect,
+ float surface_scale_factor,
+ const std::string& mailbox_name,
+ const std::vector<ui::LatencyInfo>& latency_info,
+ const BufferPresentedCallback& ack_callback) {
+ scoped_refptr<ui::Texture> previous_texture(current_surface_);
+ const gfx::Rect surface_rect = gfx::Rect(surface_size);
+ software_frame_manager_->DiscardCurrentFrame();
+
+ if (!SwapBuffersPrepare(surface_rect,
+ surface_scale_factor,
+ damage_rect,
+ mailbox_name,
+ ack_callback)) {
+ return;
+ }
+
+ SkRegion damage(RectToSkIRect(damage_rect));
+ if (!skipped_damage_.isEmpty()) {
+ damage.op(skipped_damage_, SkRegion::kUnion_Op);
+ skipped_damage_.setEmpty();
+ }
+
+ DCHECK(surface_rect.Contains(SkIRectToRect(damage.getBounds())));
+ ui::Texture* current_texture = current_surface_.get();
+
+ const gfx::Size surface_size_in_pixel = surface_size;
+ DLOG_IF(ERROR, previous_texture.get() &&
+ previous_texture->size() != current_texture->size() &&
+ SkIRectToRect(damage.getBounds()) != surface_rect) <<
+ "Expected full damage rect after size change";
+ if (previous_texture.get() && !previous_damage_.isEmpty() &&
+ previous_texture->size() == current_texture->size()) {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ GLHelper* gl_helper = factory->GetGLHelper();
+ gl_helper->CopySubBufferDamage(
+ current_texture->PrepareTexture(),
+ previous_texture->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(surface_scale_factor,
+ gfx::Rect(damage_rect.x(),
+ surface_size_in_pixel.height() -
+ damage_rect.y() - damage_rect.height(),
+ damage_rect.width(),
+ damage_rect.height()));
+
+ // Damage may not have been DIP aligned, so inflate damage to compensate
+ // for any round-off error.
+ rect_to_paint.Inset(-1, -1);
+ rect_to_paint.Intersect(window_->bounds());
+
+ window_->SchedulePaintInRect(rect_to_paint);
+ for (size_t i = 0; i < latency_info.size(); i++)
+ compositor->SetLatencyInfo(latency_info[i]);
+ }
+
+ SwapBuffersCompleted(ack_callback, previous_texture);
+}
+
void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel,
int gpu_host_id) {
- // Oldschool composited mode is no longer supported.
+ gfx::Rect damage_rect(params_in_pixel.x,
+ params_in_pixel.y,
+ params_in_pixel.width,
+ params_in_pixel.height);
+ BufferPresentedCallback ack_callback =
+ base::Bind(&AcknowledgeBufferForGpu,
+ params_in_pixel.route_id,
+ gpu_host_id,
+ params_in_pixel.mailbox_name);
+ BuffersSwapped(params_in_pixel.surface_size,
+ damage_rect,
+ params_in_pixel.surface_scale_factor,
+ params_in_pixel.mailbox_name,
+ params_in_pixel.latency_info,
+ ack_callback);
}
void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() {
}
void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() {
+ // This really tells us to release the frontbuffer.
+ if (current_surface_.get()) {
+ 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.
+ AddOnCommitCallbackAndDisableLocks(
+ base::Bind(&RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor,
+ AsWeakPtr(),
+ current_surface_)); // Hold a ref so the texture will not
+ // get deleted until after commit.
+ }
+ current_surface_ = NULL;
+ UpdateExternalTexture();
+ }
}
bool RenderWidgetHostViewAura::HasAcceleratedSurface(
@@ -2383,10 +2675,31 @@ void RenderWidgetHostViewAura::DidRecreateLayer(ui::Layer *old_layer,
float mailbox_scale_factor;
cc::TextureMailbox old_mailbox =
old_layer->GetTextureMailbox(&mailbox_scale_factor);
+ scoped_refptr<ui::Texture> old_texture = old_layer->external_texture();
// The new_layer is the one that will be used by our Window, so that's the one
// that should keep our texture. old_layer will be returned to the
// RecreateLayer caller, and should have a copy.
- if (old_mailbox.IsSharedMemory()) {
+ if (old_texture.get()) {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ GLHelper* gl_helper = factory->GetGLHelper();
+ scoped_refptr<ui::Texture> new_texture;
+ if (host_->is_accelerated_compositing_active() &&
+ gl_helper && current_surface_.get()) {
+ GLuint texture_id =
+ gl_helper->CopyTexture(current_surface_->PrepareTexture(),
+ current_surface_->size());
+ if (texture_id) {
+ new_texture = factory->CreateOwnedTexture(
+ current_surface_->size(),
+ current_surface_->device_scale_factor(), texture_id);
+ }
+ }
+ if (new_texture.get())
+ old_layer->SetExternalTexture(new_texture.get());
+ else
+ old_layer->SetShowPaintedContent();
+ new_layer->SetExternalTexture(old_texture.get());
+ } else if (old_mailbox.IsSharedMemory()) {
base::SharedMemory* old_buffer = old_mailbox.shared_memory();
const size_t size = old_mailbox.shared_memory_size_in_bytes();
@@ -2407,7 +2720,7 @@ void RenderWidgetHostViewAura::DidRecreateLayer(ui::Layer *old_layer,
}
} else if (frame_provider_.get()) {
new_layer->SetShowDelegatedContent(frame_provider_.get(),
- current_frame_size_in_dip_);
+ current_frame_size_);
}
}
@@ -2844,7 +3157,7 @@ void RenderWidgetHostViewAura::ReleaseReferencesToSoftwareFrame() {
AddOnCommitCallbackAndDisableLocks(base::Bind(
&RenderWidgetHostViewAura::SendReclaimSoftwareFrames, AsWeakPtr()));
}
- window_->layer()->SetShowPaintedContent();
+ UpdateExternalTexture();
}
////////////////////////////////////////////////////////////////////////////////
@@ -2858,8 +3171,7 @@ void RenderWidgetHostViewAura::OnCompositingDidCommit(
can_lock_compositor_ = YES_DID_LOCK;
}
RunOnCommitCallbacks();
- if (resize_lock_ &&
- resize_lock_->expected_size() == current_frame_size_in_dip_) {
+ if (resize_lock_ && resize_lock_->expected_size() == current_frame_size_) {
resize_lock_.reset();
host_->WasResized();
// We may have had a resize while we had the lock (e.g. if the lock expired,
@@ -2964,11 +3276,16 @@ void RenderWidgetHostViewAura::FatalAccessibilityTreeError() {
// RenderWidgetHostViewAura, ImageTransportFactoryObserver implementation:
void RenderWidgetHostViewAura::OnLostResources() {
- if (frame_provider_.get())
- EvictDelegatedFrame();
+ current_surface_ = NULL;
+ UpdateExternalTexture();
+
idle_frame_subscriber_textures_.clear();
yuv_readback_pipeline_.reset();
+ // Make sure all ImageTransportClients are deleted now that the context those
+ // are using is becoming invalid. This sends pending ACKs and needs to happen
+ // after calling UpdateExternalTexture() which syncs with the impl thread.
+ RunOnCommitCallbacks();
host_->ScheduleComposite();
}
@@ -3175,6 +3492,8 @@ void RenderWidgetHostViewAura::AddedToRootWindow() {
cursor_client->AddObserver(this);
NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
}
+ if (current_surface_.get())
+ UpdateExternalTexture();
if (HasFocus()) {
ui::InputMethod* input_method = GetInputMethod();
if (input_method)
@@ -3192,10 +3511,18 @@ void RenderWidgetHostViewAura::RemovingFromRootWindow() {
window_->GetDispatcher()->RemoveRootWindowObserver(this);
host_->ParentChanged(0);
+ ui::Compositor* compositor = GetCompositor();
+ if (current_surface_.get()) {
+ // We can't get notification for commits after this point, which would
+ // guarantee that the compositor isn't using an old texture any more, so
+ // instead we force the layer to stop using any external resources which
+ // synchronizes with the compositor thread, and makes it safe to run the
+ // callback.
+ window_->layer()->SetShowPaintedContent();
+ }
RunOnCommitCallbacks();
resize_lock_.reset();
host_->WasResized();
- ui::Compositor* compositor = GetCompositor();
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 e14ee6c..dbbdd44 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -356,9 +356,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Exposed for tests.
aura::Window* window() { return window_; }
- gfx::Size current_frame_size_in_dip() const {
- return current_frame_size_in_dip_;
- }
+ gfx::Size current_frame_size() const { return current_frame_size_; }
void LockResources();
void UnlockResources();
@@ -425,6 +423,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Checks if the resize lock can be released because we received an new frame.
void CheckResizeLock();
+ void UpdateExternalTexture();
ui::InputMethod* GetInputMethod() const;
// Returns whether the widget needs an input grab to work properly.
@@ -514,6 +513,28 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Converts |rect| from screen coordinate to window coordinate.
gfx::Rect ConvertRectFromScreen(const gfx::Rect& rect) const;
+ typedef base::Callback<void(bool, const scoped_refptr<ui::Texture>&)>
+ BufferPresentedCallback;
+
+ // The common entry point for buffer updates from renderer
+ // and GPU process.
+ void BuffersSwapped(const gfx::Size& surface_size,
+ const gfx::Rect& damage_rect,
+ float surface_scale_factor,
+ const std::string& mailbox_name,
+ const std::vector<ui::LatencyInfo>& latency_info,
+ const BufferPresentedCallback& ack_callback);
+
+ bool SwapBuffersPrepare(const gfx::Rect& surface_rect,
+ float surface_scale_factor,
+ const gfx::Rect& damage_rect,
+ const std::string& mailbox_name,
+ const BufferPresentedCallback& ack_callback);
+
+ void SwapBuffersCompleted(
+ const BufferPresentedCallback& ack_callback,
+ const scoped_refptr<ui::Texture>& texture_to_return);
+
void SwapDelegatedFrame(
uint32 output_surface_id,
scoped_ptr<cc::DelegatedFrameData> frame_data,
@@ -605,6 +626,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
std::vector<base::Closure> on_compositing_did_commit_callbacks_;
+ // The current frontbuffer texture.
+ scoped_refptr<ui::Texture> current_surface_;
+
// This holds the current software framebuffer, if any.
scoped_ptr<SoftwareFrameManager> software_frame_manager_;
@@ -617,6 +641,12 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// returns until the acks are sent.
int pending_delegated_ack_count_;
+ // The damage in the previously presented buffer.
+ SkRegion previous_damage_;
+
+ // Pending damage from previous frames that we skipped.
+ SkRegion skipped_damage_;
+
// True after a delegated frame has been skipped, until a frame is not
// skipped.
bool skipped_frames_;
@@ -629,9 +659,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Provides delegated frame updates to the cc::DelegatedRendererLayer.
scoped_refptr<cc::DelegatedFrameProvider> frame_provider_;
- // The size and scale of the last software compositing frame that was swapped.
- gfx::Size last_swapped_software_frame_size_;
- float last_swapped_software_frame_scale_factor_;
+ // 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_;
+ float last_swapped_surface_scale_factor_;
// If non-NULL we're in OnPaint() and this is the supplied canvas.
gfx::Canvas* paint_canvas_;
@@ -651,6 +683,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// events vs. normal mouse move events.
bool synthetic_move_sent_;
+ // Signals that the accelerated compositing has been turned on or off.
+ // This is used to signal to turn off the external texture as soon as the
+ // software backing store is updated.
+ bool accelerated_compositing_state_changed_;
+
// This lock is the one waiting for a frame of the right size to come back
// from the renderer/GPU process. It is set from the moment the aura window
// got resized, to the moment we committed the renderer frame of the same
@@ -660,7 +697,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
scoped_ptr<ResizeLock> resize_lock_;
// Keeps track of the current frame size.
- gfx::Size current_frame_size_in_dip_;
+ gfx::Size current_frame_size_;
// This lock is for waiting for a front surface to become available to draw.
scoped_refptr<ui::CompositorLock> released_front_lock_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index edeba63..6911f28 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -155,7 +155,7 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
virtual bool ShouldCreateResizeLock() OVERRIDE {
gfx::Size desired_size = window()->bounds().size();
- return desired_size != current_frame_size_in_dip();
+ return desired_size != current_frame_size();
}
virtual scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock)
@@ -834,6 +834,19 @@ TEST_F(RenderWidgetHostViewAuraTest, UpdateCursorIfOverSelf) {
EXPECT_EQ(0, cursor_client.calls_to_set_cursor());
}
+scoped_ptr<cc::CompositorFrame> MakeGLFrame(float scale_factor,
+ gfx::Size size,
+ gfx::Rect damage) {
+ scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
+ frame->metadata.device_scale_factor = scale_factor;
+ frame->gl_frame_data.reset(new cc::GLFrameData);
+ frame->gl_frame_data->sync_point = 1;
+ memset(frame->gl_frame_data->mailbox.name, '1', 64);
+ frame->gl_frame_data->size = size;
+ frame->gl_frame_data->sub_buffer_rect = damage;
+ return frame.Pass();
+}
+
scoped_ptr<cc::CompositorFrame> MakeSoftwareFrame(float scale_factor,
gfx::Size size,
gfx::Rect damage) {
@@ -889,9 +902,7 @@ TEST_F(RenderWidgetHostViewAuraTest, FullscreenResize) {
// Resizes are blocked until we swapped a frame of the correct size, and
// we've committed it.
view_->OnSwapCompositorFrame(
- 0,
- MakeDelegatedFrame(
- 1.f, params.a.new_size, gfx::Rect(params.a.new_size)));
+ 0, MakeGLFrame(1.f, params.a.new_size, gfx::Rect(params.a.new_size)));
ui::DrawWaiterForTest::WaitForCommit(
root_window->GetDispatcher()->host()->compositor());
}
@@ -912,9 +923,7 @@ TEST_F(RenderWidgetHostViewAuraTest, FullscreenResize) {
gfx::Rect(params.a.screen_info.availableRect).ToString());
EXPECT_EQ("1600x1200", params.a.new_size.ToString());
view_->OnSwapCompositorFrame(
- 0,
- MakeDelegatedFrame(
- 1.f, params.a.new_size, gfx::Rect(params.a.new_size)));
+ 0, MakeGLFrame(1.f, params.a.new_size, gfx::Rect(params.a.new_size)));
ui::DrawWaiterForTest::WaitForCommit(
root_window->GetDispatcher()->host()->compositor());
}
@@ -936,6 +945,54 @@ TEST_F(RenderWidgetHostViewAuraTest, SwapNotifiesWindow) {
MockWindowObserver observer;
view_->window_->AddObserver(&observer);
+ // Swap a frame through the GPU path.
+ GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
+ params.surface_id = widget_host_->surface_id();
+ params.route_id = widget_host_->GetRoutingID();
+ params.mailbox_name = std::string(64, '1');
+ params.size = view_size;
+ params.scale_factor = 1.f;
+
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->AcceleratedSurfaceBuffersSwapped(params, 0);
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // DSF = 2
+ params.size = gfx::Size(200, 200);
+ params.scale_factor = 2.f;
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->AcceleratedSurfaceBuffersSwapped(params, 0);
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // Partial frames though GPU path
+ GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params post_params;
+ post_params.surface_id = widget_host_->surface_id();
+ post_params.route_id = widget_host_->GetRoutingID();
+ post_params.mailbox_name = std::string(64, '1');
+ post_params.surface_size = gfx::Size(200, 200);
+ post_params.surface_scale_factor = 2.f;
+ post_params.x = 40;
+ post_params.y = 40;
+ post_params.width = 80;
+ post_params.height = 80;
+ // rect from params is upside down, and is inflated in RWHVA, just because.
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
+ gfx::Rect(19, 39, 42, 42)));
+ view_->AcceleratedSurfacePostSubBuffer(post_params, 0);
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // Composite-to-mailbox path
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ view_->OnSwapCompositorFrame(0, MakeGLFrame(1.f, view_size, view_rect));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
+ // rect from GL frame is upside down, and is inflated in RWHVA, just because.
+ EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
+ gfx::Rect(4, 89, 7, 7)));
+ view_->OnSwapCompositorFrame(
+ 0, MakeGLFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5)));
+ testing::Mock::VerifyAndClearExpectations(&observer);
+
// Software path
EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
view_->OnSwapCompositorFrame(0, MakeSoftwareFrame(1.f, view_size, view_rect));