Commit 581f3e40 authored by Eric Petit's avatar Eric Petit

+ macosx/vout*: use two pictures and OpenGL textures so a texture

                 cannot be affected by VLC loading the next picture
		 (should fix the artifacts when moving or resizing
		  the window)
parent 90376941
...@@ -61,7 +61,8 @@ ...@@ -61,7 +61,8 @@
{ {
vout_thread_t * p_vout; vout_thread_t * p_vout;
int i_effect; int i_effect;
unsigned long i_texture; unsigned long pi_textures[2];
int i_curTexture;
float f_x; float f_x;
float f_y; float f_y;
int initDone; int initDone;
...@@ -72,7 +73,7 @@ ...@@ -72,7 +73,7 @@
- (id) initWithFrame: (NSRect) frame vout: (vout_thread_t*) p_vout; - (id) initWithFrame: (NSRect) frame vout: (vout_thread_t*) p_vout;
- (void) initTextures; - (void) initTextures;
- (void) reloadTexture; - (void) reloadTexture: (int) index;
- (void) goFullScreen; - (void) goFullScreen;
- (void) exitFullScreen; - (void) exitFullScreen;
- (void) cleanUp; - (void) cleanUp;
...@@ -115,5 +116,9 @@ struct vout_sys_t ...@@ -115,5 +116,9 @@ struct vout_sys_t
Ptr p_fullscreen_state; Ptr p_fullscreen_state;
#endif #endif
/* OpenGL */
VLCGLView * o_glview; VLCGLView * o_glview;
uint8_t * p_data[2];
uint8_t * p_data_orig[2];
int i_cur_pic;
}; };
...@@ -282,11 +282,10 @@ int E_(OpenVideo) ( vlc_object_t *p_this ) ...@@ -282,11 +282,10 @@ int E_(OpenVideo) ( vlc_object_t *p_this )
/***************************************************************************** /*****************************************************************************
* vout_Init: initialize video thread output method * vout_Init: initialize video thread output method
*****************************************************************************/ *****************************************************************************/
static int vout_InitOpenGL( vout_thread_t *p_vout );
static int vout_InitQuickTime( vout_thread_t *p_vout );
static int vout_Init( vout_thread_t *p_vout ) static int vout_Init( vout_thread_t *p_vout )
{ {
int i_index;
picture_t *p_pic;
I_OUTPUTPICTURES = 0; I_OUTPUTPICTURES = 0;
/* Initialize the output structure; we already found a codec, /* Initialize the output structure; we already found a codec,
...@@ -296,31 +295,41 @@ static int vout_Init( vout_thread_t *p_vout ) ...@@ -296,31 +295,41 @@ static int vout_Init( vout_thread_t *p_vout )
p_vout->output.i_height = p_vout->render.i_height; p_vout->output.i_height = p_vout->render.i_height;
p_vout->output.i_aspect = p_vout->render.i_aspect; p_vout->output.i_aspect = p_vout->render.i_aspect;
if( !p_vout->p_sys->i_opengl ) if( p_vout->p_sys->i_opengl )
{
SetPort( p_vout->p_sys->p_qdport );
QTScaleMatrix( p_vout );
if( QTCreateSequence( p_vout ) )
{ {
msg_Err( p_vout, "unable to create sequence" ); return vout_InitOpenGL( p_vout );
return( 1 );
}
} }
else else
{ {
return vout_InitQuickTime( p_vout );
}
}
static int vout_InitOpenGL( vout_thread_t *p_vout )
{
picture_t *p_pic;
int i_bytes;
int i_index;
/* Apple OpenGL extensions only accept YUV as YUY2 */
p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2'); p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
p_vout->output.i_rmask = 0xFF0000; p_vout->output.i_rmask = 0xFF0000;
p_vout->output.i_gmask = 0x00FF00; p_vout->output.i_gmask = 0x00FF00;
p_vout->output.i_bmask = 0x0000FF; p_vout->output.i_bmask = 0x0000FF;
}
/* Try to initialize up to QT_MAX_DIRECTBUFFERS direct buffers */ /* Allocate our 2 picture buffers */
while( I_OUTPUTPICTURES < i_bytes = 2 * p_vout->output.i_width * p_vout->output.i_height;
p_vout->p_sys->i_opengl ? 1 : QT_MAX_DIRECTBUFFERS ) p_vout->p_sys->p_data[0] = vlc_memalign(
{ &p_vout->p_sys->p_data_orig[0], 16, i_bytes );
p_pic = NULL; p_vout->p_sys->p_data[1] = vlc_memalign(
&p_vout->p_sys->p_data_orig[1], 16, i_bytes );
p_vout->p_sys->i_cur_pic = 1;
/* We declare only one picture and will switch buffers
manually */
p_pic = NULL;
while( I_OUTPUTPICTURES < 1 )
{
/* Find an empty picture slot */ /* Find an empty picture slot */
for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ ) for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ )
{ {
...@@ -330,46 +339,85 @@ static int vout_Init( vout_thread_t *p_vout ) ...@@ -330,46 +339,85 @@ static int vout_Init( vout_thread_t *p_vout )
break; break;
} }
} }
/* Allocate the picture */
if( p_pic == NULL ) if( p_pic == NULL )
{ {
break; break;
} }
if( !p_vout->p_sys->i_opengl ) vout_InitPicture( VLC_OBJECT( p_vout ), p_pic,
{
if( QTNewPicture( p_vout, p_pic ) )
{
break;
}
}
else
{
/* Nothing special to do, we just need a basic allocated
picture_t */
vout_AllocatePicture( VLC_OBJECT( p_vout ), p_pic,
p_vout->output.i_chroma, p_vout->output.i_width, p_vout->output.i_chroma, p_vout->output.i_width,
p_vout->output.i_height, p_vout->output.i_aspect ); p_vout->output.i_height, p_vout->output.i_aspect );
p_pic->p_data = p_vout->p_sys->p_data[0];
p_pic->p[0].p_pixels = p_pic->p_data;
for( i_index = 1; i_index < p_pic->i_planes; i_index++ )
{
p_pic->p[i_index].p_pixels =
p_pic->p[i_index-1].p_pixels +
p_pic->p[i_index-1].i_lines *
p_pic->p[i_index-1].i_pitch;
} }
p_pic->i_status = DESTROYED_PICTURE; p_pic->i_status = DESTROYED_PICTURE;
p_pic->i_type = DIRECT_PICTURE; p_pic->i_type = DIRECT_PICTURE;
PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
I_OUTPUTPICTURES++; I_OUTPUTPICTURES++;
} }
if( p_vout->p_sys->i_opengl )
{
[p_vout->p_sys->o_glview lockFocus]; [p_vout->p_sys->o_glview lockFocus];
[p_vout->p_sys->o_glview initTextures]; [p_vout->p_sys->o_glview initTextures];
[p_vout->p_sys->o_glview reshape]; [p_vout->p_sys->o_glview reshape];
[p_vout->p_sys->o_glview unlockFocus]; [p_vout->p_sys->o_glview unlockFocus];
return 0;
}
static int vout_InitQuickTime( vout_thread_t *p_vout )
{
picture_t *p_pic;
int i_index;
SetPort( p_vout->p_sys->p_qdport );
QTScaleMatrix( p_vout );
if( QTCreateSequence( p_vout ) )
{
msg_Err( p_vout, "unable to create sequence" );
return( 1 );
} }
return( 0 ); /* Try to initialize up to QT_MAX_DIRECTBUFFERS direct buffers */
while( I_OUTPUTPICTURES < QT_MAX_DIRECTBUFFERS )
{
p_pic = NULL;
/* Find an empty picture slot */
for( i_index = 0; i_index < VOUT_MAX_PICTURES; i_index++ )
{
if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
{
p_pic = p_vout->p_picture + i_index;
break;
}
}
if( p_pic == NULL )
{
break;
}
/* Allocate the picture */
if( QTNewPicture( p_vout, p_pic ) )
{
break;
}
p_pic->i_status = DESTROYED_PICTURE;
p_pic->i_type = DIRECT_PICTURE;
PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
I_OUTPUTPICTURES++;
}
return 0;
} }
/***************************************************************************** /*****************************************************************************
...@@ -398,7 +446,8 @@ static void vout_End( vout_thread_t *p_vout ) ...@@ -398,7 +446,8 @@ static void vout_End( vout_thread_t *p_vout )
} }
else else
{ {
free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig ); free( p_vout->p_sys->p_data_orig[0] );
free( p_vout->p_sys->p_data_orig[1] );
} }
} }
} }
...@@ -509,11 +558,30 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -509,11 +558,30 @@ static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
{ {
if( [p_vout->p_sys->o_glview lockFocusIfCanDraw] ) if( [p_vout->p_sys->o_glview lockFocusIfCanDraw] )
{ {
/* Texture gotta be reload before the buffer is filled int i_index;
(thanks to gcc from arstechnica forums) */ int i_old = p_vout->p_sys->i_cur_pic;
int i_new = ( i_old + 1 ) % 2;
/* Draw the new picture */
p_vout->p_sys->i_cur_pic = i_new;
[p_vout->p_sys->o_glview drawRect: [p_vout->p_sys->o_glview drawRect:
[p_vout->p_sys->o_glview bounds]]; [p_vout->p_sys->o_glview bounds]];
[p_vout->p_sys->o_glview reloadTexture];
/* Reload the other texture. Textures have to be reloaded
before the buffer is filled (thanks to gcc from
arstechnica forums) */
[p_vout->p_sys->o_glview reloadTexture: i_old];
/* Switch buffers */
p_pic->p_data = p_vout->p_sys->p_data[i_old];
p_pic->p[0].p_pixels = p_pic->p_data;
for( i_index = 1; i_index < p_pic->i_planes; i_index++ )
{
p_pic->p[i_index].p_pixels =
p_pic->p[i_index-1].p_pixels +
p_pic->p[i_index-1].i_lines *
p_pic->p[i_index-1].i_pitch;
}
[p_vout->p_sys->o_glview unlockFocus]; [p_vout->p_sys->o_glview unlockFocus];
} }
} }
...@@ -1414,7 +1482,8 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1414,7 +1482,8 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
glTranslatef( 0.0, 0.0, - 5.0 ); glTranslatef( 0.0, 0.0, - 5.0 );
} }
i_texture = 0; pi_textures[0] = 0;
pi_textures[1] = 0;
initDone = 0; initDone = 0;
isFullScreen = 0; isFullScreen = 0;
...@@ -1434,12 +1503,12 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1434,12 +1503,12 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
glViewport( 0, 0, (GLint) bounds.size.width, glViewport( 0, 0, (GLint) bounds.size.width,
(GLint) bounds.size.height ); (GLint) bounds.size.height );
/* Quad size is set in order to preserve the aspect ratio */
if( config_GetInt( p_vout, "macosx-stretch" ) ) if( config_GetInt( p_vout, "macosx-stretch" ) )
{ {
f_x = 1.0; f_x = 1.0;
f_y = 1.0; f_y = 1.0;
} }
/* Quad size is set in order to preserve the aspect ratio */
else if( bounds.size.height * p_vout->output.i_aspect < else if( bounds.size.height * p_vout->output.i_aspect <
bounds.size.width * VOUT_ASPECT_FACTOR ) bounds.size.width * VOUT_ASPECT_FACTOR )
{ {
...@@ -1457,21 +1526,24 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1457,21 +1526,24 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
- (void) initTextures - (void) initTextures
{ {
int i;
[currentContext makeCurrentContext]; [currentContext makeCurrentContext];
/* Free previous texture if any */ /* Free previous texture if any */
if( i_texture ) if( initDone )
{ {
glDeleteTextures( 1, &i_texture ); glDeleteTextures( 2, pi_textures );
} }
/* Create textures */ /* Create textures */
glGenTextures( 1, &i_texture ); glGenTextures( 2, pi_textures );
glEnable( GL_TEXTURE_RECTANGLE_EXT ); glEnable( GL_TEXTURE_RECTANGLE_EXT );
glEnable( GL_UNPACK_CLIENT_STORAGE_APPLE ); glEnable( GL_UNPACK_CLIENT_STORAGE_APPLE );
glBindTexture( GL_TEXTURE_RECTANGLE_EXT, i_texture ); for( i = 0; i < 2; i++ )
{
glBindTexture( GL_TEXTURE_RECTANGLE_EXT, pi_textures[i] );
/* Use VRAM texturing */ /* Use VRAM texturing */
glTexParameteri( GL_TEXTURE_RECTANGLE_EXT, glTexParameteri( GL_TEXTURE_RECTANGLE_EXT,
...@@ -1498,12 +1570,13 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1498,12 +1570,13 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
glTexImage2D( GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, glTexImage2D( GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA,
p_vout->output.i_width, p_vout->output.i_height, 0, p_vout->output.i_width, p_vout->output.i_height, 0,
GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE,
PP_OUTPUTPICTURE[0]->p_data ); p_vout->p_sys->p_data[i] );
}
initDone = 1; initDone = 1;
} }
- (void)reloadTexture - (void)reloadTexture: (int) index
{ {
if( !initDone ) if( !initDone )
{ {
...@@ -1512,7 +1585,7 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1512,7 +1585,7 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
[currentContext makeCurrentContext]; [currentContext makeCurrentContext];
glBindTexture( GL_TEXTURE_RECTANGLE_EXT, i_texture ); glBindTexture( GL_TEXTURE_RECTANGLE_EXT, pi_textures[index] );
/* glTexSubImage2D is faster than glTexImage2D /* glTexSubImage2D is faster than glTexImage2D
http://developer.apple.com/samplecode/Sample_Code/Graphics_3D/ http://developer.apple.com/samplecode/Sample_Code/Graphics_3D/
...@@ -1520,7 +1593,7 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1520,7 +1593,7 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
glTexSubImage2D( GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, glTexSubImage2D( GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0,
p_vout->output.i_width, p_vout->output.i_height, p_vout->output.i_width, p_vout->output.i_height,
GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE,
PP_OUTPUTPICTURE[0]->p_data ); p_vout->p_sys->p_data[index] );
} }
- (void)goFullScreen - (void)goFullScreen
...@@ -1536,7 +1609,7 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1536,7 +1609,7 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
NSOpenGLPFADepthSize, 24, NSOpenGLPFADepthSize, 24,
NSOpenGLPFAFullScreen, NSOpenGLPFAFullScreen,
NSOpenGLPFAScreenMask, NSOpenGLPFAScreenMask,
/* TODO handle macosx-vdev */ /* TODO multi monitor support */
CGDisplayIDToOpenGLDisplayMask( kCGDirectMainDisplay ), CGDisplayIDToOpenGLDisplayMask( kCGDirectMainDisplay ),
0 0
}; };
...@@ -1549,6 +1622,8 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1549,6 +1622,8 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
} }
/* Create the new OpenGL context */ /* Create the new OpenGL context */
/* TODO have the shared context working so we don't have to
re-init textures */
fullScreenContext = [[NSOpenGLContext alloc] fullScreenContext = [[NSOpenGLContext alloc]
initWithFormat: fmt shareContext: nil]; initWithFormat: fmt shareContext: nil];
if( !fullScreenContext ) if( !fullScreenContext )
...@@ -1559,6 +1634,8 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1559,6 +1634,8 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
currentContext = fullScreenContext; currentContext = fullScreenContext;
/* Capture display, switch to fullscreen */ /* Capture display, switch to fullscreen */
/* XXX we should capture only the display the user wants the
picture on */
if( CGCaptureAllDisplays() != CGDisplayNoErr ) if( CGCaptureAllDisplays() != CGDisplayNoErr )
{ {
msg_Warn( p_vout, "CGCaptureAllDisplays() failed" ); msg_Warn( p_vout, "CGCaptureAllDisplays() failed" );
...@@ -1740,7 +1817,8 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ) ...@@ -1740,7 +1817,8 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
} }
/* Draw */ /* Draw */
glBindTexture( GL_TEXTURE_RECTANGLE_EXT, i_texture ); glBindTexture( GL_TEXTURE_RECTANGLE_EXT,
pi_textures[p_vout->p_sys->i_cur_pic] );
if( i_effect & ( OPENGL_EFFECT_CUBE | if( i_effect & ( OPENGL_EFFECT_CUBE |
OPENGL_EFFECT_TRANSPARENT_CUBE ) ) OPENGL_EFFECT_TRANSPARENT_CUBE ) )
{ {
......
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