Commit bc80bfd7 authored by Pierre d'Herbemont's avatar Pierre d'Herbemont

video_output/opengllayer.m: Proper three-buffering, that should work if texture was copied.

parent 7af65b11
...@@ -110,13 +110,15 @@ struct vout_sys_t ...@@ -110,13 +110,15 @@ struct vout_sys_t
{ {
vout_thread_t * p_vout; vout_thread_t * p_vout;
uint8_t *pp_buffer[2]; /* one last rendered, one to be rendered */ uint8_t *pp_buffer[3]; /* one last rendered, one to be rendered */
int i_index; int i_rendering_index;
int i_rendered_index;
int i_on_screen_index;
vlc_bool_t b_frame_available; vlc_bool_t b_frame_available;
int i_tex_width; int i_tex_width;
int i_tex_height; int i_tex_height;
GLuint p_textures[2]; GLuint p_textures[3];
NSAutoreleasePool *autorealease_pool; NSAutoreleasePool *autorealease_pool;
VLCVoutLayer * o_layer; VLCVoutLayer * o_layer;
...@@ -146,7 +148,6 @@ static int CreateVout( vlc_object_t *p_this ) ...@@ -146,7 +148,6 @@ static int CreateVout( vlc_object_t *p_this )
msg_Dbg( p_vout, "Texture size: %dx%d", p_sys->i_tex_width, msg_Dbg( p_vout, "Texture size: %dx%d", p_sys->i_tex_width,
p_sys->i_tex_height ); p_sys->i_tex_height );
p_vout->pf_init = Init; p_vout->pf_init = Init;
p_vout->pf_end = End; p_vout->pf_end = End;
p_vout->pf_manage = Manage; p_vout->pf_manage = Manage;
...@@ -193,7 +194,7 @@ static int Init( vout_thread_t *p_vout ) ...@@ -193,7 +194,7 @@ static int Init( vout_thread_t *p_vout )
/* We know the chroma, allocate two buffer which will be used /* We know the chroma, allocate two buffer which will be used
* directly by the decoder */ * directly by the decoder */
int i; int i;
for( i = 0; i < 2; i++ ) for( i = 0; i < 3; i++ )
{ {
p_sys->pp_buffer[i] = p_sys->pp_buffer[i] =
malloc( p_sys->i_tex_width * p_sys->i_tex_height * i_pixel_pitch ); malloc( p_sys->i_tex_width * p_sys->i_tex_height * i_pixel_pitch );
...@@ -204,10 +205,12 @@ static int Init( vout_thread_t *p_vout ) ...@@ -204,10 +205,12 @@ static int Init( vout_thread_t *p_vout )
} }
} }
p_sys->b_frame_available = VLC_FALSE; p_sys->b_frame_available = VLC_FALSE;
p_sys->i_index = 0; p_sys->i_on_screen_index = 0;
p_sys->i_rendered_index = 1;
p_sys->i_rendering_index = 2;
p_vout->p_picture[0].i_planes = 1; p_vout->p_picture[0].i_planes = 1;
p_vout->p_picture[0].p->p_pixels = p_sys->pp_buffer[0]; p_vout->p_picture[0].p->p_pixels = p_sys->pp_buffer[p_sys->i_rendering_index];
p_vout->p_picture[0].p->i_lines = p_vout->output.i_height; p_vout->p_picture[0].p->i_lines = p_vout->output.i_height;
p_vout->p_picture[0].p->i_visible_lines = p_vout->output.i_height; p_vout->p_picture[0].p->i_visible_lines = p_vout->output.i_height;
p_vout->p_picture[0].p->i_pixel_pitch = i_pixel_pitch; p_vout->p_picture[0].p->i_pixel_pitch = i_pixel_pitch;
...@@ -255,6 +258,7 @@ static void End( vout_thread_t *p_vout ) ...@@ -255,6 +258,7 @@ static void End( vout_thread_t *p_vout )
/* Free the texture buffer*/ /* Free the texture buffer*/
free( p_sys->pp_buffer[0] ); free( p_sys->pp_buffer[0] );
free( p_sys->pp_buffer[1] ); free( p_sys->pp_buffer[1] );
if( p_sys->pp_buffer[2] ) free( p_sys->pp_buffer[2] );
} }
/***************************************************************************** /*****************************************************************************
...@@ -277,6 +281,8 @@ static void DestroyVout( vlc_object_t *p_this ) ...@@ -277,6 +281,8 @@ static void DestroyVout( vlc_object_t *p_this )
*****************************************************************************/ *****************************************************************************/
static int Manage( vout_thread_t *p_vout ) static int Manage( vout_thread_t *p_vout )
{ {
vout_sys_t *p_sys = p_vout->p_sys;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -287,15 +293,13 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -287,15 +293,13 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
{ {
vout_sys_t *p_sys = p_vout->p_sys; vout_sys_t *p_sys = p_vout->p_sys;
/* Switch buffers */ /* Make sure we never draw to the currently on screen buffer */
int p_new_index; assert(p_sys->i_rendering_index != p_sys->i_on_screen_index );
@synchronized(p_sys->o_layer)
{
p_new_index = (p_sys->i_index + 1) & 1;
}
/* Give a buffer where the image will be rendered */ /* Give a buffer where the image will be rendered */
p_pic->p->p_pixels = p_sys->pp_buffer[p_new_index]; p_pic->p->p_pixels = p_sys->pp_buffer[p_sys->i_rendering_index];
} }
/***************************************************************************** /*****************************************************************************
...@@ -305,13 +309,16 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -305,13 +309,16 @@ static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
{ {
vout_sys_t *p_sys = p_vout->p_sys; vout_sys_t *p_sys = p_vout->p_sys;
/* The frame is ready, give its number so the o_layer can display it */ /* Swap the buffer */
@synchronized(p_sys->o_layer) @synchronized(p_sys->o_layer)
{ {
p_sys->i_index = (p_sys->i_index + 1) & 1; /* Indicate the layer should use that index */ int temp = p_sys->i_rendered_index;
p_sys->i_rendered_index = p_sys->i_rendering_index;
p_sys->i_rendering_index = temp;
p_sys->b_frame_available = VLC_TRUE;
assert(p_sys->i_rendering_index != p_sys->i_on_screen_index );
} }
p_sys->b_frame_available = VLC_TRUE;
} }
/***************************************************************************** /*****************************************************************************
...@@ -342,10 +349,10 @@ static int InitTextures( vout_thread_t *p_vout ) ...@@ -342,10 +349,10 @@ static int InitTextures( vout_thread_t *p_vout )
vout_sys_t *p_sys = p_vout->p_sys; vout_sys_t *p_sys = p_vout->p_sys;
int i_index; int i_index;
glDeleteTextures( 2, p_sys->p_textures ); glDeleteTextures( 3, p_sys->p_textures );
glGenTextures( 2, p_sys->p_textures ); glGenTextures( 3, p_sys->p_textures );
for( i_index = 0; i_index < 2; i_index++ ) for( i_index = 0; i_index < 3; i_index++ )
{ {
glBindTexture( VLCGL_TARGET, p_sys->p_textures[i_index] ); glBindTexture( VLCGL_TARGET, p_sys->p_textures[i_index] );
...@@ -360,7 +367,9 @@ static int InitTextures( vout_thread_t *p_vout ) ...@@ -360,7 +367,9 @@ static int InitTextures( vout_thread_t *p_vout )
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
#ifdef __DISABLED_FOR_NOW__ /* Note: It seems that we can't bypass those, and even
* disabled they are used. They are the cause of the flickering */
/* Tell the driver not to make a copy of the texture but to use /* Tell the driver not to make a copy of the texture but to use
our buffer */ our buffer */
glEnable( GL_UNPACK_CLIENT_STORAGE_APPLE ); glEnable( GL_UNPACK_CLIENT_STORAGE_APPLE );
...@@ -369,10 +378,9 @@ static int InitTextures( vout_thread_t *p_vout ) ...@@ -369,10 +378,9 @@ static int InitTextures( vout_thread_t *p_vout )
/* Use AGP texturing */ /* Use AGP texturing */
glTexParameteri( VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE, glTexParameteri( VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE,
GL_STORAGE_SHARED_APPLE ); GL_STORAGE_SHARED_APPLE );
#endif
/* Call glTexImage2D only once, and use glTexSubImage2D later */ /* Call glTexImage2D only once, and use glTexSubImage2D later */
glTexImage2D( VLCGL_TARGET, 0, 3, p_sys->i_tex_width, glTexImage2D( VLCGL_TARGET, 0, 4, p_sys->i_tex_width,
p_sys->i_tex_height, 0, VLCGL_FORMAT, VLCGL_TYPE, p_sys->i_tex_height, 0, VLCGL_FORMAT, VLCGL_TYPE,
p_sys->pp_buffer[i_index] ); p_sys->pp_buffer[i_index] );
} }
...@@ -397,18 +405,13 @@ static int InitTextures( vout_thread_t *p_vout ) ...@@ -397,18 +405,13 @@ static int InitTextures( vout_thread_t *p_vout )
[p_vout->p_sys->o_cocoa_container addVoutLayer:p_vout->p_sys->o_layer]; [p_vout->p_sys->o_cocoa_container addVoutLayer:p_vout->p_sys->o_layer];
} }
- (void)setVout:(vout_thread_t*)_p_vout
{
p_vout = _p_vout;
}
+ (id)layerWithVout:(vout_thread_t*)_p_vout + (id)layerWithVout:(vout_thread_t*)_p_vout
{ {
VLCVoutLayer* me = [super layer]; VLCVoutLayer* me = [[[self alloc] init] autorelease];
if( me ) if( me )
{ {
me->p_vout = _p_vout;
me.asynchronous = YES; me.asynchronous = YES;
[me setVout: _p_vout];
me.bounds = CGRectMake( 0.0, 0.0, me.bounds = CGRectMake( 0.0, 0.0,
(float)_p_vout->fmt_in.i_visible_width * _p_vout->fmt_in.i_sar_num, (float)_p_vout->fmt_in.i_visible_width * _p_vout->fmt_in.i_sar_num,
(float)_p_vout->fmt_in.i_visible_height * _p_vout->fmt_in.i_sar_den ); (float)_p_vout->fmt_in.i_visible_height * _p_vout->fmt_in.i_sar_den );
...@@ -437,14 +440,29 @@ static int InitTextures( vout_thread_t *p_vout ) ...@@ -437,14 +440,29 @@ static int InitTextures( vout_thread_t *p_vout )
f_height = (float)p_vout->fmt_out.i_y_offset + f_height = (float)p_vout->fmt_out.i_y_offset +
(float)p_vout->fmt_out.i_visible_height; (float)p_vout->fmt_out.i_visible_height;
assert(p_vout->p_sys->i_rendering_index != p_vout->p_sys->i_on_screen_index );
@synchronized(self) @synchronized(self)
{ {
glBindTexture( VLCGL_TARGET, p_vout->p_sys->p_textures[p_vout->p_sys->i_index] ); /* Swap the buffers */
if( p_vout->p_sys->b_frame_available )
{
int temp;
temp = p_vout->p_sys->i_on_screen_index;
p_vout->p_sys->i_on_screen_index = p_vout->p_sys->i_rendered_index;
p_vout->p_sys->i_rendered_index = temp;
p_vout->p_sys->b_frame_available = VLC_FALSE;
}
glBindTexture( VLCGL_TARGET, p_vout->p_sys->p_textures[p_vout->p_sys->i_on_screen_index] );
glTexSubImage2D( VLCGL_TARGET, 0, 0, 0, glTexSubImage2D( VLCGL_TARGET, 0, 0, 0,
p_vout->fmt_out.i_width, p_vout->fmt_out.i_width,
p_vout->fmt_out.i_height, p_vout->fmt_out.i_height,
VLCGL_FORMAT, VLCGL_TYPE, p_vout->p_sys->pp_buffer[p_vout->p_sys->i_index] ); VLCGL_FORMAT, VLCGL_TYPE, p_vout->p_sys->pp_buffer[p_vout->p_sys->i_on_screen_index] );
/* Make sure the that there is no old reference of the pointer old texture kept around */
glFinishObjectAPPLE(GL_TEXTURE_RECTANGLE_EXT, p_vout->p_sys->p_textures[p_vout->p_sys->i_on_screen_index]);
glClear( GL_COLOR_BUFFER_BIT ); glClear( GL_COLOR_BUFFER_BIT );
...@@ -459,34 +477,13 @@ static int InitTextures( vout_thread_t *p_vout ) ...@@ -459,34 +477,13 @@ static int InitTextures( vout_thread_t *p_vout )
glDisable( VLCGL_TARGET ); glDisable( VLCGL_TARGET );
glFlush(); glFlush();
}
CGLUnlockContext( glContext ); CGLUnlockContext( glContext );
p_vout->p_sys->b_frame_available = VLC_FALSE; p_vout->p_sys->b_frame_available = VLC_FALSE;
}
} }
// - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
// {
// GLuint attribs[] =
// {
// NSOpenGLPFANoRecovery,
// NSOpenGLPFAWindow,
// NSOpenGLPFAAccelerated,
// NSOpenGLPFADoubleBuffer,
// NSOpenGLPFAColorSize, 24,
// NSOpenGLPFAAlphaSize, 8,
// NSOpenGLPFADepthSize, 24,
// NSOpenGLPFAStencilSize, 8,
// NSOpenGLPFAAccumSize, 0,
// 0
// };
//
// NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: (NSOpenGLPixelFormatAttribute*) attribs];
//
// return [fmt CGLPixelFormatObj];
// }
- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
{ {
CGLContextObj context = [super copyCGLContextForPixelFormat:pixelFormat]; CGLContextObj context = [super copyCGLContextForPixelFormat:pixelFormat];
...@@ -513,6 +510,7 @@ static int InitTextures( vout_thread_t *p_vout ) ...@@ -513,6 +510,7 @@ static int InitTextures( vout_thread_t *p_vout )
glClear( GL_COLOR_BUFFER_BIT ); glClear( GL_COLOR_BUFFER_BIT );
CGLUnlockContext( context ); CGLUnlockContext( context );
return context; return context;
} }
...@@ -521,7 +519,7 @@ static int InitTextures( vout_thread_t *p_vout ) ...@@ -521,7 +519,7 @@ static int InitTextures( vout_thread_t *p_vout )
CGLLockContext( glContext ); CGLLockContext( glContext );
CGLSetCurrentContext( glContext ); CGLSetCurrentContext( glContext );
glDeleteTextures( 2, p_vout->p_sys->p_textures ); glDeleteTextures( 3, p_vout->p_sys->p_textures );
CGLUnlockContext( glContext ); CGLUnlockContext( glContext );
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment