Index: content/browser/compositor/browser_compositor_view_private_mac.mm |
diff --git a/content/browser/compositor/browser_compositor_view_private_mac.mm b/content/browser/compositor/browser_compositor_view_private_mac.mm |
index cd6ed66cc6d539eb944ad2e7eadfff6f07b4b376..8a1b392484dce56907f13a28a1910d08fd42cae8 100644 |
--- a/content/browser/compositor/browser_compositor_view_private_mac.mm |
+++ b/content/browser/compositor/browser_compositor_view_private_mac.mm |
@@ -132,7 +132,7 @@ void BrowserCompositorViewMacInternal::GotAcceleratedFrame( |
// If there is no client and therefore no superview to draw into, early-out. |
if (!client_) { |
- AcceleratedLayerDidDrawFrame(true); |
+ AcceleratedLayerDidDrawFrame(); |
return; |
} |
@@ -178,23 +178,16 @@ void BrowserCompositorViewMacInternal::GotAcceleratedCAContextFrame( |
// Acknowledge the frame to unblock the compositor immediately (the GPU |
// process will do any required throttling). |
- AcceleratedLayerDidDrawFrame(true); |
+ AcceleratedLayerDidDrawFrame(); |
// If this replacing a same-type layer, remove it now that the new layer is |
// in the hierarchy. |
if (old_ca_context_layer != ca_context_layer_) |
- [old_ca_context_layer removeFromSuperlayer]; |
+ DestroyCAContextLayer(old_ca_context_layer); |
// Remove any different-type layers that this is replacing. |
- if (io_surface_layer_) { |
- [io_surface_layer_ resetClient]; |
- [io_surface_layer_ removeFromSuperlayer]; |
- io_surface_layer_.reset(); |
- } |
- if (software_layer_) { |
- [software_layer_ removeFromSuperlayer]; |
- software_layer_.reset(); |
- } |
+ DestroyIOSurfaceLayer(io_surface_layer_); |
+ DestroySoftwareLayer(); |
} |
void BrowserCompositorViewMacInternal::GotAcceleratedIOSurfaceFrame( |
@@ -216,51 +209,64 @@ void BrowserCompositorViewMacInternal::GotAcceleratedIOSurfaceFrame( |
if (needs_new_layer) { |
scoped_refptr<content::CompositingIOSurfaceMac> iosurface = |
content::CompositingIOSurfaceMac::Create(); |
- io_surface_layer_.reset([[CompositingIOSurfaceLayer alloc] |
- initWithIOSurface:iosurface |
- withScaleFactor:scale_factor |
- withClient:this]); |
- [flipped_layer_ addSublayer:io_surface_layer_]; |
+ if (!iosurface) { |
+ LOG(ERROR) << "Failed to create CompositingIOSurfaceMac"; |
+ } else { |
+ io_surface_layer_.reset([[CompositingIOSurfaceLayer alloc] |
+ initWithIOSurface:iosurface |
+ withScaleFactor:scale_factor |
+ withClient:this]); |
+ if (io_surface_layer_) |
+ [flipped_layer_ addSublayer:io_surface_layer_]; |
+ else |
+ LOG(ERROR) << "Failed to create CompositingIOSurfaceLayer"; |
+ } |
} |
// Open the provided IOSurface. |
- { |
+ if (io_surface_layer_) { |
bool result = true; |
gfx::ScopedCGLSetCurrentContext scoped_set_current_context( |
[io_surface_layer_ context]->cgl_context()); |
result = [io_surface_layer_ iosurface]->SetIOSurfaceWithContextCurrent( |
[io_surface_layer_ context], io_surface_id, pixel_size, scale_factor); |
- if (!result) |
- LOG(ERROR) << "Failed SetIOSurface on CompositingIOSurfaceMac"; |
+ if (!result) { |
+ DestroyIOSurfaceLayer(io_surface_layer_); |
+ LOG(ERROR) << "Failed open IOSurface in CompositingIOSurfaceLayer"; |
+ } |
+ } |
+ |
+ // Give a final complaint if anything with the layer's creation went wrong. |
+ // This frame will appear blank, the compositor will try to create another, |
+ // and maybe that will go better. |
+ if (!io_surface_layer_) { |
+ LOG(ERROR) << "CompositingIOSurfaceLayer is nil, tab will be blank"; |
+ AcceleratedLayerHitError(); |
+ } |
+ |
+ // Make the CALayer draw and set its size appropriately. |
+ if (io_surface_layer_) { |
+ [io_surface_layer_ gotNewFrame]; |
+ |
+ // Set the bounds of the accelerated layer to match the size of the frame. |
+ // If the bounds changed, force the content to be displayed immediately. |
+ CGRect new_layer_bounds = CGRectMake( |
+ 0, 0, last_swap_size_dip_.width(), last_swap_size_dip_.height()); |
+ bool bounds_changed = !CGRectEqualToRect( |
+ new_layer_bounds, [io_surface_layer_ bounds]); |
+ [io_surface_layer_ setBounds:new_layer_bounds]; |
+ if (bounds_changed) |
+ [io_surface_layer_ setNeedsDisplayAndDisplayAndAck]; |
} |
- [io_surface_layer_ gotNewFrame]; |
- |
- // Set the bounds of the accelerated layer to match the size of the frame. |
- // If the bounds changed, force the content to be displayed immediately. |
- CGRect new_layer_bounds = CGRectMake( |
- 0, 0, last_swap_size_dip_.width(), last_swap_size_dip_.height()); |
- bool bounds_changed = !CGRectEqualToRect( |
- new_layer_bounds, [io_surface_layer_ bounds]); |
- [io_surface_layer_ setBounds:new_layer_bounds]; |
- if (bounds_changed) |
- [io_surface_layer_ setNeedsDisplayAndDisplayAndAck]; |
// If this replacing a same-type layer, remove it now that the new layer is |
// in the hierarchy. |
- if (old_io_surface_layer != io_surface_layer_) { |
- [old_io_surface_layer resetClient]; |
- [old_io_surface_layer removeFromSuperlayer]; |
- } |
+ if (old_io_surface_layer != io_surface_layer_) |
+ DestroyIOSurfaceLayer(old_io_surface_layer); |
// Remove any different-type layers that this is replacing. |
- if (ca_context_layer_) { |
- [ca_context_layer_ removeFromSuperlayer]; |
- ca_context_layer_.reset(); |
- } |
- if (software_layer_) { |
- [software_layer_ removeFromSuperlayer]; |
- software_layer_.reset(); |
- } |
+ DestroyCAContextLayer(ca_context_layer_); |
+ DestroySoftwareLayer(); |
} |
void BrowserCompositorViewMacInternal::GotSoftwareFrame( |
@@ -291,15 +297,34 @@ void BrowserCompositorViewMacInternal::GotSoftwareFrame( |
last_swap_size_dip_ = ConvertSizeToDIP(scale_factor, pixel_size); |
// Remove any different-type layers that this is replacing. |
- if (ca_context_layer_) { |
- [ca_context_layer_ removeFromSuperlayer]; |
+ DestroyCAContextLayer(ca_context_layer_); |
+ DestroyIOSurfaceLayer(io_surface_layer_); |
+} |
+ |
+void BrowserCompositorViewMacInternal::DestroyCAContextLayer( |
+ base::scoped_nsobject<CALayerHost> ca_context_layer) { |
+ if (!ca_context_layer) |
+ return; |
+ [ca_context_layer removeFromSuperlayer]; |
+ if (ca_context_layer == ca_context_layer_) |
ca_context_layer_.reset(); |
- } |
- if (io_surface_layer_) { |
- [io_surface_layer_ resetClient]; |
- [io_surface_layer_ removeFromSuperlayer]; |
+} |
+ |
+void BrowserCompositorViewMacInternal::DestroyIOSurfaceLayer( |
+ base::scoped_nsobject<CompositingIOSurfaceLayer> io_surface_layer) { |
+ if (!io_surface_layer) |
+ return; |
+ [io_surface_layer resetClient]; |
+ [io_surface_layer removeFromSuperlayer]; |
+ if (io_surface_layer == io_surface_layer_) |
io_surface_layer_.reset(); |
- } |
+} |
+ |
+void BrowserCompositorViewMacInternal::DestroySoftwareLayer() { |
+ if (!software_layer_) |
+ return; |
+ [software_layer_ removeFromSuperlayer]; |
+ software_layer_.reset(); |
} |
bool BrowserCompositorViewMacInternal::AcceleratedLayerShouldAckImmediately() |
@@ -311,8 +336,7 @@ bool BrowserCompositorViewMacInternal::AcceleratedLayerShouldAckImmediately() |
return client_->BrowserCompositorViewShouldAckImmediately(); |
} |
-void BrowserCompositorViewMacInternal::AcceleratedLayerDidDrawFrame( |
- bool succeeded) { |
+void BrowserCompositorViewMacInternal::AcceleratedLayerDidDrawFrame() { |
if (accelerated_output_surface_id_) { |
content::ImageTransportFactory::GetInstance()->OnSurfaceDisplayed( |
accelerated_output_surface_id_); |
@@ -323,12 +347,17 @@ void BrowserCompositorViewMacInternal::AcceleratedLayerDidDrawFrame( |
client_->BrowserCompositorViewFrameSwapped(accelerated_latency_info_); |
accelerated_latency_info_.clear(); |
+} |
- if (!succeeded) { |
- if (io_surface_layer_) |
- [io_surface_layer_ context]->PoisonContextAndSharegroup(); |
- compositor_->ScheduleFullRedraw(); |
- } |
+void BrowserCompositorViewMacInternal::AcceleratedLayerHitError() { |
+ // Perform all acks that would have been done if the frame had succeeded, to |
+ // un-block the compositor and renderer. |
+ AcceleratedLayerDidDrawFrame(); |
+ |
+ // Poison the context being used and request a mulligan. |
+ if (io_surface_layer_) |
+ [io_surface_layer_ context]->PoisonContextAndSharegroup(); |
+ compositor_->ScheduleFullRedraw(); |
} |
// static |