📄 opengl.c
字号:
/* Set the perpective */ glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glFrustum( -1.0, 1.0, -1.0, 1.0, 3.0, 20.0 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); 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;}/***************************************************************************** * End: terminate GLX video thread output method *****************************************************************************/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 ); }}/***************************************************************************** * Destroy: destroy GLX video thread output method ***************************************************************************** * Terminate an output method created by CreateVout *****************************************************************************/static void DestroyVout( vlc_object_t *p_this ){ vout_thread_t *p_vout = (vout_thread_t *)p_this; vout_sys_t *p_sys = p_vout->p_sys; module_Unneed( p_sys->p_vout, p_sys->p_vout->p_module ); vlc_object_detach( p_sys->p_vout ); vlc_object_destroy( p_sys->p_vout ); /* 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 );}/***************************************************************************** * Manage: handle Sys events ***************************************************************************** * This function should be called regularly by video output thread. It returns * 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; int i_ret, i_fullscreen_change; i_fullscreen_change = ( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE ); p_sys->p_vout->i_changes = p_vout->i_changes; i_ret = p_sys->p_vout->pf_manage( p_sys->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 ) { InitTextures( p_vout ); switch( p_sys->i_effect ) { case OPENGL_EFFECT_CUBE: glEnable( GL_CULL_FACE ); break; case OPENGL_EFFECT_TRANSPARENT_CUBE: glDisable( GL_DEPTH_TEST ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE ); break; } if( p_sys->i_effect & ( OPENGL_EFFECT_CUBE | OPENGL_EFFECT_TRANSPARENT_CUBE ) ) { /* Set the perpective */ glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glFrustum( -1.0, 1.0, -1.0, 1.0, 3.0, 20.0 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); 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;}/***************************************************************************** * Render: render previously calculated output *****************************************************************************/static void Render( vout_thread_t *p_vout, picture_t *p_pic ){ vout_sys_t *p_sys = p_vout->p_sys; /* On Win32/GLX, we do this the usual way: + Fill the buffer with new content, + Reload the texture, + Use the texture. On OS X with VRAM or AGP texturing, the order has to be: + Reload the texture, + Fill the buffer with new content, + Use the texture. (Thanks to gcc from the Arstechnica forums for the tip) Therefore, we have to use two buffers and textures. On Win32/GLX, we reload the texture to be displayed and use it right away. On 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] ); /* 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.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( 0.5 * p_sys->f_speed , 0.3, 0.5, 0.7 ); glEnable( VLCGL_TARGET ); glBegin( GL_QUADS ); /* Front */ 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.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.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.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.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 ); 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 ){ /* Return the nearest power of 2 */ int i_result = 1; while( i_result < i_size ) { i_result *= 2; } return i_result;}/***************************************************************************** * Control: control facility for the vout *****************************************************************************/static int Control( vout_thread_t *p_vout, int i_query, va_list args ){ vout_sys_t *p_sys = p_vout->p_sys; 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 ){ vout_sys_t *p_sys = p_vout->p_sys; int i_index; glDeleteTextures( 2, p_sys->p_textures ); glGenTextures( 2, p_sys->p_textures ); for( i_index = 0; i_index < 2; i_index++ ) { glBindTexture( VLCGL_TARGET, p_sys->p_textures[i_index] ); /* 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 ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );#ifdef SYS_DARWIN /* 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 ); #if 0 /* Use VRAM texturing */ glTexParameteri( VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE );#else /* Use AGP texturing */ glTexParameteri( VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE );#endif#endif /* Call glTexImage2D only once, and use glTexSubImage2D later */ glTexImage2D( VLCGL_TARGET, 0, 3, p_sys->i_tex_width, p_sys->i_tex_height, 0, VLCGL_FORMAT, VLCGL_TYPE, p_sys->pp_buffer[i_index] ); } return 0;}/***************************************************************************** * SendEvents: forward mouse and keyboard events to the parent p_vout *****************************************************************************/static int SendEvents( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *_p_vout ){ return var_Set( (vlc_object_t *)_p_vout, psz_var, newval );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -