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 443eee97de207ab2a71a8152c2fc42f4ffc91b2c..f6fac8bb96aa3415f1251a7665e9ee4399d27222 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc |
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc |
@@ -918,7 +918,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() { |
@@ -1219,13 +1219,13 @@ void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() { |
accelerated_compositing_state_changed_ = true; |
} |
-bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) { |
+bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) const { |
if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME || |
can_lock_compositor_ == NO_PENDING_COMMIT || |
resize_locks_.empty()) |
return false; |
- ResizeLockList::iterator it = resize_locks_.begin(); |
+ ResizeLockList::const_iterator it = resize_locks_.begin(); |
while (it != resize_locks_.end()) { |
if ((*it)->expected_size() == size_in_dip) |
break; |
@@ -1273,10 +1273,15 @@ void RenderWidgetHostViewAura::UpdateExternalTexture() { |
if (accelerated_compositing_state_changed_) |
accelerated_compositing_state_changed_ = false; |
- if (current_surface_ && host_->is_accelerated_compositing_active()) { |
+ bool is_compositing_active = host_->is_accelerated_compositing_active(); |
+ if (is_compositing_active && current_surface_) { |
window_->SetExternalTexture(current_surface_.get()); |
gfx::Size container_size = ConvertSizeToDIP(this, current_surface_->size()); |
CheckResizeLocks(container_size); |
+ } else if (is_compositing_active && current_dib_) { |
+ window_->SetExternalTexture(NULL); |
+ gfx::Size frame_size = ConvertSizeToDIP(this, last_swapped_surface_size_); |
+ CheckResizeLocks(frame_size); |
} else { |
window_->SetExternalTexture(NULL); |
resize_locks_.clear(); |
@@ -1326,12 +1331,8 @@ void RenderWidgetHostViewAura::SwapBuffersCompleted( |
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( |
+ AddOnCommitCallbackAndDisableLocks( |
base::Bind(ack_callback, false, texture_to_return)); |
- if (!compositor->HasObserver(this)) |
- compositor->AddObserver(this); |
} |
} |
@@ -1400,12 +1401,9 @@ void RenderWidgetHostViewAura::SwapDelegatedFrame( |
if (!compositor) { |
SendDelegatedFrameAck(); |
} else { |
- can_lock_compositor_ = NO_PENDING_COMMIT; |
- on_compositing_did_commit_callbacks_.push_back( |
+ AddOnCommitCallbackAndDisableLocks( |
base::Bind(&RenderWidgetHostViewAura::SendDelegatedFrameAck, |
- base::Unretained(this))); |
- if (!compositor->HasObserver(this)) |
- compositor->AddObserver(this); |
+ AsWeakPtr())); |
} |
} |
@@ -1416,6 +1414,80 @@ 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; |
+ const TransportDIB::Id& dib_id = frame_data->dib_id; |
+ |
+ scoped_ptr<TransportDIB> dib; |
+#if defined(OS_WIN) |
+ TransportDIB::Handle my_handle = TransportDIB::DefaultHandleValue(); |
+ ::DuplicateHandle(host_->GetProcess()->GetHandle(), dib_id.handle, |
+ ::GetCurrentProcess(), &my_handle, |
+ 0, FALSE, DUPLICATE_SAME_ACCESS); |
+ dib.reset(TransportDIB::Map(my_handle)); |
+#elif defined(USE_X11) |
+ dib.reset(TransportDIB::Map(dib_id.shmkey)); |
+#else |
+ NOTIMPLEMENTED(); |
+#endif |
+ |
+ // Validate the received DIB. |
+ size_t expected_size = 4 * frame_size.GetArea(); |
+ if (!dib || dib->size() < expected_size) { |
+ host_->GetProcess()->ReceivedBadMessage(); |
+ return; |
+ } |
+ |
+ if (last_swapped_surface_size_ != frame_size) { |
+ DLOG_IF(ERROR, damage_rect != gfx::Rect(frame_size)) |
+ << "Expected full damage rect"; |
+ } |
+ |
+ TransportDIB::Id last_dib_id = current_dib_id_; |
+ current_dib_.reset(dib.release()); |
+ current_dib_id_ = dib_id; |
+ last_swapped_surface_size_ = frame_size; |
+ previous_damage_.op(RectToSkIRect(damage_rect), SkRegion::kUnion_Op); |
+ |
+ ui::Compositor* compositor = GetCompositor(); |
+ gfx::Size frame_size_in_dip = gfx::ToFlooredSize( |
+ gfx::ScaleSize(frame_size, 1.0f / frame_device_scale_factor)); |
+ if (!compositor) { |
+ SendSoftwareFrameAck(last_dib_id); |
+ return; |
+ } |
+ |
+ window_->SetExternalTexture(NULL); |
+ released_front_lock_ = NULL; |
+ CheckResizeLocks(frame_size_in_dip); |
+ |
+ if (ShouldSkipFrame(frame_size_in_dip)) { |
+ can_lock_compositor_ = NO_PENDING_COMMIT; |
+ SendSoftwareFrameAck(last_dib_id); |
+ } else { |
+ AddOnCommitCallbackAndDisableLocks( |
+ base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck, |
+ AsWeakPtr(), last_dib_id)); |
+ } |
+ |
+ if (paint_observer_) |
+ paint_observer_->OnUpdateCompositorContent(); |
+ window_->SchedulePaintInRect(ConvertRectToDIP(this, damage_rect)); |
+} |
+ |
+void RenderWidgetHostViewAura::SendSoftwareFrameAck( |
+ const TransportDIB::Id& id) { |
+ if (!TransportDIB::is_valid_id(id)) |
+ return; |
+ cc::CompositorFrameAck ack; |
+ ack.last_dib_id = id; |
+ RenderWidgetHostImpl::SendSwapCompositorFrameAck( |
+ host_->GetRoutingID(), host_->GetProcess()->GetID(), ack); |
+} |
+ |
void RenderWidgetHostViewAura::OnSwapCompositorFrame( |
scoped_ptr<cc::CompositorFrame> frame) { |
if (frame->delegated_frame_data) { |
@@ -1423,6 +1495,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; |
@@ -1452,7 +1531,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; |
@@ -1478,7 +1557,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, |
@@ -1552,15 +1631,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( |
+ AddOnCommitCallbackAndDisableLocks( |
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(); |
@@ -1943,12 +2019,47 @@ 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_) { |
+ const gfx::Size window_size = window_->bounds().size(); |
+ const gfx::Size& frame_size = last_swapped_surface_size_; |
+ |
+ SkBitmap bitmap; |
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, |
+ frame_size.width(), |
+ frame_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 (frame_size != window_size) { |
+ SkRegion region; |
+ region.op(0, 0, window_size.width(), window_size.height(), |
+ SkRegion::kUnion_Op); |
+ region.op(0, 0, frame_size.width(), frame_size.height(), |
+ SkRegion::kDifference_Op); |
+ SkPaint paint; |
+ paint.setColor(SK_ColorWHITE); |
+ for (SkRegion::Iterator it(region); !it.done(); it.next()) |
+ sk_canvas->drawIRect(it.rect(), paint); |
+ } |
+ |
+ 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()) { |
@@ -2366,7 +2477,7 @@ void RenderWidgetHostViewAura::OnCompositingDidCommit( |
if ((*it)->GrabDeferredLock()) |
can_lock_compositor_ = YES_DID_LOCK; |
} |
- RunCompositingDidCommitCallbacks(); |
+ RunOnCommitCallbacks(); |
locks_pending_commit_.clear(); |
} |
@@ -2465,7 +2576,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(); |
@@ -2621,7 +2732,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) { |
@@ -2630,6 +2741,18 @@ void RenderWidgetHostViewAura::RunCompositingDidCommitCallbacks() { |
on_compositing_did_commit_callbacks_.clear(); |
} |
+void RenderWidgetHostViewAura::AddOnCommitCallbackAndDisableLocks( |
+ const base::Closure& callback) { |
+ ui::Compositor* compositor = GetCompositor(); |
+ DCHECK(compositor); |
+ |
+ if (!compositor->HasObserver(this)) |
+ compositor->AddObserver(this); |
+ |
+ can_lock_compositor_ = NO_PENDING_COMMIT; |
+ on_compositing_did_commit_callbacks_.push_back(callback); |
+} |
+ |
void RenderWidgetHostViewAura::AddedToRootWindow() { |
window_->GetRootWindow()->AddRootWindowObserver(this); |
host_->ParentChanged(GetNativeViewId()); |
@@ -2649,7 +2772,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); |