Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

glx.c

00001 /*****************************************************************************
00002  * glx.c: GLX OpenGL provider
00003  *****************************************************************************
00004  * Copyright (C) 2004 the VideoLAN team
00005  * $Id: glx.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Cyril Deguet <[email protected]>
00008  *          Gildas Bazin <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 /*****************************************************************************
00026  * Preamble
00027  *****************************************************************************/
00028 #include <errno.h>                                                 /* ENOMEM */
00029 #include <stdlib.h>                                      /* malloc(), free() */
00030 #include <string.h>
00031 
00032 #include <vlc/vlc.h>
00033 #include <vlc/intf.h>
00034 #include <vlc/vout.h>
00035 
00036 #ifdef HAVE_SYS_SHM_H
00037 #   include <sys/shm.h>                                /* shmget(), shmctl() */
00038 #endif
00039 
00040 #include <X11/Xlib.h>
00041 #include <X11/Xmd.h>
00042 #include <X11/Xutil.h>
00043 #include <X11/keysym.h>
00044 #ifdef HAVE_SYS_SHM_H
00045 #   include <X11/extensions/XShm.h>
00046 #endif
00047 #ifdef DPMSINFO_IN_DPMS_H
00048 #   include <X11/extensions/dpms.h>
00049 #endif
00050 
00051 #include <GL/glx.h>
00052 
00053 #include "xcommon.h"
00054 
00055 /* RV16 */
00056 //#define VLCGL_RGB_FORMAT GL_RGB
00057 //#define VLCGL_RGB_TYPE GL_UNSIGNED_SHORT_5_6_5
00058 
00059 /* RV24 */
00060 //#define VLCGL_RGB_FORMAT GL_RGB
00061 //#define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
00062 
00063 /* RV32 */
00064 #define VLCGL_RGB_FORMAT GL_RGBA
00065 #define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
00066 
00067 
00068 /*****************************************************************************
00069  * OpenGL provider interface
00070  *****************************************************************************/
00071 static int  CreateOpenGL ( vlc_object_t * );
00072 static void DestroyOpenGL( vlc_object_t * );
00073 static int  InitOpenGL   ( vout_thread_t * );
00074 static void SwapBuffers  ( vout_thread_t * );
00075 
00076 /*****************************************************************************
00077  * Local prototypes
00078  *****************************************************************************/
00079 static int  CheckGLX     ( vlc_object_t *, vlc_bool_t * );
00080 static int  InitGLX12    ( vout_thread_t * );
00081 static int  InitGLX13    ( vout_thread_t * );
00082 static void SwitchContext( vout_thread_t * );
00083 
00084 /*****************************************************************************
00085  * Module descriptor
00086  *****************************************************************************/
00087 #define ADAPTOR_TEXT N_("XVideo adaptor number")
00088 #define ADAPTOR_LONGTEXT N_( \
00089     "If you graphics card provides several adaptors, this option allows you " \
00090     "to choose which one will be used (you shouldn't have to change this).")
00091 
00092 #define ALT_FS_TEXT N_("Alternate fullscreen method")
00093 #define ALT_FS_LONGTEXT N_( \
00094     "There are two ways to make a fullscreen window, unfortunately each one " \
00095     "has its drawbacks.\n" \
00096     "1) Let the window manager handle your fullscreen window (default), but " \
00097     "things like taskbars will likely show on top of the video.\n" \
00098     "2) Completely bypass the window manager, but then nothing will be able " \
00099     "to show on top of the video.")
00100 
00101 #define DISPLAY_TEXT N_("X11 display name")
00102 #define DISPLAY_LONGTEXT N_( \
00103     "Specify the X11 hardware display you want to use. By default VLC will " \
00104     "use the value of the DISPLAY environment variable.")
00105 
00106 #define SCREEN_TEXT N_("Screen to be used for fullscreen mode.")
00107 #define SCREEN_LONGTEXT N_( \
00108     "Choose the screen you want to use in fullscreen mode. For instance " \
00109     "set it to 0 for first screen, 1 for the second.")
00110 
00111 vlc_module_begin();
00112     set_shortname( "OpenGL" );
00113     set_category( CAT_VIDEO );
00114     set_subcategory( SUBCAT_VIDEO_VOUT );
00115     set_description( _("OpenGL video output") );
00116     set_capability( "opengl provider", 50 );
00117     set_callbacks( CreateOpenGL, DestroyOpenGL );
00118 
00119     add_string( "glx-display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT, VLC_TRUE );
00120     add_integer( "glx-adaptor", -1, NULL, ADAPTOR_TEXT, ADAPTOR_LONGTEXT, VLC_TRUE );
00121     add_bool( "glx-altfullscreen", 0, NULL, ALT_FS_TEXT, ALT_FS_LONGTEXT, VLC_TRUE );
00122 #ifdef HAVE_XINERAMA
00123     add_integer ( "glx-xineramascreen", 0, NULL, SCREEN_TEXT, SCREEN_LONGTEXT, VLC_TRUE );
00124 #endif
00125 vlc_module_end();
00126 
00127 /*****************************************************************************
00128  * Exported prototypes
00129  *****************************************************************************/
00130 extern int  E_(Activate)   ( vlc_object_t * );
00131 extern void E_(Deactivate) ( vlc_object_t * );
00132 
00133 /*****************************************************************************
00134  * CreateOpenGL: initialize an OpenGL provider
00135  *****************************************************************************/
00136 static int CreateOpenGL( vlc_object_t *p_this )
00137 {
00138     vout_thread_t *p_vout = (vout_thread_t *)p_this;
00139     vlc_bool_t b_glx13;
00140 
00141     if( CheckGLX( p_this, &b_glx13 ) != VLC_SUCCESS )
00142     {
00143         msg_Err( p_vout, "no GLX support" );
00144         return VLC_EGENERIC;
00145     }
00146 
00147     if( E_(Activate)( p_this ) != VLC_SUCCESS )
00148     {
00149         return VLC_EGENERIC;
00150     }
00151 
00152     /* Set the function pointer */
00153     p_vout->pf_init = InitOpenGL;
00154     p_vout->pf_swap = SwapBuffers;
00155     p_vout->p_sys->b_glx13 = b_glx13;
00156 
00157     return VLC_SUCCESS;
00158 }
00159 
00160 /*****************************************************************************
00161  * DestroyOpenGL: destroys an OpenGL provider
00162  *****************************************************************************/
00163 static void DestroyOpenGL( vlc_object_t *p_this )
00164 {
00165     vout_thread_t *p_vout = (vout_thread_t *)p_this;
00166     vout_sys_t *p_sys = p_vout->p_sys;
00167 
00168     glXDestroyContext( p_sys->p_display, p_sys->gwctx );
00169     if( p_sys->b_glx13 )
00170     {
00171         glXDestroyWindow( p_sys->p_display, p_sys->gwnd );
00172     }
00173 
00174     E_(Deactivate)( p_this );
00175 }
00176 
00177 /*****************************************************************************
00178  * OpenDisplay: open and initialize OpenGL device
00179  *****************************************************************************/
00180 static int CheckGLX( vlc_object_t *p_this, vlc_bool_t *b_glx13 )
00181 {
00182     Display *p_display = NULL;
00183     int i_opcode, i_evt, i_err = 0;
00184     int i_maj, i_min = 0;
00185 
00186     /* Open the display */
00187     p_display = XOpenDisplay( NULL );
00188     if( p_display == NULL )
00189     {
00190         msg_Err( p_this, "Cannot open display" );
00191         return VLC_EGENERIC;
00192     }
00193 
00194     /* Check for GLX extension */
00195     if( !XQueryExtension( p_display, "GLX", &i_opcode, &i_evt, &i_err ) )
00196     {
00197         msg_Err( p_this, "GLX extension not supported" );
00198         XCloseDisplay( p_display );
00199         return VLC_EGENERIC;
00200     }
00201     if( !glXQueryExtension( p_display, &i_err, &i_evt ) )
00202     {
00203         msg_Err( p_this, "glXQueryExtension failed" );
00204         XCloseDisplay( p_display );
00205         return VLC_EGENERIC;
00206     }
00207 
00208     /* Check GLX version */
00209     if (!glXQueryVersion( p_display, &i_maj, &i_min ) )
00210     {
00211         msg_Err( p_this, "glXQueryVersion failed" );
00212         XCloseDisplay( p_display );
00213         return VLC_EGENERIC;
00214     }
00215     if( i_maj <= 0 || ((i_maj == 1) && (i_min < 3)) )
00216     {
00217         *b_glx13 = VLC_FALSE;
00218         msg_Dbg( p_this, "Using GLX 1.2 API" );
00219     }
00220     else
00221     {
00222         *b_glx13 = VLC_TRUE;
00223         msg_Dbg( p_this, "Using GLX 1.3 API" );
00224     }
00225 
00226     XCloseDisplay( p_display );
00227     return VLC_SUCCESS;
00228 }
00229 
00230 /*****************************************************************************
00231  * InitOpenGL: initializes OpenGL provider
00232  *****************************************************************************/
00233 static int InitOpenGL( vout_thread_t *p_vout )
00234 {
00235     /* Initialize GLX */
00236     if( !p_vout->p_sys->b_glx13 )
00237     {
00238         if( InitGLX12( p_vout ) != VLC_SUCCESS )
00239         {
00240             return VLC_EGENERIC;
00241         }
00242     }
00243     else
00244     {
00245         if( InitGLX13( p_vout ) != VLC_SUCCESS )
00246         {
00247             return VLC_EGENERIC;
00248         }
00249     }
00250 
00251     /* Set the OpenGL context _for the current thread_ */
00252     SwitchContext( p_vout );
00253 
00254     return VLC_SUCCESS;
00255 }
00256 
00257 int InitGLX12( vout_thread_t *p_vout )
00258 {
00259     vout_sys_t *p_sys = p_vout->p_sys;
00260     XVisualInfo *p_vi;
00261     int p_attr[] = { GLX_RGBA, GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 5,
00262                      GLX_BLUE_SIZE, 5, GLX_DOUBLEBUFFER, 0 };
00263 
00264     p_vi = glXChooseVisual( p_sys->p_display,
00265                             DefaultScreen( p_sys->p_display), p_attr );
00266     if(! p_vi )
00267     {
00268         msg_Err( p_vout, "Cannot get GLX 1.2 visual" );
00269         return VLC_EGENERIC;
00270     }
00271 
00272     /* Create an OpenGL context */
00273     p_sys->gwctx = glXCreateContext( p_sys->p_display, p_vi, 0, True );
00274     XFree( p_vi );
00275     if( !p_sys->gwctx )
00276     {
00277         msg_Err( p_vout, "Cannot create OpenGL context");
00278         return VLC_EGENERIC;
00279     }
00280 
00281     return VLC_SUCCESS;
00282 }
00283 
00284 int InitGLX13( vout_thread_t *p_vout )
00285 {
00286     vout_sys_t *p_sys = p_vout->p_sys;
00287     int i_nbelem;
00288     GLXFBConfig *p_fbconfs, fbconf;
00289     XVisualInfo *p_vi;
00290     int p_attr[] = { GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 5,
00291                      GLX_BLUE_SIZE, 5, GLX_DOUBLEBUFFER, True,
00292                      GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, 0 };
00293 
00294     /* Get the FB configuration */
00295     p_fbconfs = glXChooseFBConfig( p_sys->p_display, 0, p_attr, &i_nbelem );
00296     if( (i_nbelem <= 0) || !p_fbconfs )
00297     {
00298         msg_Err( p_vout, "Cannot get FB configurations");
00299         if( p_fbconfs ) XFree( p_fbconfs );
00300         return VLC_EGENERIC;
00301     }
00302     fbconf = p_fbconfs[0];
00303 
00304     /* Get the X11 visual */
00305     p_vi = glXGetVisualFromFBConfig( p_sys->p_display, fbconf );
00306     if( !p_vi )
00307     {
00308         msg_Err( p_vout, "Cannot get X11 visual" );
00309         XFree( p_fbconfs );
00310         return VLC_EGENERIC;
00311     }
00312     XFree( p_vi );
00313 
00314     /* Create the GLX window */
00315     p_sys->gwnd = glXCreateWindow( p_sys->p_display, fbconf,
00316                                    p_sys->p_win->video_window, NULL );
00317     if( p_sys->gwnd == None )
00318     {
00319         msg_Err( p_vout, "Cannot create GLX window" );
00320         return VLC_EGENERIC;
00321     }
00322 
00323     /* Create an OpenGL context */
00324     p_sys->gwctx = glXCreateNewContext( p_sys->p_display, fbconf,
00325                                         GLX_RGBA_TYPE, NULL, True );
00326     XFree( p_fbconfs );
00327     if( !p_sys->gwctx )
00328     {
00329         msg_Err( p_vout, "Cannot create OpenGL context");
00330         return VLC_EGENERIC;
00331     }
00332 
00333     return VLC_SUCCESS;
00334 }
00335 
00336 /*****************************************************************************
00337  * SwapBuffers: swap front/back buffers
00338  *****************************************************************************/
00339 static void SwapBuffers( vout_thread_t *p_vout )
00340 {
00341     vout_sys_t *p_sys = p_vout->p_sys;
00342     int i_width, i_height, i_x, i_y;
00343 
00344     vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
00345                        p_vout->p_sys->p_win->i_height,
00346                        &i_x, &i_y, &i_width, &i_height );
00347 
00348     glViewport( 0, 0, (GLint)i_width, (GLint)i_height );
00349 
00350     if( p_sys->b_glx13 )
00351     {
00352         glXSwapBuffers( p_sys->p_display, p_sys->gwnd );
00353     }
00354     else
00355     {
00356         glXSwapBuffers( p_sys->p_display, p_sys->p_win->video_window );
00357     }
00358 }
00359 
00360 void SwitchContext( vout_thread_t *p_vout )
00361 {
00362     vout_sys_t *p_sys = p_vout->p_sys;
00363 
00364     /* Change the current OpenGL context */
00365     if( p_sys->b_glx13 )
00366     {
00367         glXMakeContextCurrent( p_sys->p_display, p_sys->gwnd,
00368                                p_sys->gwnd, p_sys->gwctx );
00369     }
00370     else
00371     {
00372         glXMakeCurrent( p_sys->p_display, p_sys->p_win->video_window,
00373                         p_sys->gwctx );
00374     }
00375 }

Generated on Tue Dec 20 10:14:55 2005 for vlc-0.8.4a by  doxygen 1.4.2