1 /*****************************************************************************
2 * glx.c: GLX OpenGL provider
3 *****************************************************************************
4 * Copyright (C) 2004 the VideoLAN team
7 * Authors: Cyril Deguet <asmax@videolan.org>
8 * Gildas Bazin <gbazin@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
33 #include <errno.h> /* ENOMEM */
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_interface.h>
42 #include <X11/Xutil.h>
43 #include <X11/keysym.h>
44 #ifdef DPMSINFO_IN_DPMS_H
45 # include <X11/extensions/dpms.h>
53 //#define VLCGL_RGB_FORMAT GL_RGB
54 //#define VLCGL_RGB_TYPE GL_UNSIGNED_SHORT_5_6_5
57 //#define VLCGL_RGB_FORMAT GL_RGB
58 //#define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
61 #define VLCGL_RGB_FORMAT GL_RGBA
62 #define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
65 /*****************************************************************************
66 * OpenGL provider interface
67 *****************************************************************************/
68 static int CreateOpenGL ( vlc_object_t * );
69 static void DestroyOpenGL( vlc_object_t * );
70 static int InitOpenGL ( vout_thread_t * );
71 static void SwapBuffers ( vout_thread_t * );
73 /*****************************************************************************
75 *****************************************************************************/
76 static int InitGLX12 ( vout_thread_t * );
77 static int InitGLX13 ( vout_thread_t * );
78 static void SwitchContext( vout_thread_t * );
80 /*****************************************************************************
82 *****************************************************************************/
83 #define DISPLAY_TEXT N_("X11 display")
84 #define DISPLAY_LONGTEXT N_( \
85 "X11 hardware display to use. By default VLC will " \
86 "use the value of the DISPLAY environment variable.")
88 #define SHM_TEXT N_("Use shared memory")
89 #define SHM_LONGTEXT N_( \
90 "Use shared memory to communicate between VLC and the X server.")
93 set_shortname( "OpenGL(GLX)" )
94 set_category( CAT_VIDEO )
95 set_subcategory( SUBCAT_VIDEO_VOUT )
96 set_description( N_("OpenGL(GLX) provider") )
97 set_capability( "opengl provider", 50 )
98 set_callbacks( CreateOpenGL, DestroyOpenGL )
100 add_string( "glx-display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT, true )
101 add_obsolete_integer( "glx-adaptor" ) /* Deprecated since 1.0.4 */
102 #ifdef HAVE_SYS_SHM_H
103 add_bool( "glx-shm", true, NULL, SHM_TEXT, SHM_LONGTEXT, true )
107 /*****************************************************************************
108 * Exported prototypes
109 *****************************************************************************/
110 extern int Activate ( vlc_object_t * );
111 extern void Deactivate ( vlc_object_t * );
113 /*****************************************************************************
114 * CreateOpenGL: initialize an OpenGL provider
115 *****************************************************************************/
116 static int CreateOpenGL( vlc_object_t *p_this )
118 vout_thread_t *p_vout = (vout_thread_t *)p_this;
120 if( Activate( p_this ) != VLC_SUCCESS )
125 /* Set the function pointer */
126 p_vout->pf_init = InitOpenGL;
127 p_vout->pf_swap = SwapBuffers;
132 /*****************************************************************************
133 * DestroyOpenGL: destroys an OpenGL provider
134 *****************************************************************************/
135 static void DestroyOpenGL( vlc_object_t *p_this )
137 vout_thread_t *p_vout = (vout_thread_t *)p_this;
138 vout_sys_t *p_sys = p_vout->p_sys;
140 glXDestroyContext( p_sys->p_display, p_sys->gwctx );
143 glXDestroyWindow( p_sys->p_display, p_sys->gwnd );
146 Deactivate( p_this );
149 /*****************************************************************************
150 * InitOpenGL: initializes OpenGL provider
151 *****************************************************************************/
152 static int InitOpenGL( vout_thread_t *p_vout )
155 if( !p_vout->p_sys->b_glx13 )
157 if( InitGLX12( p_vout ) != VLC_SUCCESS )
164 if( InitGLX13( p_vout ) != VLC_SUCCESS )
170 /* Set the OpenGL context _for the current thread_ */
171 SwitchContext( p_vout );
176 int InitGLX12( vout_thread_t *p_vout )
178 vout_sys_t *p_sys = p_vout->p_sys;
180 int p_attr[] = { GLX_RGBA, GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 5,
181 GLX_BLUE_SIZE, 5, GLX_DOUBLEBUFFER, 0 };
183 p_vi = glXChooseVisual( p_sys->p_display,
184 DefaultScreen( p_sys->p_display), p_attr );
187 msg_Err( p_vout, "Cannot get GLX 1.2 visual" );
191 /* Create an OpenGL context */
192 p_sys->gwctx = glXCreateContext( p_sys->p_display, p_vi, 0, True );
196 msg_Err( p_vout, "Cannot create OpenGL context");
203 int InitGLX13( vout_thread_t *p_vout )
205 vout_sys_t *p_sys = p_vout->p_sys;
206 int i_nb, ret = VLC_EGENERIC;
207 GLXFBConfig *p_fbconfs = NULL, fbconf = NULL;
208 XWindowAttributes att;
209 static const int p_attr[] = {
210 GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 5, GLX_BLUE_SIZE, 5,
211 GLX_DOUBLEBUFFER, True, GLX_X_RENDERABLE, True,
212 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
216 /* Get the FB configuration */
217 p_fbconfs = glXChooseFBConfig( p_sys->p_display, p_sys->i_screen, p_attr, &i_nb );
218 if( p_fbconfs == NULL )
220 msg_Err( p_vout, "Cannot get FB configurations");
224 /* We should really create the window _after_ the frame buffer
225 * configuration was chosen, instead of selecting the frame buffer from
226 * the window. That requires reworking xcommon.c though.
228 XGetWindowAttributes( p_sys->p_display, p_sys->window.video_window, &att );
229 for( int i = 0; i < i_nb && !fbconf; i++ )
233 /* Get the X11 visual */
234 p_vi = glXGetVisualFromFBConfig( p_sys->p_display, p_fbconfs[i] );
238 if( p_vi->visualid == att.visual->visualid )
239 fbconf = p_fbconfs[i];
244 msg_Err( p_vout, "Cannot find matching frame buffer" );
248 /* Create the GLX window */
249 p_sys->gwnd = glXCreateWindow( p_sys->p_display, fbconf,
250 p_sys->window.video_window, NULL );
251 if( p_sys->gwnd == None )
253 msg_Err( p_vout, "Cannot create GLX window" );
257 /* Create an OpenGL context */
258 p_sys->gwctx = glXCreateNewContext( p_sys->p_display, fbconf,
259 GLX_RGBA_TYPE, NULL, True );
261 msg_Err( p_vout, "Cannot create OpenGL context");
270 /*****************************************************************************
271 * SwapBuffers: swap front/back buffers
272 *****************************************************************************/
273 static void SwapBuffers( vout_thread_t *p_vout )
275 vout_sys_t *p_sys = p_vout->p_sys;
276 unsigned int i_width, i_height, i_x, i_y;
278 vout_PlacePicture( p_vout, p_vout->p_sys->window.i_width,
279 p_vout->p_sys->window.i_height,
280 &i_x, &i_y, &i_width, &i_height );
282 glViewport( 0, 0, (GLint)i_width, (GLint)i_height );
286 glXSwapBuffers( p_sys->p_display, p_sys->gwnd );
290 glXSwapBuffers( p_sys->p_display, p_sys->window.video_window );
294 void SwitchContext( vout_thread_t *p_vout )
296 vout_sys_t *p_sys = p_vout->p_sys;
298 /* Change the current OpenGL context */
301 glXMakeContextCurrent( p_sys->p_display, p_sys->gwnd,
302 p_sys->gwnd, p_sys->gwctx );
306 glXMakeCurrent( p_sys->p_display, p_sys->window.video_window,