]> git.sesse.net Git - mlt/blobdiff - src/modules/opengl/filter_glsl_manager.cpp
Add back automatic cleanup of OpenGL fences.
[mlt] / src / modules / opengl / filter_glsl_manager.cpp
index f1dfaa6a469f4183185381d587f50aedca92ae14..9cb0855cb5da0ea530df2e7c02cbdfbfbff14290 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <stdlib.h>
 #include <string>
-#include "glsl_manager.h"
+#include "filter_glsl_manager.h"
 #include <movit/init.h>
 #include <movit/util.h>
 #include <movit/effect_chain.h>
@@ -51,6 +51,7 @@ GlslManager::GlslManager()
        , pbo(0)
        , initEvent(0)
        , closeEvent(0)
+       , prev_sync(NULL)
 {
        mlt_filter filter = get_filter();
        if ( filter ) {
@@ -76,6 +77,13 @@ GlslManager::~GlslManager()
 //             delete (glsl_texture) texture_list.pop_back();
        delete initEvent;
        delete closeEvent;
+       if (prev_sync != NULL) {
+               glDeleteSync( prev_sync );
+       }
+       while (syncs_to_delete.count() > 0) {
+               GLsync sync = (GLsync) syncs_to_delete.pop_front();
+               glDeleteSync( sync );
+       }
 }
 
 GlslManager* GlslManager::get_instance()
@@ -194,6 +202,17 @@ void GlslManager::release_texture(glsl_texture texture)
        texture->used = 0;
 }
 
+void GlslManager::delete_sync(GLsync sync)
+{
+       // We do not know which thread we are called from, and we can only
+       // delete this if we are in one with a valid OpenGL context.
+       // Thus, store it for later deletion in render_frame_texture().
+       GlslManager* g = GlslManager::get_instance();
+       g->lock();
+       g->syncs_to_delete.push_back(sync);
+       g->unlock();
+}
+
 glsl_pbo GlslManager::get_pbo(int size)
 {
        lock();
@@ -349,30 +368,30 @@ void GlslManager::reset_finalized( mlt_service service )
        mlt_properties_set_int( MLT_SERVICE_PROPERTIES(service), "_movit finalized", 0 );
 }
 
-Effect* GlslManager::get_effect( mlt_filter filter, mlt_frame frame )
+Effect* GlslManager::get_effect( mlt_service service, mlt_frame frame )
 {
        Mlt::Producer producer( mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) ) );
-       char *unique_id = mlt_properties_get( MLT_FILTER_PROPERTIES(filter), "_unique_id" );
+       char *unique_id = mlt_properties_get( MLT_SERVICE_PROPERTIES(service), "_unique_id" );
        return (Effect*) GlslManager::get_instance()->effect_list( producer ).get_data( unique_id );
 }
 
-Effect* GlslManager::add_effect( mlt_filter filter, mlt_frame frame, Effect* effect )
+Effect* GlslManager::add_effect( mlt_service service, mlt_frame frame, Effect* effect )
 {
        Mlt::Producer producer( mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) ) );
        EffectChain* chain = (EffectChain*) producer.get_data( "movit chain" );
        chain->add_effect( effect );
-       char *unique_id = mlt_properties_get( MLT_FILTER_PROPERTIES(filter), "_unique_id" );
+       char *unique_id = mlt_properties_get( MLT_SERVICE_PROPERTIES(service), "_unique_id" );
        GlslManager::get_instance()->effect_list( producer ).set( unique_id, effect, 0 );
        return effect;
 }
 
-Effect* GlslManager::add_effect( mlt_filter filter, mlt_frame frame, Effect* effect, Effect* input_b )
+Effect* GlslManager::add_effect( mlt_service service, mlt_frame frame, Effect* effect, Effect* input_b )
 {
        Mlt::Producer producer( mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) ) );
        EffectChain* chain = (EffectChain*) producer.get_data( "movit chain" );
        chain->add_effect( effect, chain->last_added_effect(),
                input_b? input_b : chain->last_added_effect() );
-       char *unique_id = mlt_properties_get( MLT_FILTER_PROPERTIES(filter), "_unique_id" );
+       char *unique_id = mlt_properties_get( MLT_SERVICE_PROPERTIES(service), "_unique_id" );
        GlslManager::get_instance()->effect_list( producer ).set( unique_id, effect, 0 );
        return effect;
 }
@@ -408,9 +427,25 @@ int GlslManager::render_frame_texture(mlt_service service, mlt_frame frame, int
        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
        check_error();
 
+       lock();
+       while (syncs_to_delete.count() > 0) {
+               GLsync sync = (GLsync) syncs_to_delete.pop_front();
+               glDeleteSync( sync );
+       }
+       unlock();
+
+       // Make sure we never have more than one frame pending at any time.
+       // This ensures we do not swamp the GPU with so much work
+       // that we cannot actually display the frames we generate.
+       if (prev_sync != NULL) {
+               glFlush();
+               glClientWaitSync( prev_sync, 0, GL_TIMEOUT_IGNORED );
+               glDeleteSync( prev_sync );
+       }
        render_fbo( service, chain, fbo->fbo, width, height );
+       prev_sync = glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 );
+       GLsync sync = glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 );
 
-       glFinish();
        check_error();
        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
        check_error();
@@ -420,6 +455,8 @@ int GlslManager::render_frame_texture(mlt_service service, mlt_frame frame, int
        mlt_frame_set_image( frame, *image, 0, NULL );
        mlt_properties_set_data( MLT_FRAME_PROPERTIES(frame), "movit.convert.texture", texture, 0,
                (mlt_destructor) GlslManager::release_texture, NULL );
+       mlt_properties_set_data( MLT_FRAME_PROPERTIES(frame), "movit.convert.fence", sync, 0,
+               (mlt_destructor) GlslManager::delete_sync, NULL );
 
        return 0;
 }