1098b3bd2f6874aa28ba9a613d9098b5d87b7460
[vlc.git] / modules / video_output / x11 / glx.c
1 /*****************************************************************************
2  * glx.c: GLX video output
3  *****************************************************************************
4  * Copyright (C) 2004 VideoLAN
5  * $Id$
6  *
7  * Authors: Cyril Deguet <asmax@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <errno.h>                                                 /* ENOMEM */
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/intf.h>
33 #include <vlc/vout.h>
34
35 #include <X11/Xlib.h>
36 #include <X11/Xutil.h>
37 #include <GL/glx.h>
38
39 /*****************************************************************************
40  * Local prototypes
41  *****************************************************************************/
42 static int  Create      ( vlc_object_t * );
43 static void Destroy     ( vlc_object_t * );
44
45 static int  Init        ( vout_thread_t * );
46 static void End         ( vout_thread_t * );
47 static int  Manage      ( vout_thread_t * );
48 static void Render      ( vout_thread_t *p_vout, picture_t *p_pic );
49 static void DisplayVideo( vout_thread_t *, picture_t * );
50
51 static int  OpenDisplay ( vout_thread_t * );
52 static void CloseDisplay( vout_thread_t * );
53 static int  InitGLX12   ( vout_thread_t *p_vout );
54 static int  InitGLX13   ( vout_thread_t *p_vout );
55 static void CreateWindow( vout_thread_t *p_vout, XVisualInfo *p_vi );
56 static void SwitchContext( vout_thread_t *p_vout );
57
58 static inline int GetAlignedSize( int i_size );
59
60 #define MAX_TEXTURE_SIZE 512
61
62 /*****************************************************************************
63  * Module descriptor
64  *****************************************************************************/
65 vlc_module_begin();
66     set_description( _("X11 OpenGL (GLX) video output") );
67     set_capability( "video output", 20 );
68     add_shortcut( "glx" );
69     set_callbacks( Create, Destroy );
70 vlc_module_end();
71
72 /*****************************************************************************
73  * vout_sys_t: GLX video output method descriptor
74  *****************************************************************************
75  * This structure is part of the video output thread descriptor.
76  * It describes the GLX specific properties of an output thread.
77  *****************************************************************************/
78 struct vout_sys_t
79 {
80     uint8_t     *p_buffer;
81     int         i_index;
82
83     int         i_width;
84     int         i_height;
85     int         b_fullscreen;
86
87     Display     *p_display;
88     int         b_glx13;
89     GLXContext  gwctx;
90     Window      wnd;
91     GLXWindow   gwnd;
92     Atom        wm_delete;
93
94     GLuint      texture;
95
96     int         i_effect; //XXX
97 };
98
99 #define MWM_HINTS_DECORATIONS   (1L << 1)
100 #define PROP_MWM_HINTS_ELEMENTS 5
101 typedef struct mwmhints_t
102 {
103     uint32_t flags;
104     uint32_t functions;
105     uint32_t decorations;
106     int32_t  input_mode;
107     uint32_t status;
108 } mwmhints_t;
109
110
111 /*****************************************************************************
112  * Create: allocates GLX video thread output method
113  *****************************************************************************
114  * This function allocates and initializes a GLX vout method.
115  *****************************************************************************/
116 static int Create( vlc_object_t *p_this )
117 {
118     vout_thread_t *p_vout = (vout_thread_t *)p_this;
119
120     /* Allocate structure */
121     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
122     if( p_vout->p_sys == NULL )
123     {
124         msg_Err( p_vout, "out of memory" );
125         return( 1 );
126     }
127     
128     //XXX set to 0 to disable the cube effect
129     p_vout->p_sys->i_effect = 1;
130
131    /* p_vout->p_sys->i_width = p_vout->i_window_width;
132     p_vout->p_sys->i_height = p_vout->i_window_height; */
133     p_vout->p_sys->i_width = 700;
134     p_vout->p_sys->i_height = 700;
135
136     p_vout->p_sys->b_fullscreen = 0;
137
138     /* A texture must have a size aligned on a power of 2 */
139     p_vout->output.i_width  = GetAlignedSize( p_vout->render.i_width );
140     p_vout->output.i_height = GetAlignedSize( p_vout->render.i_height );
141     p_vout->output.i_aspect = p_vout->render.i_aspect;
142
143     msg_Dbg( p_vout, "Texture size: %dx%d",  p_vout->output.i_width,
144              p_vout->output.i_height );
145
146     /* Open and initialize device */
147     if( OpenDisplay( p_vout ) )
148     {
149         msg_Err( p_vout, "cannot open display" );
150         free( p_vout->p_sys );
151         return( 1 );
152     }
153
154     p_vout->pf_init = Init;
155     p_vout->pf_end = End;
156     p_vout->pf_manage = Manage;
157     p_vout->pf_render = Render;
158     p_vout->pf_display = DisplayVideo;
159
160     return( 0 );
161 }
162
163 /*****************************************************************************
164  * Init: initialize GLX video thread output method
165  *****************************************************************************/
166 static int Init( vout_thread_t *p_vout )
167 {
168     int i_index;
169     picture_t *p_pic;
170
171     /* No YUV textures :( */
172     p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
173     p_vout->output.i_rmask = 0x000000ff;
174     p_vout->output.i_gmask = 0x0000ff00;
175     p_vout->output.i_bmask = 0x00ff0000;
176
177     I_OUTPUTPICTURES = 0;
178
179     p_pic = NULL;
180
181     /* Find an empty picture slot */
182     for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
183     {
184         if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
185         {
186             p_pic = p_vout->p_picture + i_index;
187             break;
188         }
189     }
190
191     if( p_pic == NULL )
192     {
193         return -1;
194     }
195
196    /* We know the chroma, allocate a buffer which will be used
197      * directly by the decoder */
198     p_pic->i_planes = 1;
199
200     p_pic->p->p_pixels = p_vout->p_sys->p_buffer;
201     p_pic->p->i_lines = p_vout->output.i_height;
202     p_pic->p->i_pitch = p_vout->output.i_width * 4;
203     p_pic->p->i_pixel_pitch = 4;
204     p_pic->p->i_visible_pitch = p_vout->output.i_width * 4;
205
206     p_pic->i_status = DESTROYED_PICTURE;
207     p_pic->i_type   = DIRECT_PICTURE;
208
209     PP_OUTPUTPICTURE[ 0 ] = p_pic;
210
211     I_OUTPUTPICTURES = 1;
212
213     SwitchContext( p_vout );
214
215     /* Set the texture parameters */
216     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
217     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
218
219     if( p_vout->p_sys->i_effect )
220     {
221         glEnable( GL_CULL_FACE);
222         /*glDisable( GL_DEPTH_TEST );
223         glEnable( GL_BLEND );
224         glBlendFunc( GL_SRC_ALPHA, GL_ONE );*/
225
226         /* Set the perpective */
227         glMatrixMode( GL_PROJECTION );
228         glLoadIdentity();
229         glFrustum( -1.0, 1.0, -1.0, 1.0, 3.0, 20.0 );
230         glMatrixMode( GL_MODELVIEW );
231         glLoadIdentity();
232         glTranslatef( 0.0, 0.0, - 5.0 );
233     }
234
235     return 0;
236 }
237
238 /*****************************************************************************
239  * End: terminate GLX video thread output method
240  *****************************************************************************/
241 static void End( vout_thread_t *p_vout )
242 {
243     ;
244 }
245
246 /*****************************************************************************
247  * Destroy: destroy GLX video thread output method
248  *****************************************************************************
249  * Terminate an output method created by Create
250  *****************************************************************************/
251 static void Destroy( vlc_object_t *p_this )
252 {
253     vout_thread_t *p_vout = (vout_thread_t *)p_this;
254
255     CloseDisplay( p_vout );
256
257     /* Free the texture buffer*/
258     if( p_vout->p_sys->p_buffer )
259     {
260         free( p_vout->p_sys->p_buffer );
261     }
262
263     free( p_vout->p_sys );
264 }
265
266 /*****************************************************************************
267  * Manage: handle X11 events
268  *****************************************************************************
269  * This function should be called regularly by video output thread. It manages
270  * console events. It returns a non null value on error.
271  *****************************************************************************/
272 static int Manage( vout_thread_t *p_vout )
273 {
274     Display *p_display;
275
276     p_display = p_vout->p_sys->p_display;
277
278     /* loop on X11 events */
279     while( XPending( p_display ) > 0 )
280     {
281         XEvent evt;
282         XNextEvent( p_display, &evt );
283         switch( evt.type )
284         {
285             case ClientMessage:
286             {
287                 /* Delete notification */
288                 if( (evt.xclient.format == 32) &&
289                     ((Atom)evt.xclient.data.l[0] == p_vout->p_sys->wm_delete) )
290                 {
291                     /* the user wants to close the window */
292                     playlist_t * p_playlist =
293                         (playlist_t *)vlc_object_find( p_vout, VLC_OBJECT_PLAYLIST,
294                                                        FIND_ANYWHERE );
295                     if( p_playlist != NULL )
296                     {
297                         playlist_Stop( p_playlist );
298                         vlc_object_release( p_playlist );
299                     }
300                 }
301                 break;
302             }
303         }
304     }
305     return 0;
306 }
307
308 /*****************************************************************************
309  * Render: render previously calculated output
310  *****************************************************************************/
311 static void Render( vout_thread_t *p_vout, picture_t *p_pic )
312 {
313     glClear(GL_COLOR_BUFFER_BIT);
314     glTexImage2D (GL_TEXTURE_2D, 0, 3, p_vout->output.i_width,
315                   p_vout->output.i_height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
316                   p_vout->p_sys->p_buffer);
317
318     if( !p_vout->p_sys->i_effect )
319     {
320         glEnable( GL_TEXTURE_2D);
321         glBegin( GL_POLYGON);
322         glTexCoord2f(0.0,0.0); glVertex2f(-1.0,1.0);
323         glTexCoord2f(1.0,0.0); glVertex2f(1.0,1.0);
324         glTexCoord2f(1.0,1.0); glVertex2f(1.0,-1.0);
325         glTexCoord2f(0.0,1.0); glVertex2f(-1.0,-1.0);
326         glEnd();
327     }
328     else
329     {
330         glRotatef( 2.0, 3.3, 1.5, 2.7 );
331
332         glEnable( GL_TEXTURE_2D);
333         glBegin( GL_QUADS );
334         /* Front */
335         glTexCoord2f( 0.0, 0.0 );
336         glVertex3f( - 1.0, 1.0, 1.0 );
337         glTexCoord2f( 0.0, 1.0 );
338         glVertex3f( - 1.0, - 1.0, 1.0 );
339         glTexCoord2f( 1.0,
340                       1.0 );
341         glVertex3f( 1.0, - 1.0, 1.0 );
342         glTexCoord2f( 1.0, 0.0 );
343         glVertex3f( 1.0, 1.0, 1.0 );
344
345         /* Left */
346         glTexCoord2f( 0.0, 0.0 );
347         glVertex3f( - 1.0, 1.0, - 1.0 );
348         glTexCoord2f( 0.0, 1.0 );
349         glVertex3f( - 1.0, - 1.0, - 1.0 );
350         glTexCoord2f( 1.0,
351                       1.0 );
352         glVertex3f( - 1.0, - 1.0, 1.0 );
353         glTexCoord2f( 1.0, 0.0 );
354         glVertex3f( - 1.0, 1.0, 1.0 );
355
356         /* Back */
357         glTexCoord2f( 0.0, 0.0 );
358         glVertex3f( 1.0, 1.0, - 1.0 );
359         glTexCoord2f( 0.0, 1.0 );
360         glVertex3f( 1.0, - 1.0, - 1.0 );
361         glTexCoord2f( 1.0,
362                       1.0 );
363         glVertex3f( - 1.0, - 1.0, - 1.0 );
364         glTexCoord2f( 1.0, 0.0 );
365         glVertex3f( - 1.0, 1.0, - 1.0 );
366
367         /* Right */
368         glTexCoord2f( 0.0, 0.0 );
369         glVertex3f( 1.0, 1.0, 1.0 );
370         glTexCoord2f( 0.0, 1.0 );
371         glVertex3f( 1.0, - 1.0, 1.0 );
372         glTexCoord2f( 1.0,
373                       1.0 );
374         glVertex3f( 1.0, - 1.0, - 1.0 );
375         glTexCoord2f( 1.0, 0.0 );
376         glVertex3f( 1.0, 1.0, - 1.0 );
377
378         /* Top */
379         glTexCoord2f( 0.0, 0.0 );
380         glVertex3f( - 1.0, 1.0, - 1.0 );
381         glTexCoord2f( 0.0, 1.0 );
382         glVertex3f( - 1.0, 1.0, 1.0 );
383         glTexCoord2f( 1.0,
384                       1.0 );
385         glVertex3f( 1.0, 1.0, 1.0 );
386         glTexCoord2f( 1.0, 0.0 );
387         glVertex3f( 1.0, 1.0, - 1.0 );
388
389         /* Bottom */
390         glTexCoord2f( 0.0, 0.0 );
391         glVertex3f( - 1.0, - 1.0, 1.0 );
392         glTexCoord2f( 0.0, 1.0 );
393         glVertex3f( - 1.0, - 1.0, - 1.0 );
394         glTexCoord2f( 1.0,
395                       1.0 );
396         glVertex3f( 1.0, - 1.0, - 1.0 );
397         glTexCoord2f( 1.0, 0.0 );
398         glVertex3f( 1.0, - 1.0, 1.0 );
399         glEnd();
400     }
401     glDisable( GL_TEXTURE_2D);
402     
403   
404 }
405
406 /*****************************************************************************
407  * DisplayVideo: displays previously rendered output
408  *****************************************************************************/
409 static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
410 {
411     if( p_vout->p_sys->b_glx13 )
412     {
413         glXSwapBuffers( p_vout->p_sys->p_display, p_vout->p_sys->gwnd );
414     }
415     else
416     {
417         glXSwapBuffers( p_vout->p_sys->p_display, p_vout->p_sys->wnd );
418     }
419
420 }
421
422 /* following functions are local */
423
424 /*****************************************************************************
425  * OpenDisplay: open and initialize OpenGL device
426  *****************************************************************************/
427
428 static int OpenDisplay( vout_thread_t *p_vout )
429 {
430     Display *p_display;
431     int i_opcode, i_evt, i_err;
432     int i_maj, i_min;
433
434     /* Open the display */
435     p_vout->p_sys->p_display = p_display = XOpenDisplay( NULL );
436     if( !p_display )
437     {
438         msg_Err( p_vout, "Cannot open display" );
439         return -1;
440     }
441
442     /* Check for GLX extension */
443     if( !XQueryExtension( p_display, "GLX", &i_opcode, &i_evt, &i_err ) )
444     {
445         msg_Err( p_vout, "GLX extension not supported" );
446         return -1;
447     }
448     if( !glXQueryExtension( p_display, &i_err, &i_evt ) )
449     {
450         msg_Err( p_vout, "glXQueryExtension failed" );
451         return -1;
452     }
453
454     /* Check GLX version */
455     if (!glXQueryVersion( p_display, &i_maj, &i_min ) )
456     {
457         msg_Err( p_vout, "glXQueryVersion failed" );
458         return -1;
459     }
460     if( i_maj <= 0 || ((i_maj == 1) && (i_min < 3)) )
461     {
462         p_vout->p_sys->b_glx13 = 0;
463         msg_Dbg( p_vout, "Using GLX 1.2 API" );
464         if( InitGLX12( p_vout ) == -1 )
465         {
466             return -1;
467         }
468     }
469     else
470     {
471         p_vout->p_sys->b_glx13 = 1;
472         msg_Dbg( p_vout, "Using GLX 1.3 API" );
473         if( InitGLX13( p_vout ) == -1 )
474         {
475             return -1;
476         }
477     }
478
479     XMapWindow( p_display, p_vout->p_sys->wnd );
480     if( p_vout->p_sys->b_fullscreen )
481     {
482         //XXX
483         XMoveWindow( p_display, p_vout->p_sys->wnd, 0, 0 );
484     }
485     XFlush( p_display );
486
487     /* Allocate the texture buffer */
488     p_vout->p_sys->p_buffer =
489         malloc( p_vout->output.i_width * p_vout->output.i_height * 4 );
490     if( !p_vout->p_sys->p_buffer )
491     {
492         msg_Err( p_vout, "Out of memory" );
493         return -1;
494     }
495     return 0;
496 }
497
498 /*****************************************************************************
499  * CloseDisplay: close and reset OpenGL device
500  *****************************************************************************
501  * Returns all resources allocated by OpenDisplay and restore the original
502  * state of the device.
503  *****************************************************************************/
504 static void CloseDisplay( vout_thread_t *p_vout )
505 {
506     Display *p_display;
507
508     glFlush();
509
510     p_display = p_vout->p_sys->p_display;
511     glXDestroyContext( p_display, p_vout->p_sys->gwctx );
512     if( p_vout->p_sys->b_glx13 )
513     {
514         glXDestroyWindow( p_display, p_vout->p_sys->gwnd );
515     }
516     XDestroyWindow( p_display, p_vout->p_sys->wnd );
517     XCloseDisplay( p_display );
518
519 }
520
521
522 int InitGLX12( vout_thread_t *p_vout )
523 {
524     Display *p_display;
525     XVisualInfo *p_vi;
526     GLXContext gwctx;
527     int p_attr[] = { GLX_RGBA, GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 5,
528                      GLX_BLUE_SIZE, 5, GLX_DOUBLEBUFFER,
529                      0 };
530
531     p_display = p_vout->p_sys->p_display;
532
533     p_vi = glXChooseVisual( p_display, DefaultScreen( p_display), p_attr );
534     if(! p_vi )
535     {
536         msg_Err( p_vout, "Cannot get GLX 1.2 visual" );
537         return -1;
538     }
539
540     /* Create the window */
541     CreateWindow( p_vout, p_vi );
542
543      /* Create an OpenGL context */
544     p_vout->p_sys->gwctx = gwctx = glXCreateContext( p_display, p_vi, 0, True );
545     if( !gwctx )
546     {
547         msg_Err( p_vout, "Cannot create OpenGL context");
548         XFree( p_vi );
549         return -1;
550     }
551     XFree( p_vi );
552
553     return 0;
554 }
555
556
557 int InitGLX13( vout_thread_t *p_vout )
558 {
559     Display *p_display;
560     int i_nbelem;
561     GLXFBConfig *p_fbconfs, fbconf;
562     XVisualInfo *p_vi;
563     GLXContext gwctx;
564     int p_attr[] = { GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 5,
565                      GLX_BLUE_SIZE, 5, GLX_DOUBLEBUFFER, True,
566                      GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, 0 };
567
568     p_display = p_vout->p_sys->p_display;
569
570     /* Get the FB configuration */
571     p_fbconfs = glXChooseFBConfig( p_display, 0, p_attr, &i_nbelem );
572     if( (i_nbelem <= 0) || !p_fbconfs )
573     {
574         msg_Err( p_vout, "Cannot get FB configurations");
575         if( p_fbconfs )
576         {
577             XFree( p_fbconfs );
578         }
579         return -1;
580     }
581     fbconf = p_fbconfs[0];
582
583     /* Get the X11 visual */
584     p_vi = glXGetVisualFromFBConfig( p_display, fbconf );
585     if( !p_vi )
586     {
587         msg_Err( p_vout, "Cannot get X11 visual" );
588         XFree( p_fbconfs );
589         return -1;
590     }
591
592     /* Create the window */
593     CreateWindow( p_vout, p_vi );
594
595     XFree( p_vi );
596
597     /* Create the GLX window */
598     p_vout->p_sys->gwnd = glXCreateWindow( p_display, fbconf, p_vout->p_sys->wnd, NULL );
599     if( p_vout->p_sys->gwnd == None )
600     {
601         msg_Err( p_vout, "Cannot create GLX window" );
602         return -1;
603     }
604
605     /* Create an OpenGL context */
606     p_vout->p_sys->gwctx = gwctx = glXCreateNewContext( p_display, fbconf,
607                                                   GLX_RGBA_TYPE, NULL, True );
608     if( !gwctx )
609     {
610         msg_Err( p_vout, "Cannot create OpenGL context");
611         XFree( p_fbconfs );
612         return -1;
613     }
614     XFree( p_fbconfs );
615
616     return 0;
617 }
618
619
620
621 void CreateWindow( vout_thread_t *p_vout, XVisualInfo *p_vi )
622 {
623     Display *p_display;
624     XSetWindowAttributes xattr;
625     Window wnd;
626     Colormap cm;
627     XSizeHints* p_size_hints;
628     Atom prop;
629     mwmhints_t mwmhints;
630
631     p_display = p_vout->p_sys->p_display;
632
633     /* Create a colormap */
634     cm = XCreateColormap( p_display, RootWindow( p_display, p_vi->screen ),
635                           p_vi->visual, AllocNone );
636
637     /* Create the window */
638     xattr.background_pixel = BlackPixel( p_display, DefaultScreen(p_display) );
639     xattr.border_pixel = 0;
640     xattr.colormap = cm;
641     p_vout->p_sys->wnd = wnd = XCreateWindow( p_display, DefaultRootWindow(p_display),
642             0, 0, p_vout->p_sys->i_width, p_vout->p_sys->i_height, 0, p_vi->depth,
643             InputOutput, p_vi->visual,
644             CWBackPixel | CWBorderPixel | CWColormap, &xattr);
645
646     /* Allow the window to be deleted by the window manager */
647     p_vout->p_sys->wm_delete = XInternAtom( p_display, "WM_DELETE_WINDOW", False );
648     XSetWMProtocols( p_display, wnd, &p_vout->p_sys->wm_delete, 1 );
649
650     if( p_vout->p_sys->b_fullscreen )
651     {
652         mwmhints.flags = MWM_HINTS_DECORATIONS;
653         mwmhints.decorations = False;
654
655         prop = XInternAtom( p_display, "_MOTIF_WM_HINTS", False );
656         XChangeProperty( p_display, wnd, prop, prop, 32, PropModeReplace,
657                          (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS );
658     }
659     else
660     {
661         /* Prevent the window from being resized */
662         p_size_hints = XAllocSizeHints();
663         p_size_hints->flags = PMinSize | PMaxSize;
664         p_size_hints->min_width = p_vout->p_sys->i_width;
665         p_size_hints->min_height = p_vout->p_sys->i_height;
666         p_size_hints->max_width = p_vout->p_sys->i_width;
667         p_size_hints->max_height = p_vout->p_sys->i_height;
668         XSetWMNormalHints( p_display, wnd, p_size_hints );
669         XFree( p_size_hints );
670     }
671     XSelectInput( p_display, wnd, KeyPressMask );
672 }
673
674
675 void SwitchContext( vout_thread_t *p_vout )
676 {
677     /* Change the current OpenGL context */
678     if( p_vout->p_sys->b_glx13 )
679     {
680         glXMakeContextCurrent( p_vout->p_sys->p_display, p_vout->p_sys->gwnd,
681                                p_vout->p_sys->gwnd, p_vout->p_sys->gwctx );
682     }
683     else
684     {
685         glXMakeCurrent( p_vout->p_sys->p_display, p_vout->p_sys->wnd,
686                         p_vout->p_sys->gwctx );
687     }
688 }
689
690
691 int GetAlignedSize( int i_size )
692 {
693     /* Return the nearest power of 2 */
694     int i_result = 1;
695     while( i_result < i_size )
696     {
697         i_result *= 2;
698     }
699     return i_result;
700 }