X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fopengllayer.m;h=aed86020f95703c612c0da1ab5d84059afe960f9;hb=f5f434a61e9d0de0f6bcc5fe01bf72d2216739b5;hp=042b1ee9e607561eb16771711188dae7b5f10ccb;hpb=978372f47ea6350cc95bb596b482064215ee4562;p=vlc diff --git a/modules/video_output/opengllayer.m b/modules/video_output/opengllayer.m index 042b1ee9e6..aed86020f9 100644 --- a/modules/video_output/opengllayer.m +++ b/modules/video_output/opengllayer.m @@ -32,7 +32,12 @@ *****************************************************************************/ #include /* ENOMEM */ -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include #include #import @@ -88,7 +93,7 @@ vlc_module_begin(); set_shortname( "OpenGLLayer" ); set_category( CAT_VIDEO ); set_subcategory( SUBCAT_VIDEO_VOUT ); - set_description( _("Core Animation OpenGL Layer (Mac OS X)") ); + set_description( N_("Core Animation OpenGL Layer (Mac OS X)") ); set_capability( "video output", 20 ); add_shortcut( "opengllayer" ); set_callbacks( CreateVout, DestroyVout ); @@ -112,7 +117,9 @@ struct vout_sys_t uint8_t *pp_buffer[2]; /* one last rendered, one to be rendered */ int i_index; - vlc_bool_t b_frame_available; + bool b_frame_available; + + CGLContextObj glContext; int i_tex_width; int i_tex_height; @@ -146,7 +153,6 @@ static int CreateVout( vlc_object_t *p_this ) 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; @@ -203,11 +209,11 @@ static int Init( vout_thread_t *p_vout ) return VLC_EGENERIC; } } - p_sys->b_frame_available = VLC_FALSE; + p_sys->b_frame_available = false; p_sys->i_index = 0; - + 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_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; @@ -238,23 +244,17 @@ static void End( vout_thread_t *p_vout ) { vout_sys_t *p_sys = p_vout->p_sys; - p_vout->p_sys->b_frame_available = 0; + p_vout->p_sys->b_frame_available = false; - [CATransaction performSelectorOnMainThread:@selector(begin) - withObject:nil waitUntilDone:YES]; - - [p_sys->o_layer performSelectorOnMainThread:@selector(removeFromSuperlayer) - withObject:nil waitUntilDone:YES]; - [CATransaction performSelectorOnMainThread:@selector(commit) - withObject:nil waitUntilDone:YES]; + [p_vout->p_sys->o_cocoa_container performSelectorOnMainThread:@selector(removeVoutLayer:) withObject:p_vout->p_sys->o_layer waitUntilDone:YES]; // Should be done automatically [p_sys->o_layer release]; [p_sys->autorealease_pool release]; /* Free the texture buffer*/ - if( p_sys->pp_buffer[0] ) free( p_sys->pp_buffer[0] ); - if( p_sys->pp_buffer[1] ) free( p_sys->pp_buffer[1] ); + free( p_sys->pp_buffer[0] ); + free( p_sys->pp_buffer[1] ); } /***************************************************************************** @@ -276,7 +276,9 @@ static void DestroyVout( vlc_object_t *p_this ) * 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; } @@ -287,16 +289,37 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic ) { vout_sys_t *p_sys = p_vout->p_sys; - /* Switch buffers */ - int p_new_index; - @synchronized(p_sys->o_layer) + @synchronized( p_sys->o_layer ) /* Make sure the p_sys->glContext isn't edited */ { - p_new_index = (p_sys->i_index + 1) & 1; + if( p_sys->glContext ) + { + CGLLockContext(p_sys->glContext); + CGLSetCurrentContext(p_sys->glContext); + 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_vout->fmt_out.i_width, + p_vout->fmt_out.i_height, + VLCGL_FORMAT, VLCGL_TYPE, p_sys->pp_buffer[i_new_index] ); + + /* Bind to the previous texture for drawing */ + glBindTexture( VLCGL_TARGET, p_sys->p_textures[p_sys->i_index] ); + + /* Switch buffers */ + p_sys->i_index = i_new_index; + p_pic->p->p_pixels = p_sys->pp_buffer[p_sys->i_index]; + CGLUnlockContext(p_sys->glContext); + + p_sys->b_frame_available = true; + } } /* 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_index]; } /***************************************************************************** @@ -305,14 +328,9 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic ) static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic ) { vout_sys_t *p_sys = p_vout->p_sys; - - /* The frame is ready, give its number so the o_layer can display it */ - @synchronized(p_sys->o_layer) - { - p_sys->i_index = (p_sys->i_index + 1) & 1; /* Indicate the layer should use that index */ - } - - p_sys->b_frame_available = 1; + + [p_sys->o_layer performSelectorOnMainThread:@selector(display) + withObject:nil waitUntilDone:YES]; } /***************************************************************************** @@ -361,19 +379,19 @@ static int InitTextures( vout_thread_t *p_vout ) 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 ); glPixelStorei( GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE ); /* Use AGP texturing */ - glTexParameteri( VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE, - GL_STORAGE_SHARED_APPLE ); -#endif + glTexParameteri( VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE ); /* 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] ); } @@ -394,22 +412,17 @@ static int InitTextures( vout_thread_t *p_vout ) + (void)autoinitInVout:(NSValue*)arg { vout_thread_t * p_vout = [arg pointerValue]; - p_vout->p_sys->o_layer = [[VLCVoutLayer layerWithVout: p_vout] retain]; + p_vout->p_sys->o_layer = [[VLCVoutLayer layerWithVout:p_vout] retain]; [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.asynchronous = YES; - [me setVout: _p_vout]; + me->p_vout = _p_vout; + me.asynchronous = NO; 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 ); @@ -419,15 +432,12 @@ static int InitTextures( vout_thread_t *p_vout ) - (BOOL)canDrawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp { - /* Only draw the frame when if have a frame that was previously rendered */ - BOOL ret = p_vout->p_sys->b_frame_available; - p_vout->p_sys->b_frame_available = VLC_FALSE; - return ret; + /* 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: } - (void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp { - /* Init */ CGLLockContext( glContext ); CGLSetCurrentContext( glContext ); @@ -440,60 +450,30 @@ static int InitTextures( vout_thread_t *p_vout ) f_height = (float)p_vout->fmt_out.i_y_offset + (float)p_vout->fmt_out.i_visible_height; - @synchronized(self) - { - glBindTexture( VLCGL_TARGET, p_vout->p_sys->p_textures[p_vout->p_sys->i_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] ); - - - glClear( GL_COLOR_BUFFER_BIT ); + glClear( GL_COLOR_BUFFER_BIT ); - glEnable( VLCGL_TARGET ); - glBegin( GL_POLYGON ); - glTexCoord2f( f_x, f_y ); glVertex2f( -1.0, 1.0 ); - glTexCoord2f( f_width, f_y ); glVertex2f( 1.0, 1.0 ); - glTexCoord2f( f_width, f_height ); glVertex2f( 1.0, -1.0 ); - glTexCoord2f( f_x, f_height ); glVertex2f( -1.0, -1.0 ); - glEnd(); + glEnable( VLCGL_TARGET ); + glBegin( GL_POLYGON ); + glTexCoord2f( f_x, f_y ); glVertex2f( -1.0, 1.0 ); + glTexCoord2f( f_width, f_y ); glVertex2f( 1.0, 1.0 ); + glTexCoord2f( f_width, f_height ); glVertex2f( 1.0, -1.0 ); + glTexCoord2f( f_x, f_height ); glVertex2f( -1.0, -1.0 ); + glEnd(); - glDisable( VLCGL_TARGET ); + glDisable( VLCGL_TARGET ); - glFlush(); - } + glFlush(); CGLUnlockContext( glContext ); - 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 [super copyCGLPixelFormatForDisplayMask:mask];//[fmt CGLPixelFormatObj]; } - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat { CGLContextObj context = [super copyCGLContextForPixelFormat:pixelFormat]; + CGLLockContext( context ); + + CGLSetCurrentContext( context ); /* Swap buffers only during the vertical retrace of the monitor. http://developer.apple.com/documentation/GraphicsImaging/ @@ -501,29 +481,33 @@ static int InitTextures( vout_thread_t *p_vout ) GLint params = 1; CGLSetParameter( CGLGetCurrentContext(), kCGLCPSwapInterval, - ¶ms ); - - /* Make sure our texture will gets drawn at the right resolution */ - GLint dim[2] = { p_vout->p_sys->i_tex_width, p_vout->p_sys->i_tex_height}; - NSLog(@"asking for %dx%d", p_vout->p_sys->i_tex_width, p_vout->p_sys->i_tex_height); - CGLSetParameter(context, kCGLCPSurfaceBackingSize, dim); - CGLEnable (context, kCGLCESurfaceBackingSize); + ¶ms ); - CGLSetCurrentContext( context ); InitTextures( p_vout ); - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - glDisable(GL_CULL_FACE); + glDisable( GL_BLEND ); + glDisable( GL_DEPTH_TEST ); + glDepthMask( GL_FALSE ); + glDisable( GL_CULL_FACE) ; glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT ); + CGLUnlockContext( context ); + @synchronized( self ) + { + p_vout->p_sys->glContext = context; + } + return context; } - (void)releaseCGLContext:(CGLContextObj)glContext { + @synchronized( self ) + { + p_vout->p_sys->glContext = nil; + } + CGLLockContext( glContext ); CGLSetCurrentContext( glContext ); @@ -531,5 +515,4 @@ static int InitTextures( vout_thread_t *p_vout ) CGLUnlockContext( glContext ); } - @end