Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1279)

Unified Diff: content/browser/compositor/browser_compositor_view_private_mac.mm

Issue 447113004: Fix crash in GotAcceleratedIOSurfaceFrame (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698