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

Side by Side Diff: content/browser/compositor/io_surface_layer_mac.mm

Issue 558803002: Workaround to prevent crashes when destroying CGL contexts (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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
« no previous file with comments | « content/browser/compositor/io_surface_layer_mac.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/io_surface_layer_mac.h" 5 #include "content/browser/compositor/io_surface_layer_mac.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 8
9 #include <CoreFoundation/CoreFoundation.h> 9 #include <CoreFoundation/CoreFoundation.h>
10 #include <OpenGL/CGLIOSurface.h> 10 #include <OpenGL/CGLIOSurface.h>
11 #include <OpenGL/CGLRenderers.h> 11 #include <OpenGL/CGLRenderers.h>
12 #include <OpenGL/OpenGL.h> 12 #include <OpenGL/OpenGL.h>
13 13
14 #include "base/mac/mac_util.h" 14 #include "base/mac/mac_util.h"
15 #include "base/mac/sdk_forward_declarations.h" 15 #include "base/mac/sdk_forward_declarations.h"
16 #include "content/browser/gpu/gpu_data_manager_impl.h" 16 #include "content/browser/gpu/gpu_data_manager_impl.h"
17 #include "content/browser/renderer_host/render_widget_host_impl.h" 17 #include "content/browser/renderer_host/render_widget_host_impl.h"
18 #include "content/browser/renderer_host/render_widget_host_view_mac.h" 18 #include "content/browser/renderer_host/render_widget_host_view_mac.h"
19 #include "ui/base/cocoa/animation_utils.h" 19 #include "ui/base/cocoa/animation_utils.h"
20 #include "ui/gfx/size_conversions.h" 20 #include "ui/gfx/size_conversions.h"
21 #include "ui/gl/scoped_cgl.h" 21 #include "ui/gl/scoped_cgl.h"
22 #include "ui/gl/gpu_switching_manager.h" 22 #include "ui/gl/gpu_switching_manager.h"
23 23
24 // Convenience macro for checking errors in the below code. 24 // Convenience macro for checking errors in the below code.
25 #define CHECK_GL_ERROR() do { \ 25 #define CHECK_GL_ERROR() do { \
26 GLenum gl_error = glGetError(); \ 26 GLenum gl_error = glGetError(); \
27 LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error: " << gl_error; \ 27 LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error: " << gl_error; \
28 } while (0) 28 } while (0)
29 29
30 namespace {
31
30 // Helper function for logging error codes. 32 // Helper function for logging error codes.
31 namespace {
32 template<typename T> 33 template<typename T>
33 std::string to_string(T value) { 34 std::string to_string(T value) {
34 std::ostringstream stream; 35 std::ostringstream stream;
35 stream << value; 36 stream << value;
36 return stream.str(); 37 return stream.str();
37 } 38 }
39
40 // Helper function posted to destroy textures on a clean stack.
41 void DestroyTexture(
42 base::ScopedTypeRef<CGLContextObj> context,
43 base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
44 GLuint texture) {
45 // Destroy the texture before tearing down the context, and while the
46 // IOSurface is still being kept around.
47 CGLSetCurrentContext(context);
48 glDeleteTextures(1, &texture);
49 CGLSetCurrentContext(NULL);
50
51 // Release (and likely destroy) the context.
52 context.reset();
53
54 // Finally release down the IOSurface.
Ken Russell (switch to Gerrit) 2014/09/10 01:04:08 "release the IOSurface"
ccameron 2014/09/10 01:30:03 Done.
55 io_surface.reset();
56 }
38 } 57 }
39 58
40 //////////////////////////////////////////////////////////////////////////////// 59 ////////////////////////////////////////////////////////////////////////////////
41 // IOSurfaceLayer(Private) 60 // IOSurfaceLayer(Private)
42 61
43 @interface IOSurfaceLayer(Private) 62 @interface IOSurfaceLayer(Private)
63 // Reset the texture and post a task to clean it up.
64 - (void)resetTextureAndPostDestroy;
65
44 // Force a draw immediately, but only if one was requested. 66 // Force a draw immediately, but only if one was requested.
45 - (void)displayIfNeededAndAck; 67 - (void)displayIfNeededAndAck;
46 68
47 // Called when it has been a fixed interval of time and a frame has yet to be 69 // Called when it has been a fixed interval of time and a frame has yet to be
48 // drawn. 70 // drawn.
49 - (void)timerFired; 71 - (void)timerFired;
50 @end 72 @end
51 73
52 //////////////////////////////////////////////////////////////////////////////// 74 ////////////////////////////////////////////////////////////////////////////////
53 // IOSurfaceLayerHelper 75 // IOSurfaceLayerHelper
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 - (id)initWithClient:(content::IOSurfaceLayerClient*)client 128 - (id)initWithClient:(content::IOSurfaceLayerClient*)client
107 withScaleFactor:(float)scale_factor { 129 withScaleFactor:(float)scale_factor {
108 if (self = [super init]) { 130 if (self = [super init]) {
109 client_ = client; 131 client_ = client;
110 helper_.reset(new content::IOSurfaceLayerHelper(self)); 132 helper_.reset(new content::IOSurfaceLayerHelper(self));
111 needs_display_ = false; 133 needs_display_ = false;
112 has_pending_frame_ = false; 134 has_pending_frame_ = false;
113 did_not_draw_counter_ = 0; 135 did_not_draw_counter_ = 0;
114 is_pumping_frames_ = false; 136 is_pumping_frames_ = false;
115 io_surface_texture_ = 0; 137 io_surface_texture_ = 0;
116 io_surface_texture_dirty_ = false;
117 cgl_renderer_id_ = 0; 138 cgl_renderer_id_ = 0;
118 139
119 [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)]; 140 [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
120 [self setAnchorPoint:CGPointMake(0, 0)]; 141 [self setAnchorPoint:CGPointMake(0, 0)];
121 // Setting contents gravity is necessary to prevent the layer from being 142 // Setting contents gravity is necessary to prevent the layer from being
122 // scaled during dyanmic resizes (especially with devtools open). 143 // scaled during dyanmic resizes (especially with devtools open).
123 [self setContentsGravity:kCAGravityTopLeft]; 144 [self setContentsGravity:kCAGravityTopLeft];
124 if ([self respondsToSelector:(@selector(setContentsScale:))]) 145 if ([self respondsToSelector:(@selector(setContentsScale:))])
125 [self setContentsScale:scale_factor]; 146 [self setContentsScale:scale_factor];
126 } 147 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 has_pending_frame_ = true; 184 has_pending_frame_ = true;
164 needs_display_ = true; 185 needs_display_ = true;
165 helper_->ResetTimer(); 186 helper_->ResetTimer();
166 187
167 frame_pixel_size_ = pixel_size; 188 frame_pixel_size_ = pixel_size;
168 189
169 // If this is a new IOSurface, open the IOSurface and mark that the 190 // If this is a new IOSurface, open the IOSurface and mark that the
170 // GL texture needs to bind to the new surface. 191 // GL texture needs to bind to the new surface.
171 if (!io_surface_ || io_surface_id != IOSurfaceGetID(io_surface_)) { 192 if (!io_surface_ || io_surface_id != IOSurfaceGetID(io_surface_)) {
172 io_surface_.reset(IOSurfaceLookup(io_surface_id)); 193 io_surface_.reset(IOSurfaceLookup(io_surface_id));
173 io_surface_texture_dirty_ = true;
174 if (!io_surface_) { 194 if (!io_surface_) {
195 [self resetTextureAndPostDestroy];
175 content::GpuDataManagerImpl::GetInstance()->AddLogMessage( 196 content::GpuDataManagerImpl::GetInstance()->AddLogMessage(
176 logging::LOG_ERROR, 197 logging::LOG_ERROR,
177 "IOSurfaceLayer", 198 "IOSurfaceLayer",
178 "Failed to open IOSurface in gotFrameWithIOSurface"); 199 "Failed to open IOSurface in gotFrameWithIOSurface");
179 if (client_) 200 if (client_)
180 client_->IOSurfaceLayerHitError(); 201 client_->IOSurfaceLayerHitError();
181 } 202 }
182 } 203 }
183 204
184 // If reqested, draw immediately and don't bother trying to use the 205 // If reqested, draw immediately and don't bother trying to use the
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 std::string("Failed to create pixel format object with CGL error ") + 320 std::string("Failed to create pixel format object with CGL error ") +
300 to_string(static_cast<int>(cgl_error))); 321 to_string(static_cast<int>(cgl_error)));
301 return NULL; 322 return NULL;
302 } 323 }
303 return CGLRetainPixelFormat(pixel_format); 324 return CGLRetainPixelFormat(pixel_format);
304 } 325 }
305 326
306 - (void)releaseCGLContext:(CGLContextObj)glContext { 327 - (void)releaseCGLContext:(CGLContextObj)glContext {
307 // The GL context is being destroyed, so mark the resources as needing to be 328 // The GL context is being destroyed, so mark the resources as needing to be
308 // recreated. 329 // recreated.
309 io_surface_texture_ = 0; 330 [self resetTextureAndPostDestroy];
310 io_surface_texture_dirty_ = true;
311 cgl_renderer_id_ = 0;
312 [super releaseCGLContext:glContext]; 331 [super releaseCGLContext:glContext];
313 } 332 }
314 333
315 - (void)setNeedsDisplay { 334 - (void)setNeedsDisplay {
316 needs_display_ = true; 335 needs_display_ = true;
317 [super setNeedsDisplay]; 336 [super setNeedsDisplay];
318 } 337 }
319 338
320 - (void)drawInCGLContext:(CGLContextObj)glContext 339 - (void)drawInCGLContext:(CGLContextObj)glContext
321 pixelFormat:(CGLPixelFormatObj)pixelFormat 340 pixelFormat:(CGLPixelFormatObj)pixelFormat
322 forLayerTime:(CFTimeInterval)timeInterval 341 forLayerTime:(CFTimeInterval)timeInterval
323 displayTime:(const CVTimeStamp*)timeStamp { 342 displayTime:(const CVTimeStamp*)timeStamp {
324 TRACE_EVENT0("browser", "IOSurfaceLayer::drawInCGLContext"); 343 TRACE_EVENT0("browser", "IOSurfaceLayer::drawInCGLContext");
325 344
326 // Create the texture if it has not been created in this context yet. 345 // Create the texture if it has not been created in this context yet.
327 if (!io_surface_texture_) { 346 if (!io_surface_texture_) {
347 DCHECK(!io_surface_texture_io_surface_);
348 DCHECK(!io_surface_texture_context_);
328 glGenTextures(1, &io_surface_texture_); 349 glGenTextures(1, &io_surface_texture_);
329 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, io_surface_texture_); 350 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, io_surface_texture_);
330 glTexParameteri( 351 glTexParameteri(
331 GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 352 GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
332 glTexParameteri( 353 glTexParameteri(
333 GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 354 GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
334 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); 355 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
335 io_surface_texture_dirty_ = true; 356 io_surface_texture_context_.reset(CGLRetainContext(glContext));
336 } 357 }
358 DCHECK(io_surface_texture_context_ == glContext);
337 359
338 // Associate the IOSurface with this texture, if the underlying IOSurface has 360 // Associate the IOSurface with this texture, if the underlying IOSurface has
339 // been changed. 361 // been changed.
340 if (io_surface_texture_dirty_ && io_surface_) { 362 if (io_surface_ != io_surface_texture_io_surface_) {
341 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, io_surface_texture_); 363 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, io_surface_texture_);
342 CGLError cgl_error = CGLTexImageIOSurface2D( 364 CGLError cgl_error = CGLTexImageIOSurface2D(
343 glContext, 365 glContext,
344 GL_TEXTURE_RECTANGLE_ARB, 366 GL_TEXTURE_RECTANGLE_ARB,
345 GL_RGBA, 367 GL_RGBA,
346 IOSurfaceGetWidth(io_surface_), 368 IOSurfaceGetWidth(io_surface_),
347 IOSurfaceGetHeight(io_surface_), 369 IOSurfaceGetHeight(io_surface_),
348 GL_BGRA, 370 GL_BGRA,
349 GL_UNSIGNED_INT_8_8_8_8_REV, 371 GL_UNSIGNED_INT_8_8_8_8_REV,
350 io_surface_.get(), 372 io_surface_.get(),
351 0 /* plane */); 373 0 /* plane */);
352 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); 374 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
353 if (cgl_error != kCGLNoError) { 375 if (cgl_error == kCGLNoError) {
376 io_surface_texture_io_surface_ = io_surface_;
377 } else {
378 [self resetTextureAndPostDestroy];
354 content::GpuDataManagerImpl::GetInstance()->AddLogMessage( 379 content::GpuDataManagerImpl::GetInstance()->AddLogMessage(
355 logging::LOG_ERROR, 380 logging::LOG_ERROR,
356 "IOSurfaceLayer", 381 "IOSurfaceLayer",
357 std::string("CGLTexImageIOSurface2D failed with CGL error ") + 382 std::string("CGLTexImageIOSurface2D failed with CGL error ") +
358 to_string(cgl_error)); 383 to_string(cgl_error));
359 glDeleteTextures(1, &io_surface_texture_);
360 io_surface_texture_ = 0;
361 if (client_) 384 if (client_)
362 client_->IOSurfaceLayerHitError(); 385 client_->IOSurfaceLayerHitError();
363 } 386 }
364 } else if (io_surface_texture_) { 387 } else if (!io_surface_) {
365 glDeleteTextures(1, &io_surface_texture_); 388 [self resetTextureAndPostDestroy];
366 io_surface_texture_ = 0;
367 } 389 }
368 390
369 // Fill the viewport with the texture. The viewport must be smaller or equal 391 // Fill the viewport with the texture. The viewport must be smaller or equal
370 // than the texture, because it is resized as frames arrive. 392 // than the texture, because it is resized as frames arrive.
371 if (io_surface_texture_) { 393 if (io_surface_texture_) {
372 GLint viewport[4]; 394 GLint viewport[4];
373 glGetIntegerv(GL_VIEWPORT, viewport); 395 glGetIntegerv(GL_VIEWPORT, viewport);
374 gfx::Size viewport_pixel_size(viewport[2], viewport[3]); 396 gfx::Size viewport_pixel_size(viewport[2], viewport[3]);
375 DCHECK_LE( 397 DCHECK_LE(
376 viewport_pixel_size.width(), 398 viewport_pixel_size.width(),
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 467
446 needs_display_ = false; 468 needs_display_ = false;
447 [super drawInCGLContext:glContext 469 [super drawInCGLContext:glContext
448 pixelFormat:pixelFormat 470 pixelFormat:pixelFormat
449 forLayerTime:timeInterval 471 forLayerTime:timeInterval
450 displayTime:timeStamp]; 472 displayTime:timeStamp];
451 473
452 [self ackPendingFrame]; 474 [self ackPendingFrame];
453 } 475 }
454 476
477 - (void)resetTextureAndPostDestroy {
478 if (!io_surface_texture_) {
479 DCHECK(!io_surface_texture_context_);
480 DCHECK(!io_surface_texture_io_surface_);
481 return;
482 }
483
484 // Post a task to clean up the texture on a clean stack.
485 if (io_surface_texture_context_)
486 CGLRetainContext(io_surface_texture_context_);
487 if (io_surface_texture_io_surface_)
488 CFRetain(io_surface_texture_io_surface_);
Ken Russell (switch to Gerrit) 2014/09/10 01:04:08 I'm dubious that these calls to CGLRetainContext a
ccameron 2014/09/10 01:30:02 They're completely and embarrassingly wrong. Fixed
489 base::MessageLoop::current()->PostTask(
490 FROM_HERE,
491 base::Bind(&DestroyTexture,
492 io_surface_texture_context_,
493 io_surface_texture_io_surface_,
494 io_surface_texture_));
495
496 // Reset the texture state.
497 io_surface_texture_ = 0;
498 io_surface_texture_context_.reset();
499 io_surface_texture_io_surface_.reset();
500 cgl_renderer_id_ = 0;
501 }
502
455 @end 503 @end
OLDNEW
« no previous file with comments | « content/browser/compositor/io_surface_layer_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698