Fix for thread-unsafe OpenGL implementations (OS X...)
authorEric Petit <titer@videolan.org>
Fri, 25 Mar 2005 12:02:14 +0000 (12:02 +0000)
committerEric Petit <titer@videolan.org>
Fri, 25 Mar 2005 12:02:14 +0000 (12:02 +0000)
include/video_output.h
modules/gui/macosx/voutgl.m
modules/video_output/opengl.c

index 58efcf0..ca7bc42 100644 (file)
@@ -103,6 +103,8 @@ struct vout_thread_t
     void      ( *pf_render )     ( vout_thread_t *, picture_t * );
     void      ( *pf_display )    ( vout_thread_t *, picture_t * );
     void      ( *pf_swap )       ( vout_thread_t * );         /* OpenGL only */
+    int       ( *pf_lock )       ( vout_thread_t * );         /* OpenGL only */
+    void      ( *pf_unlock )     ( vout_thread_t * );         /* OpenGL only */
     int       ( *pf_control )    ( vout_thread_t *, int, va_list );
     /**@}*/
 
index a7be323..365c3cd 100644 (file)
@@ -61,6 +61,7 @@ struct vout_sys_t
     vlc_bool_t          b_saved_frame;
     NSRect              s_frame;
     vlc_bool_t          b_got_frame;
+    vlc_mutex_t         lock;
 };
 
 /*****************************************************************************
@@ -72,6 +73,8 @@ static void End    ( vout_thread_t * p_vout );
 static int  Manage ( vout_thread_t * p_vout );
 static int  Control( vout_thread_t *, int, va_list );
 static void Swap   ( vout_thread_t * p_vout );
+static int  Lock   ( vout_thread_t * p_vout );
+static void Unlock ( vout_thread_t * p_vout );
 
 int E_(OpenVideoGL)  ( vlc_object_t * p_this )
 {
@@ -94,6 +97,7 @@ int E_(OpenVideoGL)  ( vlc_object_t * p_this )
     memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
 
     p_vout->p_sys->o_pool = [[NSAutoreleasePool alloc] init];
+    vlc_mutex_init( p_vout, &p_vout->p_sys->lock );
 
     /* Spawn window */
     p_vout->p_sys->b_got_frame = VLC_FALSE;
@@ -117,6 +121,8 @@ int E_(OpenVideoGL)  ( vlc_object_t * p_this )
     p_vout->pf_manage = Manage;
     p_vout->pf_control= Control;
     p_vout->pf_swap   = Swap;
+    p_vout->pf_lock   = Lock;
+    p_vout->pf_unlock = Unlock;
 
     return VLC_SUCCESS;
 }
@@ -136,6 +142,7 @@ void E_(CloseVideoGL) ( vlc_object_t * p_this )
     [p_vout->p_sys->o_window close];
 
     /* Clean up */
+    vlc_mutex_destroy( &p_vout->p_sys->lock );
     [o_pool release];
     free( p_vout->p_sys );
 }
@@ -220,11 +227,18 @@ static void Swap( vout_thread_t * p_vout )
 {
     p_vout->p_sys->b_got_frame = VLC_TRUE;
     [[p_vout->p_sys->o_glview openGLContext] makeCurrentContext];
-    if( [p_vout->p_sys->o_glview lockFocusIfCanDraw] )
-    {
-        glFlush();
-        [p_vout->p_sys->o_glview unlockFocus];
-    }
+    glFlush();
+}
+
+static int Lock( vout_thread_t * p_vout )
+{
+    vlc_mutex_lock( &p_vout->p_sys->lock );
+    return 0;
+}
+
+static void Unlock( vout_thread_t * p_vout )
+{
+    vlc_mutex_unlock( &p_vout->p_sys->lock );
 }
 
 /*****************************************************************************
@@ -296,8 +310,11 @@ static void Swap( vout_thread_t * p_vout )
         x = bounds.size.width;
         y = bounds.size.width * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
     }
+
+    Lock( p_vout );
     glViewport( ( bounds.size.width - x ) / 2,
                 ( bounds.size.height - y ) / 2, x, y );
+    Unlock( p_vout );
 
     if( p_vout->p_sys->b_got_frame )
     {
@@ -311,14 +328,18 @@ static void Swap( vout_thread_t * p_vout )
     }
     else
     {
+        Lock( p_vout );
         glClear( GL_COLOR_BUFFER_BIT );
+        Unlock( p_vout );
     }
 }
 
 - (void) drawRect: (NSRect) rect
 {
     [[self openGLContext] makeCurrentContext];
+    Lock( p_vout );
     glFlush();
+    Unlock( p_vout );
 }
 
 @end
index 0200590..000bad8 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Authors: Cyril Deguet <asmax@videolan.org>
  *          Gildas Bazin <gbazin@videolan.org>
+ *          Eric Petit <titer@m0k.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -310,6 +311,13 @@ static int Init( vout_thread_t *p_vout )
 
     I_OUTPUTPICTURES = 1;
 
+    if( p_sys->p_vout->pf_lock &&
+        p_sys->p_vout->pf_lock( p_sys->p_vout ) )
+    {
+        msg_Warn( p_vout, "could not lock OpenGL provider" );
+        return 0;
+    }
+
     InitTextures( p_vout );
 
     glDisable(GL_BLEND);
@@ -359,6 +367,11 @@ static int Init( vout_thread_t *p_vout )
         glTranslatef( 0.0, 0.0, - 5.0 );
     }
 
+    if( p_sys->p_vout->pf_unlock )
+    {
+        p_sys->p_vout->pf_unlock( p_sys->p_vout );
+    }
+
     return 0;
 }
 
@@ -367,8 +380,22 @@ static int Init( vout_thread_t *p_vout )
  *****************************************************************************/
 static void End( vout_thread_t *p_vout )
 {
+    vout_sys_t *p_sys = p_vout->p_sys;
+
+    if( p_sys->p_vout->pf_lock &&
+        p_sys->p_vout->pf_lock( p_sys->p_vout ) )
+    {
+        msg_Warn( p_vout, "could not lock OpenGL provider" );
+        return;
+    }
+
     glFinish();
     glFlush();
+
+    if( p_sys->p_vout->pf_unlock )
+    {
+        p_sys->p_vout->pf_unlock( p_sys->p_vout );
+    }
 }
 
 /*****************************************************************************
@@ -410,6 +437,13 @@ static int Manage( vout_thread_t *p_vout )
     p_vout->i_changes = p_sys->p_vout->i_changes;
 
 #ifdef SYS_DARWIN
+    if( p_sys->p_vout->pf_lock &&
+        p_sys->p_vout->pf_lock( p_sys->p_vout ) )
+    {
+        msg_Warn( p_vout, "could not lock OpenGL provider" );
+        return i_ret;
+    }
+
     /* On OS X, we create the window and the GL view when entering
        fullscreen - the textures have to be inited again */
     if( i_fullscreen_change )
@@ -441,6 +475,11 @@ static int Manage( vout_thread_t *p_vout )
             glTranslatef( 0.0, 0.0, - 5.0 );
         }
     }
+
+    if( p_sys->p_vout->pf_unlock )
+    {
+        p_sys->p_vout->pf_unlock( p_sys->p_vout );
+    }
 #endif
 
     return i_ret;
@@ -470,10 +509,18 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
        OS X, we first render, then reload the texture to be used next
        time. */
 
+    if( p_sys->p_vout->pf_lock &&
+        p_sys->p_vout->pf_lock( p_sys->p_vout ) )
+    {
+        msg_Warn( p_vout, "could not lock OpenGL provider" );
+        return;
+    }
+
 #ifdef SYS_DARWIN
     int i_new_index;
     i_new_index = ( p_sys->i_index + 1 ) & 1;
 
+
     /* Update the texture */
     glBindTexture( VLCGL_TARGET, p_sys->p_textures[i_new_index] );
     glTexSubImage2D( VLCGL_TARGET, 0, 0, 0, p_sys->i_tex_width,
@@ -493,6 +540,11 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
                      p_vout->render.i_width, p_vout->render.i_height,
                      VLCGL_RGB_FORMAT, VLCGL_RGB_TYPE, p_sys->pp_buffer[0] );
 #endif
+
+    if( p_sys->p_vout->pf_unlock )
+    {
+        p_sys->p_vout->pf_unlock( p_sys->p_vout );
+    }
 }
 
 /*****************************************************************************
@@ -517,6 +569,13 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
        OpenGL providers can call pf_display to force redraw. Currently,
        the OS X provider uses it to get a smooth window resizing */
 
+    if( p_sys->p_vout->pf_lock &&
+        p_sys->p_vout->pf_lock( p_sys->p_vout ) )
+    {
+        msg_Warn( p_vout, "could not lock OpenGL provider" );
+        return;
+    }
+
     glClear( GL_COLOR_BUFFER_BIT );
 
     if( p_sys->i_effect == OPENGL_EFFECT_NONE )
@@ -577,6 +636,11 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
     glDisable( VLCGL_TARGET );
 
     p_sys->p_vout->pf_swap( p_sys->p_vout );
+
+    if( p_sys->p_vout->pf_unlock )
+    {
+        p_sys->p_vout->pf_unlock( p_sys->p_vout );
+    }
 }
 
 int GetAlignedSize( int i_size )