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 b50fd999cff0582dc07c2c22a923cb37f611db70..50f1ad4cd968f6095ef39740062b6f710dce74ac 100644 |
| --- a/content/browser/renderer_host/render_widget_host_view_mac.mm |
| +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm |
| @@ -611,8 +611,7 @@ void RenderWidgetHostViewMac::EnsureSoftwareLayer() { |
| if (software_layer_ || !use_core_animation_) |
| return; |
| - software_layer_.reset([[SoftwareLayer alloc] |
| - initWithRenderWidgetHostViewMac:this]); |
| + software_layer_.reset([[SoftwareLayer alloc] init]); |
| DCHECK(software_layer_); |
| // Disable the fade-in animation as the layer is added. |
| @@ -872,7 +871,6 @@ void RenderWidgetHostViewMac::WasShown() { |
| // Call setNeedsDisplay before pausing for new frames to come in -- if any |
| // do, and are drawn, then the needsDisplay bit will be cleared. |
| - [software_layer_ setNeedsDisplay]; |
| [compositing_iosurface_layer_ setNeedsDisplay]; |
| PauseForPendingResizeOrRepaintsAndDraw(); |
| @@ -1574,6 +1572,50 @@ void RenderWidgetHostViewMac::CompositorSwapBuffers( |
| LayoutLayers(); |
| } |
| +void RenderWidgetHostViewMac::GotBrowserCompositorSoftwareFrame( |
| + cc::SoftwareFrameData* frame_data, |
| + float scale_factor, |
| + SkCanvas* canvas) { |
| + if (!frame_data || !canvas) |
| + return; |
| + |
| + // Disable animating the contents change or the scale factor change. |
| + ScopedCAActionDisabler disabler; |
| + EnsureSoftwareLayer(); |
| + |
| + // Set the contents of the software CALayer to be a CGImage with the provided |
| + // pixel data. |
| + SkImageInfo info; |
| + size_t row_bytes; |
| + const void* pixels = canvas->peekPixels(&info, &row_bytes); |
| + base::ScopedCFTypeRef<CGDataProviderRef> data_provider( |
| + CGDataProviderCreateWithData( |
| + NULL, pixels, 4 * info.fWidth * info.fHeight, NULL)); |
|
piman
2014/05/20 07:04:17
Doesn't this assume that CoreAnimation won't look
ccameron
2014/05/20 19:15:50
The documentation is very unclear, but this does a
|
| + base::ScopedCFTypeRef<CGImageRef> image( |
| + CGImageCreate(info.fWidth, |
| + info.fHeight, |
| + 8, |
| + 32, |
| + row_bytes, |
| + base::mac::GetSystemColorSpace(), |
| + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, |
| + data_provider, |
| + NULL, |
| + false, |
| + kCGRenderingIntentDefault)); |
| + [software_layer_ setContents:(id)image.get()]; |
| + |
| + // Set the contents scale of the software CALayer. |
| + if ([software_layer_ respondsToSelector:(@selector(contentsScale))] && |
| + [software_layer_ respondsToSelector:(@selector(setContentsScale:))] && |
| + [software_layer_ contentsScale] != scale_factor) { |
| + [software_layer_ setContentsScale:scale_factor]; |
| + } |
| + |
| + LayoutLayers(); |
| + DestroyCompositedIOSurfaceAndLayer(kDestroyContext); |
| +} |
| + |
| void RenderWidgetHostViewMac::DrawIOSurfaceWithoutCoreAnimation() { |
| CHECK(!use_core_animation_); |
| CHECK(compositing_iosurface_); |
| @@ -1897,6 +1939,8 @@ bool RenderWidgetHostViewMac::HasAcceleratedSurface( |
| void RenderWidgetHostViewMac::OnSwapCompositorFrame( |
| uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) { |
| + TRACE_EVENT0("browser", "RenderWidgetHostViewMac::OnSwapCompositorFrame"); |
| + |
| if (frame->delegated_frame_data) { |
| if (!compositor_) { |
| compositor_.reset(new ui::Compositor(cocoa_view_)); |
| @@ -1936,6 +1980,48 @@ void RenderWidgetHostViewMac::OnSwapCompositorFrame( |
| AddPendingLatencyInfo(frame->metadata.latency_info); |
| GotSoftwareFrame(); |
| + if (use_core_animation_) { |
| + // Disable animating the contents change or the scale factor change. |
| + ScopedCAActionDisabler disabler; |
| + EnsureSoftwareLayer(); |
| + |
| + // Set the contents of the software CALayer to be a CGImage with the |
| + // provided pixel data. |
| + gfx::Size size_in_pixels = |
| + software_frame_manager_->GetCurrentFrameSizeInPixels(); |
| + base::ScopedCFTypeRef<CGDataProviderRef> data_provider( |
| + CGDataProviderCreateWithData( |
| + NULL, |
| + software_frame_manager_->GetCurrentFramePixels(), |
| + 4 * size_in_pixels.width() * size_in_pixels.height(), |
| + NULL)); |
| + base::ScopedCFTypeRef<CGImageRef> image(CGImageCreate( |
| + size_in_pixels.width(), |
| + size_in_pixels.height(), |
| + 8, |
| + 32, |
| + 4 * size_in_pixels.width(), |
| + base::mac::GetSystemColorSpace(), |
| + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, |
| + data_provider, |
| + NULL, |
| + false, |
| + kCGRenderingIntentDefault)); |
| + [software_layer_ setContents:(id)image.get()]; |
| + |
| + // Set the contents scale of the software CALayer. |
| + if ([software_layer_ respondsToSelector:(@selector(contentsScale))] && |
| + [software_layer_ respondsToSelector:(@selector(setContentsScale:))] && |
| + [software_layer_ contentsScale] != |
| + frame->metadata.device_scale_factor) { |
| + [software_layer_ setContentsScale:frame->metadata.device_scale_factor]; |
| + } |
| + |
| + // Send latency information to the host immediately, as there will be no |
| + // subsequent draw call in which to do so. |
| + SendPendingLatencyInfoToHost(); |
| + } |
| + |
| cc::CompositorFrameAck ack; |
| RenderWidgetHostImpl::SendSwapCompositorFrameAck( |
| render_widget_host_->GetRoutingID(), |
| @@ -2077,6 +2163,8 @@ void RenderWidgetHostViewMac::GotAcceleratedFrame() { |
| } |
| void RenderWidgetHostViewMac::GotSoftwareFrame() { |
| + TRACE_EVENT0("browser", "RenderWidgetHostViewMac::GotSoftwareFrame"); |
| + |
| if (!render_widget_host_) |
| return; |
| @@ -2088,7 +2176,6 @@ void RenderWidgetHostViewMac::GotSoftwareFrame() { |
| // happen before the frame be acked, otherwise the new frame will likely be |
| // ready before the drawing is complete, thrashing the browser main thread. |
| if (use_core_animation_) { |
| - [software_layer_ setNeedsDisplay]; |
| [software_layer_ displayIfNeeded]; |
| } else { |
| [cocoa_view_ setNeedsDisplay:YES]; |
| @@ -2333,15 +2420,14 @@ void RenderWidgetHostViewMac::TickPendingLatencyInfoDelay() { |
| [compositing_iosurface_layer_ gotNewFrame]; |
| } |
| if (software_layer_) { |
| - // In software mode, setNeedsDisplay will almost immediately result in the |
| - // layer's draw function being called, so manually insert a pretend-vsync |
| - // at 60 Hz. |
| + // In software mode there is not an explicit setNeedsDisplay/display loop, |
| + // so just wait a pretend-vsync at 60 Hz. |
| base::MessageLoop::current()->PostDelayedTask( |
| FROM_HERE, |
| base::Bind(&RenderWidgetHostViewMac::TickPendingLatencyInfoDelay, |
| pending_latency_info_delay_weak_ptr_factory_.GetWeakPtr()), |
| base::TimeDelta::FromMilliseconds(1000/60)); |
| - [software_layer_ setNeedsDisplay]; |
| + SendPendingLatencyInfoToHost(); |
| } |
| } |
| @@ -2447,17 +2533,6 @@ void RenderWidgetHostViewMac::LayoutLayers() { |
| } |
| } |
| - // Dynamically update the software layer's contents scale to match the |
| - // software frame. |
| - if (software_frame_manager_->HasCurrentFrame() && |
| - [software_layer_ respondsToSelector:(@selector(contentsScale))] && |
| - [software_layer_ respondsToSelector:(@selector(setContentsScale:))]) { |
| - if (software_frame_manager_->GetCurrentFrameDeviceScaleFactor() != |
| - [software_layer_ contentsScale]) { |
| - [software_layer_ setContentsScale: |
| - software_frame_manager_->GetCurrentFrameDeviceScaleFactor()]; |
| - } |
| - } |
| // Changing the software layer's bounds and position doesn't always result |
| // in the layer being anchored to the top-left. Set the layer's frame |
| // explicitly, since this is more reliable in practice. |
| @@ -2466,7 +2541,6 @@ void RenderWidgetHostViewMac::LayoutLayers() { |
| new_background_frame, [software_layer_ frame]); |
| if (frame_changed) { |
| [software_layer_ setFrame:new_background_frame]; |
| - [software_layer_ setNeedsDisplay]; |
| } |
| } |
| } |
| @@ -3319,6 +3393,13 @@ SkBitmap::Config RenderWidgetHostViewMac::PreferredReadbackFormat() { |
| params.latency_info); |
| } |
| +- (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data |
| + withScaleFactor:(float)scale_factor |
| + withCanvas:(SkCanvas*)canvas { |
| + renderWidgetHostView_->GotBrowserCompositorSoftwareFrame( |
| + frame_data, scale_factor, canvas); |
| +} |
| + |
| - (void)drawRect:(NSRect)dirtyRect { |
| TRACE_EVENT0("browser", "RenderWidgetHostViewCocoa::drawRect"); |
| DCHECK(!renderWidgetHostView_->use_core_animation_); |
| @@ -4389,46 +4470,21 @@ extern NSString *NSTextInputReplacementRangeAttributeName; |
| @implementation SoftwareLayer |
| -- (id)initWithRenderWidgetHostViewMac:(content::RenderWidgetHostViewMac*)r { |
| +- (id)init { |
| if (self = [super init]) { |
| - renderWidgetHostView_ = r; |
| - |
| [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)]; |
| [self setAnchorPoint:CGPointMake(0, 0)]; |
| // Setting contents gravity is necessary to prevent the layer from being |
| // scaled during dyanmic resizes (especially with devtools open). |
| [self setContentsGravity:kCAGravityTopLeft]; |
| - if (renderWidgetHostView_->software_frame_manager_->HasCurrentFrame() && |
| - [self respondsToSelector:(@selector(setContentsScale:))]) { |
| - [self setContentsScale:renderWidgetHostView_->software_frame_manager_-> |
| - GetCurrentFrameDeviceScaleFactor()]; |
| - } |
| - |
| - // Ensure that the transition between frames not be animated. |
| - [self setActions:@{ @"contents" : [NSNull null] }]; |
| } |
| return self; |
| } |
| -- (void)drawInContext:(CGContextRef)context { |
| - TRACE_EVENT0("browser", "SoftwareLayer::drawInContext"); |
| - |
| - CGRect clipRect = CGContextGetClipBoundingBox(context); |
| - if (renderWidgetHostView_) { |
| - [renderWidgetHostView_->cocoa_view() drawWithDirtyRect:clipRect |
| - inContext:context]; |
| - } else { |
| - CGContextSetFillColorWithColor(context, |
| - CGColorGetConstantColor(kCGColorWhite)); |
| - CGContextFillRect(context, clipRect); |
| - } |
| -} |
| - |
| - (void)disableRendering { |
| // Disable the fade-out animation as the layer is removed. |
| ScopedCAActionDisabler disabler; |
| [self removeFromSuperlayer]; |
| - renderWidgetHostView_ = nil; |
| } |
| @end // implementation SoftwareLayer |