]> git.sesse.net Git - mlt/blobdiff - src/modules/opengl/filter_glsl_manager.cpp
Remove the glsl_texture freelist.
[mlt] / src / modules / opengl / filter_glsl_manager.cpp
index d941f8e9f2d6ec0710b63c0e26d53cd55e609844..cf71a211434073678a9135cc8e5721b903b0eeff 100644 (file)
@@ -24,6 +24,7 @@
 #include <movit/init.h>
 #include <movit/util.h>
 #include <movit/effect_chain.h>
+#include <movit/resource_pool.h>
 #include "mlt_movit_input.h"
 #include "mlt_flip_effect.h"
 #include <mlt++/MltEvent.h>
@@ -41,13 +42,16 @@ extern "C" {
 #include <GL/glx.h>
 #endif
 
-void deleteManager(GlslManager *p)
+void dec_ref_and_delete(GlslManager *p)
 {
-       delete p;
+       if (p->dec_ref() == 0) {
+               delete p;
+       }
 }
 
 GlslManager::GlslManager()
        : Mlt::Filter( mlt_filter_new() )
+       , resource_pool(new ResourcePool())
        , pbo(0)
        , initEvent(0)
        , closeEvent(0)
@@ -57,8 +61,7 @@ GlslManager::GlslManager()
        if ( filter ) {
                // Set the mlt_filter child in case we choose to override virtual functions.
                filter->child = this;
-               mlt_properties_set_data(mlt_global_properties(), "glslManager", this, 0,
-                       (mlt_destructor) deleteManager, NULL);
+               add_ref(mlt_global_properties());
 
                mlt_events_register( get_properties(), "init glsl", NULL );
                mlt_events_register( get_properties(), "close glsl", NULL );
@@ -84,58 +87,19 @@ GlslManager::~GlslManager()
                GLsync sync = (GLsync) syncs_to_delete.pop_front();
                glDeleteSync( sync );
        }
+       delete resource_pool;
 }
 
-GlslManager* GlslManager::get_instance()
-{
-       return (GlslManager*) mlt_properties_get_data(mlt_global_properties(), "glslManager", 0);
-}
-
-glsl_fbo GlslManager::get_fbo(int width, int height)
+void GlslManager::add_ref(mlt_properties properties)
 {
-#if defined(__DARWIN__)
-       CGLContextObj context = CGLGetCurrentContext();
-#elif defined(WIN32)
-       HGLRC context = wglGetCurrentContext();
-#else
-       GLXContext context = glXGetCurrentContext();
-#endif
-
-       lock();
-       for (int i = 0; i < fbo_list.count(); ++i) {
-               glsl_fbo fbo = (glsl_fbo) fbo_list.peek(i);
-               if (!fbo->used && (fbo->width == width) && (fbo->height == height) && (fbo->context == context)) {
-                       fbo->used = 1;
-                       unlock();
-                       return fbo;
-               }
-       }
-       unlock();
-
-       GLuint fb = 0;
-       glGenFramebuffers(1, &fb);
-       if (!fb)
-               return NULL;
-
-       glsl_fbo fbo = new glsl_fbo_s;
-       if (!fbo) {
-               glDeleteFramebuffers(1, &fb);
-               return NULL;
-       }
-       fbo->fbo = fb;
-       fbo->width = width;
-       fbo->height = height;
-       fbo->used = 1;
-       fbo->context = context;
-       lock();
-       fbo_list.push_back(fbo);
-       unlock();
-       return fbo;
+       inc_ref();
+       mlt_properties_set_data(properties, "glslManager", this, 0,
+           (mlt_destructor) dec_ref_and_delete, NULL);
 }
 
-void GlslManager::release_fbo(glsl_fbo fbo)
+GlslManager* GlslManager::get_instance()
 {
-       fbo->used = 0;
+       return (GlslManager*) mlt_properties_get_data(mlt_global_properties(), "glslManager", 0);
 }
 
 glsl_texture GlslManager::get_texture(int width, int height, GLint internal_format)
@@ -153,33 +117,22 @@ 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) {
-               glDeleteTextures(1, &tex);
                return NULL;
        }
 
+       glsl_texture gtex = new glsl_texture_s;
        if (!gtex) {
-               gtex = new glsl_texture_s;
-               if (!gtex)
-                       return NULL;
+               glDeleteTextures(1, &tex);
+               return NULL;
        }
 
        glBindTexture( GL_TEXTURE_2D, tex );
-       glTexImage2D( GL_TEXTURE_2D, 0, internal_format, width, height, 0, internal_format, GL_UNSIGNED_BYTE, NULL );
+       glTexImage2D( GL_TEXTURE_2D, 0, internal_format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
     glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
@@ -246,17 +199,11 @@ glsl_pbo GlslManager::get_pbo(int size)
 void GlslManager::cleanupContext()
 {
        lock();
-       while (fbo_list.peek_back()) {
-               glsl_fbo fbo = (glsl_fbo) fbo_list.pop_back();
-               glDeleteFramebuffers(1, &fbo->fbo);
-               delete fbo;
-       }
-       for (int i = 0; i < texture_list.count(); ++i) {
-               glsl_texture texture = (glsl_texture) texture_list.peek(i);
+       while (texture_list.peek_back()) {
+               glsl_texture texture = (glsl_texture) texture_list.peek_back();
                glDeleteTextures(1, &texture->texture);
-               texture->used = 0;
-               texture->width = 0;
-               texture->height = 0;
+               delete texture;
+               texture_list.pop_back();
        }
        if (pbo) {
                glDeleteBuffers(1, &pbo->pbo);
@@ -315,6 +262,13 @@ mlt_filter filter_glsl_manager_init( mlt_profile profile, mlt_service_type type,
 
 static void deleteChain( GlslChain* chain )
 {
+       // The Input* is owned by the EffectChain, but the MltInput* is not.
+       // Thus, we have to delete it here.
+       for (std::map<mlt_producer, MltInput*>::iterator input_it = chain->inputs.begin();
+            input_it != chain->inputs.end();
+            ++input_it) {
+               delete input_it->second;
+       }
        delete chain->effect_chain;
        delete chain;
 }
@@ -402,15 +356,15 @@ void GlslManager::set_effect_secondary_input( mlt_service service, mlt_frame fra
 
 int GlslManager::render_frame_texture(EffectChain *chain, mlt_frame frame, int width, int height, uint8_t **image)
 {
-       glsl_fbo fbo = get_fbo( width, height );
-       if (!fbo) return 1;
-       glsl_texture texture = get_texture( width, height, GL_RGBA );
+       glsl_texture texture = get_texture( width, height, GL_RGBA8 );
        if (!texture) {
-               release_fbo( fbo );
                return 1;
        }
 
-       glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
+       GLuint fbo;
+       glGenFramebuffers( 1, &fbo );
+       check_error();
+       glBindFramebuffer( GL_FRAMEBUFFER, fbo );
        check_error();
        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
        check_error();
@@ -432,14 +386,15 @@ int GlslManager::render_frame_texture(EffectChain *chain, mlt_frame frame, int w
                glClientWaitSync( prev_sync, 0, GL_TIMEOUT_IGNORED );
                glDeleteSync( prev_sync );
        }
-       chain->render_to_fbo( fbo->fbo, width, height );
+       chain->render_to_fbo( fbo, width, height );
        prev_sync = glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 );
        GLsync sync = glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 );
 
        check_error();
        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
        check_error();
-       release_fbo( fbo );
+       glDeleteFramebuffers( 1, &fbo );
+       check_error();
 
        *image = (uint8_t*) &texture->texture;
        mlt_frame_set_image( frame, *image, 0, NULL );
@@ -453,11 +408,8 @@ int GlslManager::render_frame_texture(EffectChain *chain, mlt_frame frame, int w
 
 int GlslManager::render_frame_rgba(EffectChain *chain, mlt_frame frame, int width, int height, uint8_t **image)
 {
-       glsl_fbo fbo = get_fbo( width, height );
-       if (!fbo) return 1;
-       glsl_texture texture = get_texture( width, height, GL_RGBA );
+       glsl_texture texture = get_texture( width, height, GL_RGBA8 );
        if (!texture) {
-               release_fbo( fbo );
                return 1;
        }
 
@@ -466,24 +418,25 @@ int GlslManager::render_frame_rgba(EffectChain *chain, mlt_frame frame, int widt
        int img_size = width * height * 4;
        glsl_pbo pbo = get_pbo( img_size );
        if (!pbo) {
-               release_fbo( fbo );
                release_texture(texture);
                return 1;
        }
 
        // Set the FBO
+       GLuint fbo;
+       glGenFramebuffers( 1, &fbo );
        check_error();
-       glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
+       glBindFramebuffer( GL_FRAMEBUFFER, fbo );
        check_error();
        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
        check_error();
        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
        check_error();
 
-       chain->render_to_fbo( fbo->fbo, width, height );
+       chain->render_to_fbo( fbo, width, height );
 
        // Read FBO into PBO
-       glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
+       glBindFramebuffer( GL_FRAMEBUFFER, fbo );
        check_error();
        glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, pbo->pbo );
        check_error();
@@ -519,7 +472,8 @@ int GlslManager::render_frame_rgba(EffectChain *chain, mlt_frame frame, int widt
        check_error();
        mlt_properties_set_data( MLT_FRAME_PROPERTIES(frame), "movit.convert.texture", texture, 0,
                (mlt_destructor) GlslManager::release_texture, NULL);
-       release_fbo( fbo );
+       glDeleteFramebuffers( 1, &fbo );
+       check_error();
 
        return 0;
 }