diff options
author | pdr@chromium.org <pdr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-06 08:11:02 +0000 |
---|---|---|
committer | pdr@chromium.org <pdr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-06 08:11:02 +0000 |
commit | 146e2db0cb9745cd26b0a965ff4abc44fbe637d2 (patch) | |
tree | 12560240fb0386dbbc3561575b5ae541a5dab098 | |
parent | 720d780cecbec1829239d3448b50f1542a7a3f7c (diff) | |
download | chromium_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
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)); |