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

Unified 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: Plug leaks 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/compositor/io_surface_layer_mac.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/compositor/io_surface_layer_mac.mm
diff --git a/content/browser/compositor/io_surface_layer_mac.mm b/content/browser/compositor/io_surface_layer_mac.mm
index c0ea9e156593cb988f1c42796385db1701760bb4..cc9ee56e5f442a678d11924bb413f2196fffdab1 100644
--- a/content/browser/compositor/io_surface_layer_mac.mm
+++ b/content/browser/compositor/io_surface_layer_mac.mm
@@ -27,20 +27,42 @@
LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error: " << gl_error; \
} while (0)
-// Helper function for logging error codes.
namespace {
+
+// Helper function for logging error codes.
template<typename T>
std::string to_string(T value) {
std::ostringstream stream;
stream << value;
return stream.str();
}
+
+// Helper function posted to destroy textures on a clean stack.
+void DestroyTexture(
+ base::ScopedTypeRef<CGLContextObj> context,
+ base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
+ GLuint texture) {
+ // Destroy the texture before tearing down the context, and while the
+ // IOSurface is still being kept around.
+ CGLSetCurrentContext(context);
+ glDeleteTextures(1, &texture);
+ CGLSetCurrentContext(NULL);
+
+ // Release (and likely destroy) the context.
+ context.reset();
+
+ // Finally release the IOSurface.
+ io_surface.reset();
+}
}
////////////////////////////////////////////////////////////////////////////////
// IOSurfaceLayer(Private)
@interface IOSurfaceLayer(Private)
+// Reset the texture and post a task to clean it up.
+- (void)resetTextureAndPostDestroy;
+
// Force a draw immediately, but only if one was requested.
- (void)displayIfNeededAndAck;
@@ -113,7 +135,6 @@ void IOSurfaceLayerHelper::TimerFired() {
did_not_draw_counter_ = 0;
is_pumping_frames_ = false;
io_surface_texture_ = 0;
- io_surface_texture_dirty_ = false;
cgl_renderer_id_ = 0;
[self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
@@ -170,8 +191,8 @@ void IOSurfaceLayerHelper::TimerFired() {
// GL texture needs to bind to the new surface.
if (!io_surface_ || io_surface_id != IOSurfaceGetID(io_surface_)) {
io_surface_.reset(IOSurfaceLookup(io_surface_id));
- io_surface_texture_dirty_ = true;
if (!io_surface_) {
+ [self resetTextureAndPostDestroy];
content::GpuDataManagerImpl::GetInstance()->AddLogMessage(
logging::LOG_ERROR,
"IOSurfaceLayer",
@@ -306,9 +327,7 @@ void IOSurfaceLayerHelper::TimerFired() {
- (void)releaseCGLContext:(CGLContextObj)glContext {
// The GL context is being destroyed, so mark the resources as needing to be
// recreated.
- io_surface_texture_ = 0;
- io_surface_texture_dirty_ = true;
- cgl_renderer_id_ = 0;
+ [self resetTextureAndPostDestroy];
[super releaseCGLContext:glContext];
}
@@ -325,6 +344,8 @@ void IOSurfaceLayerHelper::TimerFired() {
// Create the texture if it has not been created in this context yet.
if (!io_surface_texture_) {
+ DCHECK(!io_surface_texture_io_surface_);
+ DCHECK(!io_surface_texture_context_);
glGenTextures(1, &io_surface_texture_);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, io_surface_texture_);
glTexParameteri(
@@ -332,12 +353,13 @@ void IOSurfaceLayerHelper::TimerFired() {
glTexParameteri(
GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
- io_surface_texture_dirty_ = true;
+ io_surface_texture_context_.reset(CGLRetainContext(glContext));
Ken Russell (switch to Gerrit) 2014/09/10 04:06:38 Sorry I didn't notice this the first time through,
ccameron 2014/09/10 07:53:26 This one is correct -- there is no implicit retain
Ken Russell (switch to Gerrit) 2014/09/10 22:24:52 OK, sorry about my confusion, but it looks like yo
}
+ DCHECK(io_surface_texture_context_ == glContext);
// Associate the IOSurface with this texture, if the underlying IOSurface has
// been changed.
- if (io_surface_texture_dirty_ && io_surface_) {
+ if (io_surface_ != io_surface_texture_io_surface_) {
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, io_surface_texture_);
CGLError cgl_error = CGLTexImageIOSurface2D(
glContext,
@@ -350,20 +372,20 @@ void IOSurfaceLayerHelper::TimerFired() {
io_surface_.get(),
0 /* plane */);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
- if (cgl_error != kCGLNoError) {
+ if (cgl_error == kCGLNoError) {
+ io_surface_texture_io_surface_ = io_surface_;
+ } else {
+ [self resetTextureAndPostDestroy];
content::GpuDataManagerImpl::GetInstance()->AddLogMessage(
logging::LOG_ERROR,
"IOSurfaceLayer",
std::string("CGLTexImageIOSurface2D failed with CGL error ") +
to_string(cgl_error));
- glDeleteTextures(1, &io_surface_texture_);
- io_surface_texture_ = 0;
if (client_)
client_->IOSurfaceLayerHitError();
}
- } else if (io_surface_texture_) {
- glDeleteTextures(1, &io_surface_texture_);
- io_surface_texture_ = 0;
+ } else if (!io_surface_) {
+ [self resetTextureAndPostDestroy];
}
// Fill the viewport with the texture. The viewport must be smaller or equal
@@ -452,4 +474,26 @@ void IOSurfaceLayerHelper::TimerFired() {
[self ackPendingFrame];
}
+- (void)resetTextureAndPostDestroy {
+ if (!io_surface_texture_) {
+ DCHECK(!io_surface_texture_context_);
+ DCHECK(!io_surface_texture_io_surface_);
+ return;
+ }
+
+ // Post a task to clean up the texture on a clean stack.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&DestroyTexture,
+ io_surface_texture_context_,
+ io_surface_texture_io_surface_,
+ io_surface_texture_));
+
+ // Reset the texture state.
+ io_surface_texture_ = 0;
+ io_surface_texture_context_.reset();
+ io_surface_texture_io_surface_.reset();
+ cgl_renderer_id_ = 0;
+}
+
@end
« 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