| Index: content/browser/renderer_host/render_widget_host_view_aura.cc
|
| 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 f8565eee8930390b9190a23eae09d3e897e4b935..6987fcc95dab4f69a9d5887fe12e657529ad8d78 100644
|
| --- a/content/browser/renderer_host/render_widget_host_view_aura.cc
|
| +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
|
| @@ -198,11 +198,16 @@ class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
|
|
|
| class RenderWidgetHostViewAura::ResizeLock {
|
| public:
|
| - ResizeLock(aura::RootWindow* root_window, const gfx::Size new_size)
|
| + ResizeLock(aura::RootWindow* root_window,
|
| + const gfx::Size new_size,
|
| + bool defer_compositor_lock)
|
| : root_window_(root_window),
|
| new_size_(new_size),
|
| - compositor_lock_(root_window_->GetCompositorLock()),
|
| - weak_ptr_factory_(this) {
|
| + compositor_lock_(defer_compositor_lock ?
|
| + NULL :
|
| + root_window_->compositor()->GetCompositorLock()),
|
| + weak_ptr_factory_(this),
|
| + defer_compositor_lock_(defer_compositor_lock) {
|
| root_window_->HoldMouseMoves();
|
|
|
| BrowserThread::PostDelayedTask(
|
| @@ -217,6 +222,7 @@ class RenderWidgetHostViewAura::ResizeLock {
|
| }
|
|
|
| void UnlockCompositor() {
|
| + defer_compositor_lock_ = false;
|
| compositor_lock_ = NULL;
|
| }
|
|
|
| @@ -232,11 +238,21 @@ class RenderWidgetHostViewAura::ResizeLock {
|
| return new_size_;
|
| }
|
|
|
| + bool GrabDeferredLock() {
|
| + if (root_window_ && defer_compositor_lock_) {
|
| + compositor_lock_ = root_window_->compositor()->GetCompositorLock();
|
| + defer_compositor_lock_ = false;
|
| + return true;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| private:
|
| aura::RootWindow* root_window_;
|
| gfx::Size new_size_;
|
| - scoped_refptr<aura::CompositorLock> compositor_lock_;
|
| + scoped_refptr<ui::CompositorLock> compositor_lock_;
|
| base::WeakPtrFactory<ResizeLock> weak_ptr_factory_;
|
| + bool defer_compositor_lock_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ResizeLock);
|
| };
|
| @@ -263,7 +279,8 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
|
| surface_route_id_(0),
|
| paint_canvas_(NULL),
|
| synthetic_move_sent_(false),
|
| - accelerated_compositing_state_changed_(false) {
|
| + accelerated_compositing_state_changed_(false),
|
| + can_lock_compositor_(YES) {
|
| host_->SetView(this);
|
| window_observer_.reset(new WindowObserver(this));
|
| window_->AddObserver(window_observer_.get());
|
| @@ -343,7 +360,7 @@ void RenderWidgetHostViewAura::WasShown() {
|
|
|
| if (!current_surface_ && host_->is_accelerated_compositing_active() &&
|
| !released_front_lock_.get()) {
|
| - released_front_lock_ = window_->GetRootWindow()->GetCompositorLock();
|
| + released_front_lock_ = GetCompositor()->GetCompositorLock();
|
| }
|
|
|
| AdjustSurfaceProtection();
|
| @@ -388,9 +405,22 @@ void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
|
| if (window_->bounds().size() != rect.size() &&
|
| host_->is_accelerated_compositing_active()) {
|
| aura::RootWindow* root_window = window_->GetRootWindow();
|
| - if (root_window) {
|
| + ui::Compositor* compositor = root_window ?
|
| + root_window->compositor() : NULL;
|
| + if (root_window && compositor) {
|
| + // Listen to changes in the compositor lock state.
|
| + if (!compositor->HasObserver(this))
|
| + compositor->AddObserver(this);
|
| +
|
| + bool defer_compositor_lock =
|
| + can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
|
| + can_lock_compositor_ == NO_PENDING_COMMIT;
|
| +
|
| + if (can_lock_compositor_ == YES)
|
| + can_lock_compositor_ = YES_DID_LOCK;
|
| +
|
| resize_locks_.push_back(make_linked_ptr(
|
| - new ResizeLock(root_window, rect.size())));
|
| + new ResizeLock(root_window, rect.size(), defer_compositor_lock)));
|
| }
|
| }
|
| window_->SetBounds(rect);
|
| @@ -695,6 +725,28 @@ void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
|
| accelerated_compositing_state_changed_ = true;
|
| }
|
|
|
| +bool RenderWidgetHostViewAura::ShouldFastACK(uint64 surface_id) {
|
| + ui::Texture* container = image_transport_clients_[surface_id];
|
| + DCHECK(container);
|
| +
|
| + if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
|
| + can_lock_compositor_ == NO_PENDING_COMMIT ||
|
| + resize_locks_.empty())
|
| + return false;
|
| +
|
| + gfx::Size container_size = ConvertSizeToDIP(this, container->size());
|
| + ResizeLockList::iterator it = resize_locks_.begin();
|
| + while (it != resize_locks_.end()) {
|
| + if ((*it)->expected_size() == container_size)
|
| + break;
|
| + ++it;
|
| + }
|
| +
|
| + // We could be getting an unexpected frame due to an animation
|
| + // (i.e. we start resizing but we get an old size frame first).
|
| + return it == resize_locks_.end() || ++it != resize_locks_.end();
|
| +}
|
| +
|
| 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
|
| @@ -710,7 +762,6 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() {
|
| if (!container) {
|
| resize_locks_.clear();
|
| } else {
|
| - typedef std::vector<linked_ptr<ResizeLock> > ResizeLockList;
|
| ResizeLockList::iterator it = resize_locks_.begin();
|
| while (it != resize_locks_.end()) {
|
| gfx::Size container_size = ConvertSizeToDIP(this,
|
| @@ -726,8 +777,8 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() {
|
| // Delay the release of the lock until we've kicked a frame with the
|
| // new texture, to avoid resizing the UI before we have a chance to
|
| // draw a "good" frame.
|
| - locks_pending_draw_.insert(
|
| - locks_pending_draw_.begin(), resize_locks_.begin(), it);
|
| + locks_pending_commit_.insert(
|
| + locks_pending_commit_.begin(), resize_locks_.begin(), it);
|
| // However since we got the size we were looking for, unlock the
|
| // compositor.
|
| for (ResizeLockList::iterator it2 = resize_locks_.begin();
|
| @@ -744,12 +795,12 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() {
|
| window_->SetExternalTexture(NULL);
|
| if (ShouldReleaseFrontSurface() &&
|
| host_->is_accelerated_compositing_active()) {
|
| - // The current surface may have pipelined gl commands, so always wait for
|
| - // the next composite to start. If the current surface is still null,
|
| - // then we really know its no longer in use.
|
| + // We need to wait for a commit to clear to guarantee that all we
|
| + // will not issue any more GL referencing the previous surface.
|
| ui::Compositor* compositor = GetCompositor();
|
| if (compositor) {
|
| - on_compositing_will_start_callbacks_.push_back(
|
| + can_lock_compositor_ = NO_PENDING_COMMIT;
|
| + on_compositing_did_commit_callbacks_.push_back(
|
| base::Bind(&RenderWidgetHostViewAura::
|
| SetSurfaceNotInUseByCompositor,
|
| AsWeakPtr()));
|
| @@ -771,15 +822,22 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
|
| params_in_pixel.protection_state_id != protection_state_id_) {
|
| DCHECK(!current_surface_);
|
| if (!params_in_pixel.skip_ack)
|
| - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, NULL);
|
| + InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL);
|
| + return;
|
| + }
|
| +
|
| + if (ShouldFastACK(params_in_pixel.surface_handle)) {
|
| + if (!params_in_pixel.skip_ack)
|
| + InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL);
|
| return;
|
| }
|
| +
|
| 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.
|
| + // new frame, rather we are just resetting our handle to some old content
|
| + // that we still hadn't discarded. Although we could display immediately,
|
| + // by not resetting the compositor lock here, we give us some time to get
|
| + // a fresh frame which means fewer content flashes.
|
| if (!params_in_pixel.skip_ack)
|
| released_front_lock_ = NULL;
|
|
|
| @@ -787,46 +845,26 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
|
|
|
| ui::Compositor* compositor = GetCompositor();
|
| if (!compositor) {
|
| - // We have no compositor, so we have no way to display the surface.
|
| - // Must still send the ACK.
|
| if (!params_in_pixel.skip_ack)
|
| - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, NULL);
|
| + InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL);
|
| } else {
|
| DCHECK(image_transport_clients_.find(params_in_pixel.surface_handle) !=
|
| image_transport_clients_.end());
|
| gfx::Size surface_size_in_pixel =
|
| image_transport_clients_[params_in_pixel.surface_handle]->size();
|
| - gfx::Size surface_size = ConvertSizeToDIP(this,
|
| - surface_size_in_pixel);
|
| + gfx::Size surface_size = ConvertSizeToDIP(this, surface_size_in_pixel);
|
| window_->SchedulePaintInRect(gfx::Rect(surface_size));
|
|
|
| if (!params_in_pixel.skip_ack) {
|
| - if (!resize_locks_.empty()) {
|
| - // If we are waiting for the resize, fast-track the ACK.
|
| - if (compositor->IsThreaded()) {
|
| - // We need the compositor thread to pick up the active buffer before
|
| - // ACKing.
|
| - on_compositing_did_commit_callbacks_.push_back(
|
| - base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK,
|
| - params_in_pixel.route_id,
|
| - gpu_host_id));
|
| - if (!compositor->HasObserver(this))
|
| - compositor->AddObserver(this);
|
| - } else {
|
| - // The compositor will pickup the active buffer during a draw, so we
|
| - // can ACK immediately.
|
| - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id,
|
| - compositor);
|
| - }
|
| - } else {
|
| - // Add sending an ACK to the list of things to do OnCompositingWillStart
|
| - on_compositing_will_start_callbacks_.push_back(
|
| - base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK,
|
| - params_in_pixel.route_id,
|
| - gpu_host_id));
|
| - if (!compositor->HasObserver(this))
|
| - compositor->AddObserver(this);
|
| - }
|
| + // Add sending an ACK to the list of things to do OnCompositingDidCommit
|
| + can_lock_compositor_ = NO_PENDING_COMMIT;
|
| + on_compositing_did_commit_callbacks_.push_back(
|
| + base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK,
|
| + params_in_pixel.route_id,
|
| + gpu_host_id,
|
| + true));
|
| + if (!compositor->HasObserver(this))
|
| + compositor->AddObserver(this);
|
| }
|
| }
|
| }
|
| @@ -840,9 +878,15 @@ void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
|
| if (params_in_pixel.protection_state_id &&
|
| params_in_pixel.protection_state_id != protection_state_id_) {
|
| DCHECK(!current_surface_);
|
| - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, NULL);
|
| + InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL);
|
| + return;
|
| + }
|
| +
|
| + if (ShouldFastACK(params_in_pixel.surface_handle)) {
|
| + InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL);
|
| return;
|
| }
|
| +
|
| current_surface_ = params_in_pixel.surface_handle;
|
| released_front_lock_ = NULL;
|
| DCHECK(current_surface_);
|
| @@ -850,9 +894,7 @@ void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
|
|
|
| ui::Compositor* compositor = GetCompositor();
|
| if (!compositor) {
|
| - // We have no compositor, so we have no way to display the surface
|
| - // Must still send the ACK
|
| - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, NULL);
|
| + InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id, false, NULL);
|
| } else {
|
| DCHECK(image_transport_clients_.find(params_in_pixel.surface_handle) !=
|
| image_transport_clients_.end());
|
| @@ -875,32 +917,15 @@ void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
|
|
|
| window_->SchedulePaintInRect(rect_to_paint);
|
|
|
| - if (!resize_locks_.empty()) {
|
| - // If we are waiting for the resize, fast-track the ACK.
|
| - if (compositor->IsThreaded()) {
|
| - // We need the compositor thread to pick up the active buffer before
|
| - // ACKing.
|
| - on_compositing_did_commit_callbacks_.push_back(
|
| - base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK,
|
| - params_in_pixel.route_id,
|
| - gpu_host_id));
|
| - if (!compositor->HasObserver(this))
|
| - compositor->AddObserver(this);
|
| - } else {
|
| - // The compositor will pickup the active buffer during a draw, so we
|
| - // can ACK immediately.
|
| - InsertSyncPointAndACK(params_in_pixel.route_id, gpu_host_id,
|
| - compositor);
|
| - }
|
| - } else {
|
| - // Add sending an ACK to the list of things to do OnCompositingWillStart
|
| - on_compositing_will_start_callbacks_.push_back(
|
| - base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK,
|
| - params_in_pixel.route_id,
|
| - gpu_host_id));
|
| - if (!compositor->HasObserver(this))
|
| - compositor->AddObserver(this);
|
| - }
|
| + // Add sending an ACK to the list of things to do OnCompositingDidCommit
|
| + can_lock_compositor_ = NO_PENDING_COMMIT;
|
| + on_compositing_did_commit_callbacks_.push_back(
|
| + base::Bind(&RenderWidgetHostViewAura::InsertSyncPointAndACK,
|
| + params_in_pixel.route_id,
|
| + gpu_host_id,
|
| + true));
|
| + if (!compositor->HasObserver(this))
|
| + compositor->AddObserver(this);
|
| }
|
| }
|
|
|
| @@ -1653,17 +1678,19 @@ void RenderWidgetHostViewAura::OnLostActive() {
|
|
|
| void RenderWidgetHostViewAura::OnCompositingDidCommit(
|
| ui::Compositor* compositor) {
|
| + if (can_lock_compositor_ == NO_PENDING_COMMIT) {
|
| + can_lock_compositor_ = YES;
|
| + for (ResizeLockList::iterator it = resize_locks_.begin();
|
| + it != resize_locks_.end(); ++it)
|
| + if ((*it)->GrabDeferredLock())
|
| + can_lock_compositor_ = YES_DID_LOCK;
|
| + }
|
| RunCompositingDidCommitCallbacks(compositor);
|
| -}
|
| -
|
| -void RenderWidgetHostViewAura::OnCompositingWillStart(
|
| - ui::Compositor* compositor) {
|
| - RunCompositingWillStartCallbacks(compositor);
|
| + locks_pending_commit_.clear();
|
| }
|
|
|
| void RenderWidgetHostViewAura::OnCompositingStarted(
|
| ui::Compositor* compositor) {
|
| - locks_pending_draw_.clear();
|
| }
|
|
|
| void RenderWidgetHostViewAura::OnCompositingEnded(
|
| @@ -1674,6 +1701,15 @@ void RenderWidgetHostViewAura::OnCompositingAborted(
|
| ui::Compositor* compositor) {
|
| }
|
|
|
| +void RenderWidgetHostViewAura::OnCompositingLockStateChanged(
|
| + ui::Compositor* compositor) {
|
| + // A compositor lock that is part of a resize lock timed out. We
|
| + // should display a renderer frame.
|
| + if (!compositor->IsLocked() && can_lock_compositor_ == YES_DID_LOCK) {
|
| + can_lock_compositor_ = NO_PENDING_RENDERER_FRAME;
|
| + }
|
| +}
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // RenderWidgetHostViewAura, ImageTransportFactoryObserver implementation:
|
|
|
| @@ -1685,7 +1721,7 @@ void RenderWidgetHostViewAura::OnLostResources() {
|
| current_surface_in_use_by_compositor_ = true;
|
| surface_route_id_ = 0;
|
| UpdateExternalTexture();
|
| - locks_pending_draw_.clear();
|
| + locks_pending_commit_.clear();
|
|
|
| DCHECK(!shared_surface_handle_.is_null());
|
| ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
|
| @@ -1832,19 +1868,10 @@ void RenderWidgetHostViewAura::RunCompositingDidCommitCallbacks(
|
| on_compositing_did_commit_callbacks_.clear();
|
| }
|
|
|
| -void RenderWidgetHostViewAura::RunCompositingWillStartCallbacks(
|
| - ui::Compositor* compositor) {
|
| - for (std::vector< base::Callback<void(ui::Compositor*)> >::const_iterator
|
| - it = on_compositing_will_start_callbacks_.begin();
|
| - it != on_compositing_will_start_callbacks_.end(); ++it) {
|
| - it->Run(compositor);
|
| - }
|
| - on_compositing_will_start_callbacks_.clear();
|
| -}
|
| -
|
| // static
|
| void RenderWidgetHostViewAura::InsertSyncPointAndACK(
|
| - int32 route_id, int gpu_host_id, ui::Compositor* compositor) {
|
| + int32 route_id, int gpu_host_id, bool presented,
|
| + ui::Compositor* compositor) {
|
| uint32 sync_point = 0;
|
| // If we have no compositor, so we must still send the ACK. A zero
|
| // sync point will not be waited for in the GPU process.
|
| @@ -1854,7 +1881,7 @@ void RenderWidgetHostViewAura::InsertSyncPointAndACK(
|
| }
|
|
|
| RenderWidgetHostImpl::AcknowledgeBufferPresent(
|
| - route_id, gpu_host_id, sync_point);
|
| + route_id, gpu_host_id, presented, sync_point);
|
| }
|
|
|
| void RenderWidgetHostViewAura::RemovingFromRootWindow() {
|
| @@ -1866,8 +1893,7 @@ void RenderWidgetHostViewAura::RemovingFromRootWindow() {
|
| // composited data.
|
| ui::Compositor* compositor = GetCompositor();
|
| RunCompositingDidCommitCallbacks(compositor);
|
| - RunCompositingWillStartCallbacks(compositor);
|
| - locks_pending_draw_.clear();
|
| + locks_pending_commit_.clear();
|
| if (compositor && compositor->HasObserver(this))
|
| compositor->RemoveObserver(this);
|
| DetachFromInputMethod();
|
|
|