Chromium Code Reviews| Index: content/browser/renderer_host/render_widget_host_view_mac.mm |
| diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm |
| index 02c66aa03f9ff454a992bc44371f0b660e35358d..ecad063b28d74b4e113406b3f82b6f1dd04edbd7 100644 |
| --- a/content/browser/renderer_host/render_widget_host_view_mac.mm |
| +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm |
| @@ -426,7 +426,10 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) |
| weak_factory_(this), |
| fullscreen_parent_host_view_(NULL), |
| pending_swap_buffers_acks_weak_factory_(this), |
| - next_swap_ack_time_(base::Time::Now()) { |
| + next_swap_ack_time_(base::Time::Now()), |
| + software_frame_weak_ptr_factory_(this) { |
| + software_frame_manager_.reset(new SoftwareFrameManager( |
| + software_frame_weak_ptr_factory_.GetWeakPtr())); |
| // |cocoa_view_| owns us and we will be deleted when |cocoa_view_| |
| // goes away. Since we autorelease it, our caller must put |
| // |GetNativeView()| into the view hierarchy right after calling us. |
| @@ -732,6 +735,7 @@ void RenderWidgetHostViewMac::WasShown() { |
| if (web_contents_switch_paint_time_.is_null()) |
| web_contents_switch_paint_time_ = base::TimeTicks::Now(); |
| render_widget_host_->WasShown(); |
| + software_frame_manager_->SetVisibility(true); |
| // We're messing with the window, so do this to ensure no flashes. |
| if (!use_core_animation_) |
| @@ -751,6 +755,7 @@ void RenderWidgetHostViewMac::WasHidden() { |
| // If we have a renderer, then inform it that we are being hidden so it can |
| // reduce its resource utilization. |
| render_widget_host_->WasHidden(); |
| + software_frame_manager_->SetVisibility(false); |
| // There can be a transparent flash as this view is removed and the next is |
| // added, because of OSX windowing races between displaying the contents of |
| @@ -1650,17 +1655,47 @@ void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() { |
| bool RenderWidgetHostViewMac::HasAcceleratedSurface( |
| const gfx::Size& desired_size) { |
| - return last_frame_was_accelerated_ && |
| - compositing_iosurface_ && |
| - compositing_iosurface_->HasIOSurface() && |
| - (desired_size.IsEmpty() || |
| - compositing_iosurface_->dip_io_surface_size() == desired_size); |
| + if (last_frame_was_accelerated_) { |
| + return compositing_iosurface_ && |
| + compositing_iosurface_->HasIOSurface() && |
| + (desired_size.IsEmpty() || |
| + compositing_iosurface_->dip_io_surface_size() == desired_size); |
| + } else { |
| + return (software_frame_manager_->HasCurrentFrame() && |
| + (desired_size.IsEmpty() || |
| + software_frame_manager_->GetCurrentFrameSizeInDIP() == |
| + desired_size)); |
| + } |
| + return false; |
| } |
| void RenderWidgetHostViewMac::AboutToWaitForBackingStoreMsg() { |
| AckPendingSwapBuffers(); |
| } |
| +void RenderWidgetHostViewMac::OnSwapCompositorFrame( |
| + uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) { |
| + // Only software compositor frames are accepted. |
| + if (!frame->software_frame_data) { |
| + render_widget_host_->GetProcess()->ReceivedBadMessage(); |
|
piman
2013/10/22 22:32:48
That's quite extreme :) Do we really need to kill
ccameron
2013/10/23 01:05:58
I'd rather blow up the renderer than silently acce
piman
2013/10/23 23:41:40
So, you're not accepting input, you're just droppi
|
| + return; |
| + } |
| + |
| + GotSoftwareFrame(); |
| + if (!software_frame_manager_->SwapToNewFrame( |
| + output_surface_id, |
| + frame->software_frame_data.get(), |
| + frame->metadata.device_scale_factor, |
| + render_widget_host_->GetProcess()->GetHandle())) { |
| + render_widget_host_->GetProcess()->ReceivedBadMessage(); |
| + return; |
| + } |
| + software_frame_manager_->SwapToNewFrameComplete( |
| + !render_widget_host_->is_hidden()); |
| + |
| + [cocoa_view_ setNeedsDisplay:YES]; |
| +} |
| + |
| void RenderWidgetHostViewMac::OnAcceleratedCompositingStateChange() { |
| } |
| @@ -1741,6 +1776,19 @@ bool RenderWidgetHostViewMac::Send(IPC::Message* message) { |
| return false; |
| } |
| +void RenderWidgetHostViewMac::SoftwareFrameWasFreed( |
| + uint32 output_surface_id, unsigned frame_id) { |
| + cc::CompositorFrameAck ack; |
| + ack.last_software_frame_id = frame_id; |
| + RenderWidgetHostImpl::SendReclaimCompositorResources( |
| + render_widget_host_->GetRoutingID(), |
| + output_surface_id, |
| + render_widget_host_->GetProcess()->GetID(), |
| + ack); |
| +} |
| + |
| +void RenderWidgetHostViewMac::CurrentSoftwareFrameWasEvicted() { |
| +} |
| void RenderWidgetHostViewMac::ShutdownHost() { |
| weak_factory_.InvalidateWeakPtrs(); |
| @@ -1764,6 +1812,7 @@ void RenderWidgetHostViewMac::GotAcceleratedFrame() { |
| // Delete software backingstore. |
| BackingStoreManager::RemoveBackingStore(render_widget_host_); |
| + software_frame_manager_->DiscardCurrentFrame(); |
| } |
| } |
| @@ -2718,29 +2767,62 @@ void RenderWidgetHostViewMac::FrameSwapped() { |
| - (void)drawBackingStore:(BackingStoreMac*)backingStore |
| dirtyRect:(CGRect)dirtyRect |
| inContext:(CGContextRef)context { |
| - if (backingStore) { |
| + content::SoftwareFrameManager* software_frame_manager = |
| + renderWidgetHostView_->software_frame_manager_.get(); |
| + // There should never be both a legacy software and software composited |
| + // frame. |
| + DCHECK(!backingStore || !software_frame_manager->HasCurrentFrame()); |
| + |
| + if (backingStore || software_frame_manager->HasCurrentFrame()) { |
| // Note: All coordinates are in view units, not pixels. |
| - gfx::Rect bitmapRect(0, 0, |
| - backingStore->size().width(), |
| - backingStore->size().height()); |
| + gfx::Rect bitmapRect( |
| + software_frame_manager->HasCurrentFrame() ? |
| + software_frame_manager->GetCurrentFrameSizeInDIP() : |
| + backingStore->size()); |
| // Specify the proper y offset to ensure that the view is rooted to the |
| // upper left corner. This can be negative, if the window was resized |
| // smaller and the renderer hasn't yet repainted. |
| - int yOffset = NSHeight([self bounds]) - backingStore->size().height(); |
| + int yOffset = NSHeight([self bounds]) - bitmapRect.height(); |
| NSRect nsDirtyRect = NSRectFromCGRect(dirtyRect); |
| const gfx::Rect damagedRect([self flipNSRectToRect:nsDirtyRect]); |
| gfx::Rect paintRect = gfx::IntersectRects(bitmapRect, damagedRect); |
| if (!paintRect.IsEmpty()) { |
| - // if we have a CGLayer, draw that into the window |
| - if (backingStore->cg_layer()) { |
| + if (software_frame_manager->HasCurrentFrame()) { |
| + // If a software compositor framebuffer is present, draw using that. |
| + gfx::Size sizeInPixels = |
| + software_frame_manager->GetCurrentFrameSizeInPixels(); |
| + base::ScopedCFTypeRef<CGDataProviderRef> dataProvider( |
| + CGDataProviderCreateWithData( |
| + NULL, |
| + software_frame_manager->GetCurrentFramePixels(), |
| + 4 * sizeInPixels.width() * sizeInPixels.height(), |
| + NULL)); |
| + base::ScopedCFTypeRef<CGImageRef> image( |
| + CGImageCreate( |
| + sizeInPixels.width(), |
| + sizeInPixels.height(), |
| + 8, |
| + 32, |
| + 4 * sizeInPixels.width(), |
| + base::mac::GetSystemColorSpace(), |
| + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, |
| + dataProvider, |
| + NULL, |
| + false, |
| + kCGRenderingIntentDefault)); |
| + CGRect imageRect = bitmapRect.ToCGRect(); |
| + imageRect.origin.y = yOffset; |
| + CGContextDrawImage(context, imageRect, image); |
| + } else if (backingStore->cg_layer()) { |
| + // If we have a CGLayer, draw that into the window |
| // TODO: add clipping to dirtyRect if it improves drawing performance. |
| CGContextDrawLayerAtPoint(context, CGPointMake(0.0, yOffset), |
| backingStore->cg_layer()); |
| } else { |
| - // if we haven't created a layer yet, draw the cached bitmap into |
| + // If we haven't created a layer yet, draw the cached bitmap into |
| // the window. The CGLayer will be created the next time the renderer |
| // paints. |
| base::ScopedCFTypeRef<CGImageRef> image( |