X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fopengl.c;h=77a76c08cc163c0c9224fb5c78871191c3542429;hb=2a8cfbc3b887c0703286d3c97940ff88915143d1;hp=6733bcc8eb6f14dd39245253bc0070ab42a76a29;hpb=aadbe03cd05017077eece540db1d57bfd438308a;p=vlc diff --git a/modules/video_output/opengl.c b/modules/video_output/opengl.c index 6733bcc8eb..77a76c08cc 100644 --- a/modules/video_output/opengl.c +++ b/modules/video_output/opengl.c @@ -6,6 +6,7 @@ * * Authors: Cyril Deguet * Gildas Bazin + * Eric Petit * * 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 @@ -68,6 +69,10 @@ #define VLCGL_TYPE VLCGL_RGB_TYPE #endif +#ifndef GL_CLAMP_TO_EDGE +# define GL_CLAMP_TO_EDGE 0x812F +#endif + /* OpenGL effects */ #define OPENGL_EFFECT_NONE 1 #define OPENGL_EFFECT_CUBE 2 @@ -94,11 +99,27 @@ static int SendEvents( vlc_object_t *, char const *, /***************************************************************************** * Module descriptor *****************************************************************************/ +#define SPEED_TEXT N_( "OpenGL cube rotation speed" ) +/***************************************************************************** + * Module descriptor + *****************************************************************************/ +#define SPEED_TEXT N_( "OpenGL cube rotation speed" ) +#define SPEED_LONGTEXT N_( "If the OpenGL cube effect is enabled, this " \ + "controls its rotation speed." ) + #define EFFECT_TEXT N_("Select effect") #define EFFECT_LONGTEXT N_( \ "Allows you to select different visual effects.") +static char *ppsz_effects[] = { + "none", "cube", "transparent-cube" }; +static char *ppsz_effects_text[] = { + N_("None"), N_("Cube"), N_("Transparent Cube") }; + vlc_module_begin(); + set_shortname( "OpenGL" ); + set_category( CAT_VIDEO ); + set_subcategory( SUBCAT_VIDEO_VOUT ); set_description( _("OpenGL video output") ); #ifdef SYS_DARWIN set_capability( "video output", 200 ); @@ -106,10 +127,12 @@ vlc_module_begin(); set_capability( "video output", 20 ); #endif add_shortcut( "opengl" ); + add_float( "opengl-cube-speed", 2.0, NULL, SPEED_TEXT, + SPEED_LONGTEXT, VLC_TRUE ); set_callbacks( CreateVout, DestroyVout ); - add_string( "opengl-effect", "none", NULL, EFFECT_TEXT, - EFFECT_LONGTEXT, VLC_TRUE ); + EFFECT_LONGTEXT, VLC_FALSE ); + change_string_list( ppsz_effects, ppsz_effects_text, 0 ); vlc_module_end(); /***************************************************************************** @@ -129,6 +152,8 @@ struct vout_sys_t GLuint p_textures[2]; int i_effect; + + float f_speed; }; /***************************************************************************** @@ -149,6 +174,7 @@ static int CreateVout( vlc_object_t *p_this ) var_Create( p_vout, "opengl-effect", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); + p_sys->i_index = 0; #ifdef SYS_DARWIN p_sys->i_tex_width = p_vout->render.i_width; p_sys->i_tex_height = p_vout->render.i_height; @@ -190,6 +216,8 @@ static int CreateVout( vlc_object_t *p_this ) return VLC_ENOOBJ; } + p_sys->f_speed = var_CreateGetFloat( p_vout, "opengl-cube-speed" ); + p_vout->pf_init = Init; p_vout->pf_end = End; p_vout->pf_manage = Manage; @@ -294,6 +322,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); @@ -343,6 +378,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; } @@ -351,8 +391,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 ); + } } /***************************************************************************** @@ -394,6 +448,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 ) @@ -425,6 +486,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; @@ -436,19 +502,6 @@ static int Manage( vout_thread_t *p_vout ) static void Render( vout_thread_t *p_vout, picture_t *p_pic ) { vout_sys_t *p_sys = p_vout->p_sys; - float f_width, f_height; - - /* glTexCoord works differently with GL_TEXTURE_2D and - GL_TEXTURE_RECTANGLE_EXT */ -#ifdef SYS_DARWIN - f_width = (float)p_vout->output.i_width; - f_height = (float)p_vout->output.i_height; -#else - f_width = (float)p_vout->output.i_width / p_sys->i_tex_width; - f_height = (float)p_vout->output.i_height / p_sys->i_tex_height; -#endif - - glClear( GL_COLOR_BUFFER_BIT ); /* On Win32/GLX, we do this the usual way: + Fill the buffer with new content, @@ -467,93 +520,134 @@ 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, + p_sys->i_tex_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] ); -#else + /* Switch buffers */ + p_sys->i_index = i_new_index; + p_pic->p->p_pixels = p_sys->pp_buffer[p_sys->i_index]; + +#else /* Update the texture */ glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 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 ); + } +} + +/***************************************************************************** + * DisplayVideo: displays previously rendered output + *****************************************************************************/ +static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic ) +{ + vout_sys_t *p_sys = p_vout->p_sys; + float f_width, f_height; + + 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; + } + + /* glTexCoord works differently with GL_TEXTURE_2D and + GL_TEXTURE_RECTANGLE_EXT */ +#ifdef SYS_DARWIN + f_width = (float)p_vout->output.i_width; + f_height = (float)p_vout->output.i_height; +#else + f_width = (float)p_vout->output.i_width / p_sys->i_tex_width; + f_height = (float)p_vout->output.i_height / p_sys->i_tex_height; +#endif + + /* Why drawing here and not in Render()? Because this way, the + OpenGL providers can call pf_display to force redraw. Currently, + the OS X provider uses it to get a smooth window resizing */ + + glClear( GL_COLOR_BUFFER_BIT ); + if( p_sys->i_effect == OPENGL_EFFECT_NONE ) { glEnable( VLCGL_TARGET ); glBegin( GL_POLYGON ); - glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, 1.0 ); - glTexCoord2f( f_width, 0.0 ); glVertex2f( 1.0, 1.0 ); - glTexCoord2f( f_width, f_height ); glVertex2f( 1.0, -1.0 ); - glTexCoord2f( 0.0, f_height ); glVertex2f( -1.0, -1.0 ); + glTexCoord2f( 0.5, 0.5 ); glVertex2f( -1.0, 1.0 ); + glTexCoord2f( f_width - 0.5, 0.5 ); glVertex2f( 1.0, 1.0 ); + glTexCoord2f( f_width - 0.5, f_height - 0.5 ); glVertex2f( 1.0, -1.0 ); + glTexCoord2f( 0.5, f_height - 0.5 ); glVertex2f( -1.0, -1.0 ); glEnd(); } else { - glRotatef( 1.0, 0.3, 0.5, 0.7 ); + glRotatef( 0.5 * p_sys->f_speed , 0.3, 0.5, 0.7 ); glEnable( VLCGL_TARGET ); glBegin( GL_QUADS ); /* Front */ - glTexCoord2f( 0, 0 ); glVertex3f( - 1.0, 1.0, 1.0 ); - glTexCoord2f( 0, f_height ); glVertex3f( - 1.0, - 1.0, 1.0 ); - glTexCoord2f( f_width, f_height ); glVertex3f( 1.0, - 1.0, 1.0 ); - glTexCoord2f( f_width, 0 ); glVertex3f( 1.0, 1.0, 1.0 ); + glTexCoord2f( 0.5, 0.5 ); glVertex3f( - 1.0, 1.0, 1.0 ); + glTexCoord2f( 0.5, f_height - 0.5 ); glVertex3f( - 1.0, - 1.0, 1.0 ); + glTexCoord2f( f_width - 0.5, f_height - 0.5 ); glVertex3f( 1.0, - 1.0, 1.0 ); + glTexCoord2f( f_width - 0.5, 0.5 ); glVertex3f( 1.0, 1.0, 1.0 ); /* Left */ - glTexCoord2f( 0, 0 ); glVertex3f( - 1.0, 1.0, - 1.0 ); - glTexCoord2f( 0, f_height ); glVertex3f( - 1.0, - 1.0, - 1.0 ); - glTexCoord2f( f_width, f_height ); glVertex3f( - 1.0, - 1.0, 1.0 ); - glTexCoord2f( f_width, 0 ); glVertex3f( - 1.0, 1.0, 1.0 ); + glTexCoord2f( 0.5, 0.5 ); glVertex3f( - 1.0, 1.0, - 1.0 ); + glTexCoord2f( 0.5, f_height - 0.5 ); glVertex3f( - 1.0, - 1.0, - 1.0 ); + glTexCoord2f( f_width - 0.5, f_height - 0.5 ); glVertex3f( - 1.0, - 1.0, 1.0 ); + glTexCoord2f( f_width - 0.5, 0.5 ); glVertex3f( - 1.0, 1.0, 1.0 ); /* Back */ - glTexCoord2f( 0, 0 ); glVertex3f( 1.0, 1.0, - 1.0 ); - glTexCoord2f( 0, f_height ); glVertex3f( 1.0, - 1.0, - 1.0 ); - glTexCoord2f( f_width, f_height ); glVertex3f( - 1.0, - 1.0, - 1.0 ); - glTexCoord2f( f_width, 0 ); glVertex3f( - 1.0, 1.0, - 1.0 ); + glTexCoord2f( 0.5, 0.5 ); glVertex3f( 1.0, 1.0, - 1.0 ); + glTexCoord2f( 0.5, f_height - 0.5 ); glVertex3f( 1.0, - 1.0, - 1.0 ); + glTexCoord2f( f_width - 0.5, f_height - 0.5 ); glVertex3f( - 1.0, - 1.0, - 1.0 ); + glTexCoord2f( f_width - 0.5, 0.5 ); glVertex3f( - 1.0, 1.0, - 1.0 ); /* Right */ - glTexCoord2f( 0, 0 ); glVertex3f( 1.0, 1.0, 1.0 ); - glTexCoord2f( 0, f_height ); glVertex3f( 1.0, - 1.0, 1.0 ); - glTexCoord2f( f_width, f_height ); glVertex3f( 1.0, - 1.0, - 1.0 ); - glTexCoord2f( f_width, 0 ); glVertex3f( 1.0, 1.0, - 1.0 ); + glTexCoord2f( 0.5, 0.5 ); glVertex3f( 1.0, 1.0, 1.0 ); + glTexCoord2f( 0.5, f_height - 0.5 ); glVertex3f( 1.0, - 1.0, 1.0 ); + glTexCoord2f( f_width - 0.5, f_height - 0.5 ); glVertex3f( 1.0, - 1.0, - 1.0 ); + glTexCoord2f( f_width - 0.5, 0.5 ); glVertex3f( 1.0, 1.0, - 1.0 ); /* Top */ - glTexCoord2f( 0, 0 ); glVertex3f( - 1.0, 1.0, - 1.0 ); - glTexCoord2f( 0, f_height ); glVertex3f( - 1.0, 1.0, 1.0 ); - glTexCoord2f( f_width, f_height ); glVertex3f( 1.0, 1.0, 1.0 ); - glTexCoord2f( f_width, 0 ); glVertex3f( 1.0, 1.0, - 1.0 ); - - /* Bottom */ - glTexCoord2f( 0, 0 ); glVertex3f( - 1.0, - 1.0, 1.0 ); - glTexCoord2f( 0, f_height ); glVertex3f( - 1.0, - 1.0, - 1.0 ); - glTexCoord2f( f_width, f_height ); glVertex3f( 1.0, - 1.0, - 1.0 ); - glTexCoord2f( f_width, 0 ); glVertex3f( 1.0, - 1.0, 1.0 ); + glTexCoord2f( 0.5, 0.5 ); glVertex3f( - 1.0, 1.0, - 1.0 ); + glTexCoord2f( 0.5, f_height - 0.5 ); glVertex3f( - 1.0, 1.0, 1.0 ); + glTexCoord2f( f_width - 0.5, f_height - 0.5 ); glVertex3f( 1.0, 1.0, 1.0 ); + glTexCoord2f( 0.5, f_height - 0.5 ); glVertex3f( - 1.0, - 1.0, - 1.0 ); + glTexCoord2f( f_width - 0.5, f_height - 0.5 ); glVertex3f( 1.0, - 1.0, - 1.0 ); + glTexCoord2f( f_width - 0.5, 0.5 ); glVertex3f( 1.0, - 1.0, 1.0 ); glEnd(); } glDisable( VLCGL_TARGET ); -#ifdef SYS_DARWIN - /* Switch buffers */ - p_sys->i_index = ( p_sys->i_index + 1 ) & 1; - p_pic->p->p_pixels = p_sys->pp_buffer[p_sys->i_index]; - - /* Update the texture */ - glBindTexture( VLCGL_TARGET, p_sys->p_textures[p_sys->i_index] ); - glTexSubImage2D( VLCGL_TARGET, 0, 0, 0, p_sys->i_tex_width, - p_sys->i_tex_height, VLCGL_FORMAT, VLCGL_TYPE, - p_sys->pp_buffer[p_sys->i_index] ); -#endif -} - -/***************************************************************************** - * DisplayVideo: displays previously rendered output - *****************************************************************************/ -static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic ) -{ - vout_sys_t *p_sys = p_vout->p_sys; 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 ) @@ -574,10 +668,17 @@ static int Control( vout_thread_t *p_vout, int i_query, va_list args ) { vout_sys_t *p_sys = p_vout->p_sys; - if( p_sys->p_vout->pf_control ) - return p_sys->p_vout->pf_control( p_sys->p_vout, i_query, args ); - else + switch( i_query ) + { + case VOUT_SNAPSHOT: return vout_vaControlDefault( p_vout, i_query, args ); + + default: + if( p_sys->p_vout->pf_control ) + return p_sys->p_vout->pf_control( p_sys->p_vout, i_query, args ); + else + return vout_vaControlDefault( p_vout, i_query, args ); + } } static int InitTextures( vout_thread_t *p_vout ) @@ -595,12 +696,12 @@ static int InitTextures( vout_thread_t *p_vout ) /* Set the texture parameters */ glTexParameterf( VLCGL_TARGET, GL_TEXTURE_PRIORITY, 1.0 ); + glTexParameteri( VLCGL_TARGET, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri( VLCGL_TARGET, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + glTexParameteri( VLCGL_TARGET, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( VLCGL_TARGET, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - - glTexParameteri( VLCGL_TARGET, GL_TEXTURE_WRAP_S, GL_CLAMP ); - glTexParameteri( VLCGL_TARGET, GL_TEXTURE_WRAP_T, GL_CLAMP ); - + glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); #ifdef SYS_DARWIN