{
vout_thread_t * p_vout;
- uint8_t *pp_buffer[2]; /* one last rendered, one to be rendered */
- int i_index;
+ uint8_t *pp_buffer[3]; /* one last rendered, one to be rendered */
+ int i_rendering_index;
+ int i_rendered_index;
+ int i_on_screen_index;
vlc_bool_t b_frame_available;
int i_tex_width;
int i_tex_height;
- GLuint p_textures[2];
+ GLuint p_textures[3];
NSAutoreleasePool *autorealease_pool;
VLCVoutLayer * o_layer;
msg_Dbg( p_vout, "Texture size: %dx%d", p_sys->i_tex_width,
p_sys->i_tex_height );
-
p_vout->pf_init = Init;
p_vout->pf_end = End;
p_vout->pf_manage = Manage;
/* We know the chroma, allocate two buffer which will be used
* directly by the decoder */
int i;
- for( i = 0; i < 2; i++ )
+ for( i = 0; i < 3; i++ )
{
p_sys->pp_buffer[i] =
malloc( p_sys->i_tex_width * p_sys->i_tex_height * i_pixel_pitch );
}
}
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].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_visible_lines = p_vout->output.i_height;
p_vout->p_picture[0].p->i_pixel_pitch = i_pixel_pitch;
/* Free the texture buffer*/
free( p_sys->pp_buffer[0] );
free( p_sys->pp_buffer[1] );
+ if( p_sys->pp_buffer[2] ) free( p_sys->pp_buffer[2] );
}
/*****************************************************************************
* a non null value if an error occurred.
*****************************************************************************/
static int Manage( vout_thread_t *p_vout )
-{
+{
+ vout_sys_t *p_sys = p_vout->p_sys;
+
return VLC_SUCCESS;
}
{
vout_sys_t *p_sys = p_vout->p_sys;
- /* Switch buffers */
- int p_new_index;
- @synchronized(p_sys->o_layer)
- {
- p_new_index = (p_sys->i_index + 1) & 1;
- }
+ /* Make sure we never draw to the currently on screen buffer */
+ assert(p_sys->i_rendering_index != p_sys->i_on_screen_index );
/* 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];
+
+
}
/*****************************************************************************
{
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)
{
- 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;
}
/*****************************************************************************
vout_sys_t *p_sys = p_vout->p_sys;
int i_index;
- glDeleteTextures( 2, p_sys->p_textures );
- glGenTextures( 2, p_sys->p_textures );
+ glDeleteTextures( 3, 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] );
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
our buffer */
glEnable( GL_UNPACK_CLIENT_STORAGE_APPLE );
/* Use AGP texturing */
glTexParameteri( VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE,
GL_STORAGE_SHARED_APPLE );
-#endif
/* 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->pp_buffer[i_index] );
}
[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
{
- VLCVoutLayer* me = [super layer];
+ VLCVoutLayer* me = [[[self alloc] init] autorelease];
if( me )
{
+ me->p_vout = _p_vout;
me.asynchronous = YES;
- [me setVout: _p_vout];
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_height * _p_vout->fmt_in.i_sar_den );
- (BOOL)canDrawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
{
/* Only draw the frame if we have a frame that was previously rendered */
- return p_vout->p_sys->b_frame_available; // Flag is cleared by drawInCGLContext:pixelFormat:forLayerTime:displayTime:
+ return p_vout->p_sys->b_frame_available; // Flag is cleared by drawInCGLContext:pixelFormat:forLayerTime:displayTime:
}
- (void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
f_height = (float)p_vout->fmt_out.i_y_offset +
(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)
{
- 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,
p_vout->fmt_out.i_width,
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 );
glDisable( VLCGL_TARGET );
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 context = [super copyCGLContextForPixelFormat:pixelFormat];
- CGLLockContext( context );
-
+ CGLLockContext( context );
+
CGLSetCurrentContext( context );
/* Swap buffers only during the vertical retrace of the monitor.
GLint params = 1;
CGLSetParameter( CGLGetCurrentContext(), kCGLCPSwapInterval,
¶ms );
-
+
InitTextures( p_vout );
glDisable( GL_BLEND );
glClear( GL_COLOR_BUFFER_BIT );
CGLUnlockContext( context );
+
return context;
}
CGLLockContext( glContext );
CGLSetCurrentContext( glContext );
- glDeleteTextures( 2, p_vout->p_sys->p_textures );
+ glDeleteTextures( 3, p_vout->p_sys->p_textures );
CGLUnlockContext( glContext );
}