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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/compositor/browser_compositor_view_private_mac.h" 5 #include "content/browser/compositor/browser_compositor_view_private_mac.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 const std::vector<ui::LatencyInfo>& latency_info, 125 const std::vector<ui::LatencyInfo>& latency_info,
126 gfx::Size pixel_size, float scale_factor) { 126 gfx::Size pixel_size, float scale_factor) {
127 // Record the surface and latency info to use when acknowledging this frame. 127 // Record the surface and latency info to use when acknowledging this frame.
128 DCHECK(!accelerated_output_surface_id_); 128 DCHECK(!accelerated_output_surface_id_);
129 accelerated_output_surface_id_ = output_surface_id; 129 accelerated_output_surface_id_ = output_surface_id;
130 accelerated_latency_info_.insert(accelerated_latency_info_.end(), 130 accelerated_latency_info_.insert(accelerated_latency_info_.end(),
131 latency_info.begin(), latency_info.end()); 131 latency_info.begin(), latency_info.end());
132 132
133 // If there is no client and therefore no superview to draw into, early-out. 133 // If there is no client and therefore no superview to draw into, early-out.
134 if (!client_) { 134 if (!client_) {
135 AcceleratedLayerDidDrawFrame(true); 135 AcceleratedLayerDidDrawFrame();
136 return; 136 return;
137 } 137 }
138 138
139 // Disable the fade-in or fade-out effect if we create or remove layers. 139 // Disable the fade-in or fade-out effect if we create or remove layers.
140 ScopedCAActionDisabler disabler; 140 ScopedCAActionDisabler disabler;
141 141
142 last_swap_size_dip_ = ConvertSizeToDIP(scale_factor, pixel_size); 142 last_swap_size_dip_ = ConvertSizeToDIP(scale_factor, pixel_size);
143 switch (GetSurfaceHandleType(surface_handle)) { 143 switch (GetSurfaceHandleType(surface_handle)) {
144 case kSurfaceHandleTypeIOSurface: { 144 case kSurfaceHandleTypeIOSurface: {
145 IOSurfaceID io_surface_id = IOSurfaceIDFromSurfaceHandle(surface_handle); 145 IOSurfaceID io_surface_id = IOSurfaceIDFromSurfaceHandle(surface_handle);
(...skipping 25 matching lines...) Expand all
171 if ([ca_context_layer_ contextId] != ca_context_id) { 171 if ([ca_context_layer_ contextId] != ca_context_id) {
172 ca_context_layer_.reset([[CALayerHost alloc] init]); 172 ca_context_layer_.reset([[CALayerHost alloc] init]);
173 [ca_context_layer_ setContextId:ca_context_id]; 173 [ca_context_layer_ setContextId:ca_context_id];
174 [ca_context_layer_ 174 [ca_context_layer_
175 setAutoresizingMask:kCALayerMaxXMargin|kCALayerMaxYMargin]; 175 setAutoresizingMask:kCALayerMaxXMargin|kCALayerMaxYMargin];
176 [flipped_layer_ addSublayer:ca_context_layer_]; 176 [flipped_layer_ addSublayer:ca_context_layer_];
177 } 177 }
178 178
179 // Acknowledge the frame to unblock the compositor immediately (the GPU 179 // Acknowledge the frame to unblock the compositor immediately (the GPU
180 // process will do any required throttling). 180 // process will do any required throttling).
181 AcceleratedLayerDidDrawFrame(true); 181 AcceleratedLayerDidDrawFrame();
182 182
183 // If this replacing a same-type layer, remove it now that the new layer is 183 // If this replacing a same-type layer, remove it now that the new layer is
184 // in the hierarchy. 184 // in the hierarchy.
185 if (old_ca_context_layer != ca_context_layer_) 185 if (old_ca_context_layer != ca_context_layer_)
186 [old_ca_context_layer removeFromSuperlayer]; 186 DestroyCAContextLayer(old_ca_context_layer);
187 187
188 // Remove any different-type layers that this is replacing. 188 // Remove any different-type layers that this is replacing.
189 if (io_surface_layer_) { 189 DestroyIOSurfaceLayer(io_surface_layer_);
190 [io_surface_layer_ resetClient]; 190 DestroySoftwareLayer();
191 [io_surface_layer_ removeFromSuperlayer];
192 io_surface_layer_.reset();
193 }
194 if (software_layer_) {
195 [software_layer_ removeFromSuperlayer];
196 software_layer_.reset();
197 }
198 } 191 }
199 192
200 void BrowserCompositorViewMacInternal::GotAcceleratedIOSurfaceFrame( 193 void BrowserCompositorViewMacInternal::GotAcceleratedIOSurfaceFrame(
201 IOSurfaceID io_surface_id, 194 IOSurfaceID io_surface_id,
202 gfx::Size pixel_size, 195 gfx::Size pixel_size,
203 float scale_factor) { 196 float scale_factor) {
204 // In the layer is replaced, keep the old one around until after the new one 197 // In the layer is replaced, keep the old one around until after the new one
205 // is installed to avoid flashes. 198 // is installed to avoid flashes.
206 base::scoped_nsobject<CompositingIOSurfaceLayer> old_io_surface_layer = 199 base::scoped_nsobject<CompositingIOSurfaceLayer> old_io_surface_layer =
207 io_surface_layer_; 200 io_surface_layer_;
208 201
209 // Create or re-create an IOSurface layer if needed. If there already exists 202 // Create or re-create an IOSurface layer if needed. If there already exists
210 // a layer but it has the wrong scale factor or it was poisoned, re-create the 203 // a layer but it has the wrong scale factor or it was poisoned, re-create the
211 // layer. 204 // layer.
212 bool needs_new_layer = 205 bool needs_new_layer =
213 !io_surface_layer_ || 206 !io_surface_layer_ ||
214 [io_surface_layer_ context]->HasBeenPoisoned() || 207 [io_surface_layer_ context]->HasBeenPoisoned() ||
215 [io_surface_layer_ iosurface]->scale_factor() != scale_factor; 208 [io_surface_layer_ iosurface]->scale_factor() != scale_factor;
216 if (needs_new_layer) { 209 if (needs_new_layer) {
217 scoped_refptr<content::CompositingIOSurfaceMac> iosurface = 210 scoped_refptr<content::CompositingIOSurfaceMac> iosurface =
218 content::CompositingIOSurfaceMac::Create(); 211 content::CompositingIOSurfaceMac::Create();
219 io_surface_layer_.reset([[CompositingIOSurfaceLayer alloc] 212 if (!iosurface) {
220 initWithIOSurface:iosurface 213 LOG(ERROR) << "Failed to create CompositingIOSurfaceMac";
221 withScaleFactor:scale_factor 214 } else {
222 withClient:this]); 215 io_surface_layer_.reset([[CompositingIOSurfaceLayer alloc]
223 [flipped_layer_ addSublayer:io_surface_layer_]; 216 initWithIOSurface:iosurface
217 withScaleFactor:scale_factor
218 withClient:this]);
219 if (io_surface_layer_)
220 [flipped_layer_ addSublayer:io_surface_layer_];
221 else
222 LOG(ERROR) << "Failed to create CompositingIOSurfaceLayer";
223 }
224 } 224 }
225 225
226 // Open the provided IOSurface. 226 // Open the provided IOSurface.
227 { 227 if (io_surface_layer_) {
228 bool result = true; 228 bool result = true;
229 gfx::ScopedCGLSetCurrentContext scoped_set_current_context( 229 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
230 [io_surface_layer_ context]->cgl_context()); 230 [io_surface_layer_ context]->cgl_context());
231 result = [io_surface_layer_ iosurface]->SetIOSurfaceWithContextCurrent( 231 result = [io_surface_layer_ iosurface]->SetIOSurfaceWithContextCurrent(
232 [io_surface_layer_ context], io_surface_id, pixel_size, scale_factor); 232 [io_surface_layer_ context], io_surface_id, pixel_size, scale_factor);
233 if (!result) 233 if (!result) {
234 LOG(ERROR) << "Failed SetIOSurface on CompositingIOSurfaceMac"; 234 DestroyIOSurfaceLayer(io_surface_layer_);
235 LOG(ERROR) << "Failed open IOSurface in CompositingIOSurfaceLayer";
236 }
235 } 237 }
236 [io_surface_layer_ gotNewFrame];
237 238
238 // Set the bounds of the accelerated layer to match the size of the frame. 239 // Give a final complaint if anything with the layer's creation went wrong.
239 // If the bounds changed, force the content to be displayed immediately. 240 // This frame will appear blank, the compositor will try to create another,
240 CGRect new_layer_bounds = CGRectMake( 241 // and maybe that will go better.
241 0, 0, last_swap_size_dip_.width(), last_swap_size_dip_.height()); 242 if (!io_surface_layer_) {
242 bool bounds_changed = !CGRectEqualToRect( 243 LOG(ERROR) << "CompositingIOSurfaceLayer is nil, tab will be blank";
243 new_layer_bounds, [io_surface_layer_ bounds]); 244 AcceleratedLayerHitError();
244 [io_surface_layer_ setBounds:new_layer_bounds]; 245 }
245 if (bounds_changed) 246
246 [io_surface_layer_ setNeedsDisplayAndDisplayAndAck]; 247 // Make the CALayer draw and set its size appropriately.
248 if (io_surface_layer_) {
249 [io_surface_layer_ gotNewFrame];
250
251 // Set the bounds of the accelerated layer to match the size of the frame.
252 // If the bounds changed, force the content to be displayed immediately.
253 CGRect new_layer_bounds = CGRectMake(
254 0, 0, last_swap_size_dip_.width(), last_swap_size_dip_.height());
255 bool bounds_changed = !CGRectEqualToRect(
256 new_layer_bounds, [io_surface_layer_ bounds]);
257 [io_surface_layer_ setBounds:new_layer_bounds];
258 if (bounds_changed)
259 [io_surface_layer_ setNeedsDisplayAndDisplayAndAck];
260 }
247 261
248 // If this replacing a same-type layer, remove it now that the new layer is 262 // If this replacing a same-type layer, remove it now that the new layer is
249 // in the hierarchy. 263 // in the hierarchy.
250 if (old_io_surface_layer != io_surface_layer_) { 264 if (old_io_surface_layer != io_surface_layer_)
251 [old_io_surface_layer resetClient]; 265 DestroyIOSurfaceLayer(old_io_surface_layer);
252 [old_io_surface_layer removeFromSuperlayer];
253 }
254 266
255 // Remove any different-type layers that this is replacing. 267 // Remove any different-type layers that this is replacing.
256 if (ca_context_layer_) { 268 DestroyCAContextLayer(ca_context_layer_);
257 [ca_context_layer_ removeFromSuperlayer]; 269 DestroySoftwareLayer();
258 ca_context_layer_.reset();
259 }
260 if (software_layer_) {
261 [software_layer_ removeFromSuperlayer];
262 software_layer_.reset();
263 }
264 } 270 }
265 271
266 void BrowserCompositorViewMacInternal::GotSoftwareFrame( 272 void BrowserCompositorViewMacInternal::GotSoftwareFrame(
267 cc::SoftwareFrameData* frame_data, 273 cc::SoftwareFrameData* frame_data,
268 float scale_factor, 274 float scale_factor,
269 SkCanvas* canvas) { 275 SkCanvas* canvas) {
270 if (!frame_data || !canvas || !client_) 276 if (!frame_data || !canvas || !client_)
271 return; 277 return;
272 278
273 // Disable the fade-in or fade-out effect if we create or remove layers. 279 // Disable the fade-in or fade-out effect if we create or remove layers.
(...skipping 10 matching lines...) Expand all
284 size_t row_bytes; 290 size_t row_bytes;
285 const void* pixels = canvas->peekPixels(&info, &row_bytes); 291 const void* pixels = canvas->peekPixels(&info, &row_bytes);
286 gfx::Size pixel_size(info.fWidth, info.fHeight); 292 gfx::Size pixel_size(info.fWidth, info.fHeight);
287 [software_layer_ setContentsToData:pixels 293 [software_layer_ setContentsToData:pixels
288 withRowBytes:row_bytes 294 withRowBytes:row_bytes
289 withPixelSize:pixel_size 295 withPixelSize:pixel_size
290 withScaleFactor:scale_factor]; 296 withScaleFactor:scale_factor];
291 last_swap_size_dip_ = ConvertSizeToDIP(scale_factor, pixel_size); 297 last_swap_size_dip_ = ConvertSizeToDIP(scale_factor, pixel_size);
292 298
293 // Remove any different-type layers that this is replacing. 299 // Remove any different-type layers that this is replacing.
294 if (ca_context_layer_) { 300 DestroyCAContextLayer(ca_context_layer_);
295 [ca_context_layer_ removeFromSuperlayer]; 301 DestroyIOSurfaceLayer(io_surface_layer_);
302 }
303
304 void BrowserCompositorViewMacInternal::DestroyCAContextLayer(
305 base::scoped_nsobject<CALayerHost> ca_context_layer) {
306 if (!ca_context_layer)
307 return;
308 [ca_context_layer removeFromSuperlayer];
309 if (ca_context_layer == ca_context_layer_)
296 ca_context_layer_.reset(); 310 ca_context_layer_.reset();
297 } 311 }
298 if (io_surface_layer_) { 312
299 [io_surface_layer_ resetClient]; 313 void BrowserCompositorViewMacInternal::DestroyIOSurfaceLayer(
300 [io_surface_layer_ removeFromSuperlayer]; 314 base::scoped_nsobject<CompositingIOSurfaceLayer> io_surface_layer) {
315 if (!io_surface_layer)
316 return;
317 [io_surface_layer resetClient];
318 [io_surface_layer removeFromSuperlayer];
319 if (io_surface_layer == io_surface_layer_)
301 io_surface_layer_.reset(); 320 io_surface_layer_.reset();
302 } 321 }
322
323 void BrowserCompositorViewMacInternal::DestroySoftwareLayer() {
324 if (!software_layer_)
325 return;
326 [software_layer_ removeFromSuperlayer];
327 software_layer_.reset();
303 } 328 }
304 329
305 bool BrowserCompositorViewMacInternal::AcceleratedLayerShouldAckImmediately() 330 bool BrowserCompositorViewMacInternal::AcceleratedLayerShouldAckImmediately()
306 const { 331 const {
307 // If there is no client then the accelerated layer is not in the hierarchy 332 // If there is no client then the accelerated layer is not in the hierarchy
308 // and will never draw. 333 // and will never draw.
309 if (!client_) 334 if (!client_)
310 return true; 335 return true;
311 return client_->BrowserCompositorViewShouldAckImmediately(); 336 return client_->BrowserCompositorViewShouldAckImmediately();
312 } 337 }
313 338
314 void BrowserCompositorViewMacInternal::AcceleratedLayerDidDrawFrame( 339 void BrowserCompositorViewMacInternal::AcceleratedLayerDidDrawFrame() {
315 bool succeeded) {
316 if (accelerated_output_surface_id_) { 340 if (accelerated_output_surface_id_) {
317 content::ImageTransportFactory::GetInstance()->OnSurfaceDisplayed( 341 content::ImageTransportFactory::GetInstance()->OnSurfaceDisplayed(
318 accelerated_output_surface_id_); 342 accelerated_output_surface_id_);
319 accelerated_output_surface_id_ = 0; 343 accelerated_output_surface_id_ = 0;
320 } 344 }
321 345
322 if (client_) 346 if (client_)
323 client_->BrowserCompositorViewFrameSwapped(accelerated_latency_info_); 347 client_->BrowserCompositorViewFrameSwapped(accelerated_latency_info_);
324 348
325 accelerated_latency_info_.clear(); 349 accelerated_latency_info_.clear();
350 }
326 351
327 if (!succeeded) { 352 void BrowserCompositorViewMacInternal::AcceleratedLayerHitError() {
328 if (io_surface_layer_) 353 // Perform all acks that would have been done if the frame had succeeded, to
329 [io_surface_layer_ context]->PoisonContextAndSharegroup(); 354 // un-block the compositor and renderer.
330 compositor_->ScheduleFullRedraw(); 355 AcceleratedLayerDidDrawFrame();
331 } 356
357 // Poison the context being used and request a mulligan.
358 if (io_surface_layer_)
359 [io_surface_layer_ context]->PoisonContextAndSharegroup();
360 compositor_->ScheduleFullRedraw();
332 } 361 }
333 362
334 // static 363 // static
335 BrowserCompositorViewMacInternal* BrowserCompositorViewMacInternal:: 364 BrowserCompositorViewMacInternal* BrowserCompositorViewMacInternal::
336 FromAcceleratedWidget(gfx::AcceleratedWidget widget) { 365 FromAcceleratedWidget(gfx::AcceleratedWidget widget) {
337 WidgetToInternalsMap::const_iterator found = 366 WidgetToInternalsMap::const_iterator found =
338 g_widget_to_internals_map.Pointer()->find(widget); 367 g_widget_to_internals_map.Pointer()->find(widget);
339 // This can end up being accessed after the underlying widget has been 368 // This can end up being accessed after the underlying widget has been
340 // destroyed, but while the ui::Compositor is still being destroyed. 369 // destroyed, but while the ui::Compositor is still being destroyed.
341 // Return NULL in these cases. 370 // Return NULL in these cases.
342 if (found == g_widget_to_internals_map.Pointer()->end()) 371 if (found == g_widget_to_internals_map.Pointer()->end())
343 return NULL; 372 return NULL;
344 return found->second; 373 return found->second;
345 } 374 }
346 375
347 } // namespace content 376 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698