From 5b54b2b7fd01e7bc9ae42f712c4d4b7e5b5aa519 Mon Sep 17 00:00:00 2001 From: Dan Dennedy Date: Wed, 1 Jan 2014 13:08:30 -0800 Subject: [PATCH] Fix crash in release_texture() called in frame destructor. The "close glsl" event handler would destroy the texture container objects while lingering frames still held references to them. --- src/modules/opengl/filter_glsl_manager.cpp | 33 +++++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/modules/opengl/filter_glsl_manager.cpp b/src/modules/opengl/filter_glsl_manager.cpp index 28bd13fb..f1dfaa6a 100644 --- a/src/modules/opengl/filter_glsl_manager.cpp +++ b/src/modules/opengl/filter_glsl_manager.cpp @@ -70,6 +70,10 @@ GlslManager::~GlslManager() { mlt_log_debug(get_service(), "%s\n", __FUNCTION__); cleanupContext(); +// XXX If there is still a frame holding a reference to a texture after this +// destructor is called, then it will crash in release_texture(). +// while (texture_list.peek_back()) +// delete (glsl_texture) texture_list.pop_back(); delete initEvent; delete closeEvent; } @@ -141,18 +145,31 @@ glsl_texture GlslManager::get_texture(int width, int height, GLint internal_form return tex; } } + + // Recycle a glsl_texture with deleted glTexture. + glsl_texture gtex = 0; + for (int i = 0; i < texture_list.count(); ++i) { + glsl_texture tex = (glsl_texture) texture_list.peek(i); + if (!tex->used && !tex->width && !tex->height) { + gtex = tex; + break; + } + } unlock(); GLuint tex = 0; glGenTextures(1, &tex); - if (!tex) + if (!tex) { + glDeleteTextures(1, &tex); return NULL; + } - glsl_texture gtex = new glsl_texture_s; if (!gtex) { - glDeleteTextures(1, &tex); - return NULL; + gtex = new glsl_texture_s; + if (!gtex) + return NULL; } + glBindTexture( GL_TEXTURE_2D, tex ); glTexImage2D( GL_TEXTURE_2D, 0, internal_format, width, height, 0, internal_format, GL_UNSIGNED_BYTE, NULL ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); @@ -215,10 +232,12 @@ void GlslManager::cleanupContext() glDeleteFramebuffers(1, &fbo->fbo); delete fbo; } - while (texture_list.peek_back()) { - glsl_texture texture = (glsl_texture) texture_list.pop_back(); + for (int i = 0; i < texture_list.count(); ++i) { + glsl_texture texture = (glsl_texture) texture_list.peek(i); glDeleteTextures(1, &texture->texture); - delete texture; + texture->used = 0; + texture->width = 0; + texture->height = 0; } if (pbo) { glDeleteBuffers(1, &pbo->pbo); -- 2.39.5