Chromium Code Reviews| 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 c7d3affc07b5f2ead19d4796ddcb345425150f44..c08504775c88900a6b70eddd25a2e99aad1513f9 100644 |
| --- a/content/browser/renderer_host/render_widget_host_view_aura.cc |
| +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc |
| @@ -913,7 +913,7 @@ bool RenderWidgetHostViewAura::HasFocus() const { |
| } |
| bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const { |
| - return current_surface_ || !!host_->GetBackingStore(false); |
| + return current_surface_ || current_dib_ || !!host_->GetBackingStore(false); |
| } |
| void RenderWidgetHostViewAura::Show() { |
| @@ -1318,16 +1318,10 @@ void RenderWidgetHostViewAura::SwapBuffersCompleted( |
| const BufferPresentedCallback& ack_callback, |
| const scoped_refptr<ui::Texture>& texture_to_return) { |
| ui::Compositor* compositor = GetCompositor(); |
| - if (!compositor) { |
| + if (!compositor) |
| ack_callback.Run(false, texture_to_return); |
| - } else { |
| - // 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(ack_callback, false, texture_to_return)); |
| - if (!compositor->HasObserver(this)) |
| - compositor->AddObserver(this); |
| - } |
| + else |
| + AddOnCommitCallback(base::Bind(ack_callback, false, texture_to_return)); |
| } |
| #if defined(OS_WIN) |
| @@ -1395,12 +1389,9 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame( |
| if (!compositor) { |
| SendDelegatedFrameAck(); |
| } else { |
| - can_lock_compositor_ = NO_PENDING_COMMIT; |
| - on_compositing_did_commit_callbacks_.push_back( |
| + AddOnCommitCallback( |
| base::Bind(&RenderWidgetHostViewAura::SendDelegatedFrameAck, |
| - base::Unretained(this))); |
| - if (!compositor->HasObserver(this)) |
| - compositor->AddObserver(this); |
| + AsWeakPtr())); |
| } |
| } |
| @@ -1411,6 +1402,56 @@ void RenderWidgetHostViewAura::SendDelegatedFrameAck() { |
| host_->GetRoutingID(), host_->GetProcess()->GetID(), ack); |
| } |
| +void RenderWidgetHostViewAura::SwapSoftwareFrame( |
| + scoped_ptr<cc::SoftwareFrameData> frame_data, |
| + float frame_device_scale_factor) { |
| + const gfx::Size& frame_size = frame_data->size; |
| + const gfx::Rect& damage_rect = frame_data->damage_rect; |
| + TransportDIB::Handle handle = frame_data->content_dib; |
| + |
| +#if defined(OS_WIN) |
| + ::DuplicateHandle(host_->GetProcess()->GetHandle(), handle, |
|
slavi
2013/03/27 20:16:40
BUG: Save the original handle value so that we sen
|
| + ::GetCurrentProcess(), &handle, |
| + 0, FALSE, DUPLICATE_SAME_ACCESS); |
| +#endif |
| + |
| + current_dib_.reset(TransportDIB::Map(handle)); |
| + previous_damage_.op(RectToSkIRect(damage_rect), SkRegion::kUnion_Op); |
| + if (last_swapped_surface_size_ != frame_size) { |
| + DLOG_IF(ERROR, damage_rect != gfx::Rect(frame_size)) |
| + << "Expected full damage rect"; |
| + last_swapped_surface_size_ = frame_size; |
| + } |
| + |
| + gfx::Size frame_size_in_dip = gfx::ToFlooredSize( |
| + gfx::ScaleSize(frame_size, 1.0f / frame_device_scale_factor)); |
| + ui::Compositor* compositor = GetCompositor(); |
| + if (!compositor || !current_dib_ || ShouldSkipFrame(frame_size_in_dip)) { |
| + SendSoftwareFrameAck(handle); |
| + return; |
| + } |
| + |
| + window_->SetExternalTexture(NULL); |
| + released_front_lock_ = NULL; |
| + CheckResizeLocks(frame_size_in_dip); |
| + AddOnCommitCallback( |
| + base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck, |
| + AsWeakPtr(), handle)); |
| + |
| + if (paint_observer_) |
| + paint_observer_->OnUpdateCompositorContent(); |
| + window_->SchedulePaintInRect(ConvertRectToDIP(this, damage_rect)); |
| +} |
| + |
| +void RenderWidgetHostViewAura::SendSoftwareFrameAck( |
| + TransportDIB::Handle handle) { |
| + cc::CompositorFrameAck ack; |
| + ack.last_content_dib = handle; |
| + RenderWidgetHostImpl::SendSwapCompositorFrameAck( |
| + host_->GetRoutingID(), host_->GetProcess()->GetID(), ack); |
| +} |
| + |
| + |
| void RenderWidgetHostViewAura::OnSwapCompositorFrame( |
| scoped_ptr<cc::CompositorFrame> frame) { |
| if (frame->delegated_frame_data) { |
| @@ -1418,6 +1459,13 @@ void RenderWidgetHostViewAura::OnSwapCompositorFrame( |
| frame->metadata.device_scale_factor); |
| return; |
| } |
| + |
| + if (frame->software_frame_data) { |
| + SwapSoftwareFrame(frame->software_frame_data.Pass(), |
| + frame->metadata.device_scale_factor); |
| + return; |
| + } |
| + |
| if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero()) |
| return; |
| @@ -1447,7 +1495,7 @@ void RenderWidgetHostViewAura::BuffersSwapped( |
| const std::string& mailbox_name, |
| const BufferPresentedCallback& ack_callback) { |
| scoped_refptr<ui::Texture> texture_to_return(current_surface_); |
| - const gfx::Rect surface_rect = gfx::Rect(gfx::Point(), size); |
| + const gfx::Rect surface_rect = gfx::Rect(size); |
| if (!SwapBuffersPrepare( |
| surface_rect, surface_rect, mailbox_name, ack_callback)) { |
| return; |
| @@ -1473,7 +1521,7 @@ void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer( |
| int gpu_host_id) { |
| scoped_refptr<ui::Texture> previous_texture(current_surface_); |
| const gfx::Rect surface_rect = |
| - gfx::Rect(gfx::Point(), params_in_pixel.surface_size); |
| + gfx::Rect(params_in_pixel.surface_size); |
| gfx::Rect damage_rect(params_in_pixel.x, |
| params_in_pixel.y, |
| params_in_pixel.width, |
| @@ -1547,15 +1595,12 @@ void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() { |
| 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. |
| - can_lock_compositor_ = NO_PENDING_COMMIT; |
| - on_compositing_did_commit_callbacks_.push_back( |
| + AddOnCommitCallback( |
| base::Bind(&RenderWidgetHostViewAura:: |
| SetSurfaceNotInUseByCompositor, |
| AsWeakPtr(), |
| current_surface_)); // Hold a ref so the texture will not |
| // get deleted until after commit. |
| - if (!compositor->HasObserver(this)) |
| - compositor->AddObserver(this); |
| } |
| current_surface_ = NULL; |
| UpdateExternalTexture(); |
| @@ -1938,12 +1983,32 @@ void RenderWidgetHostViewAura::OnCaptureLost() { |
| } |
| void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) { |
| - paint_canvas_ = canvas; |
| - BackingStore* backing_store = host_->GetBackingStore(true); |
| - paint_canvas_ = NULL; |
| - if (backing_store) { |
| - static_cast<BackingStoreAura*>(backing_store)->SkiaShowRect(gfx::Point(), |
| - canvas); |
| + bool is_compositing_active = host_->is_accelerated_compositing_active(); |
| + bool has_backing_store = !!host_->GetBackingStore(false); |
| + if (is_compositing_active && current_dib_) { |
| + SkBitmap bitmap; |
| + bitmap.setConfig(SkBitmap::kARGB_8888_Config, |
| + last_swapped_surface_size_.width(), |
| + last_swapped_surface_size_.height()); |
| + bitmap.setPixels(current_dib_->memory()); |
| + |
| + SkCanvas* sk_canvas = canvas->sk_canvas(); |
| + for (SkRegion::Iterator it(previous_damage_); !it.done(); it.next()) { |
| + const SkIRect& src_rect = it.rect(); |
| + SkRect dst_rect = SkRect::Make(src_rect); |
| + sk_canvas->drawBitmapRect(bitmap, &src_rect, dst_rect, NULL); |
| + } |
| + previous_damage_.setEmpty(); |
| + |
| + if (paint_observer_) |
| + paint_observer_->OnPaintComplete(); |
| + } else if (!is_compositing_active && has_backing_store) { |
| + paint_canvas_ = canvas; |
| + BackingStoreAura* backing_store = static_cast<BackingStoreAura*>( |
| + host_->GetBackingStore(true)); |
| + paint_canvas_ = NULL; |
| + backing_store->SkiaShowRect(gfx::Point(), canvas); |
| + |
| if (paint_observer_) |
| paint_observer_->OnPaintComplete(); |
| } else if (aura::Env::GetInstance()->render_white_bg()) { |
| @@ -2361,7 +2426,7 @@ void RenderWidgetHostViewAura::OnCompositingDidCommit( |
| if ((*it)->GrabDeferredLock()) |
| can_lock_compositor_ = YES_DID_LOCK; |
| } |
| - RunCompositingDidCommitCallbacks(); |
| + RunOnCommitCallbacks(); |
| locks_pending_commit_.clear(); |
| } |
| @@ -2460,7 +2525,7 @@ void RenderWidgetHostViewAura::OnLostResources() { |
| // 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. |
| - RunCompositingDidCommitCallbacks(); |
| + RunOnCommitCallbacks(); |
| DCHECK(!shared_surface_handle_.is_null()); |
| ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); |
| @@ -2616,7 +2681,7 @@ bool RenderWidgetHostViewAura::ShouldMoveToCenter() { |
| global_mouse_position_.y() > rect.bottom() - border_y; |
| } |
| -void RenderWidgetHostViewAura::RunCompositingDidCommitCallbacks() { |
| +void RenderWidgetHostViewAura::RunOnCommitCallbacks() { |
| for (std::vector<base::Closure>::const_iterator |
| it = on_compositing_did_commit_callbacks_.begin(); |
| it != on_compositing_did_commit_callbacks_.end(); ++it) { |
| @@ -2625,6 +2690,20 @@ void RenderWidgetHostViewAura::RunCompositingDidCommitCallbacks() { |
| on_compositing_did_commit_callbacks_.clear(); |
| } |
| +void RenderWidgetHostViewAura::AddOnCommitCallback( |
| + const base::Closure& callback) { |
| + ui::Compositor* compositor = GetCompositor(); |
| + if (!compositor) |
| + return; |
| + |
| + if (!compositor->HasObserver(this)) |
| + compositor->AddObserver(this); |
| + |
| + can_lock_compositor_ = NO_PENDING_COMMIT; |
| + on_compositing_did_commit_callbacks_.push_back(callback); |
| + return; |
| +} |
| + |
| void RenderWidgetHostViewAura::AddedToRootWindow() { |
| window_->GetRootWindow()->AddRootWindowObserver(this); |
| host_->ParentChanged(GetNativeViewId()); |
| @@ -2644,7 +2723,7 @@ void RenderWidgetHostViewAura::RemovingFromRootWindow() { |
| // frame though, because we will reissue a new frame right away without that |
| // composited data. |
| ui::Compositor* compositor = GetCompositor(); |
| - RunCompositingDidCommitCallbacks(); |
| + RunOnCommitCallbacks(); |
| locks_pending_commit_.clear(); |
| if (compositor && compositor->HasObserver(this)) |
| compositor->RemoveObserver(this); |