glx.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:12k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * glx.c: GLX OpenGL provider
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 VideoLAN
  5.  * $Id: glx.c 8498 2004-08-22 14:32:51Z hartman $
  6.  *
  7.  * Authors: Cyril Deguet <asmax@videolan.org>
  8.  *          Gildas Bazin <gbazin@videolan.org>
  9.  *
  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.
  14.  *
  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.
  19.  *
  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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <errno.h>                                                 /* ENOMEM */
  28. #include <stdlib.h>                                      /* malloc(), free() */
  29. #include <string.h>
  30. #include <vlc/vlc.h>
  31. #include <vlc/intf.h>
  32. #include <vlc/vout.h>
  33. #ifdef HAVE_SYS_SHM_H
  34. #   include <sys/shm.h>                                /* shmget(), shmctl() */
  35. #endif
  36. #include <X11/Xlib.h>
  37. #include <X11/Xmd.h>
  38. #include <X11/Xutil.h>
  39. #include <X11/keysym.h>
  40. #ifdef HAVE_SYS_SHM_H
  41. #   include <X11/extensions/XShm.h>
  42. #endif
  43. #ifdef DPMSINFO_IN_DPMS_H
  44. #   include <X11/extensions/dpms.h>
  45. #endif
  46. #include <GL/glx.h>
  47. #include "xcommon.h"
  48. /* RV16 */
  49. //#define VLCGL_RGB_FORMAT GL_RGB
  50. //#define VLCGL_RGB_TYPE GL_UNSIGNED_SHORT_5_6_5
  51. /* RV24 */
  52. //#define VLCGL_RGB_FORMAT GL_RGB
  53. //#define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
  54. /* RV32 */
  55. #define VLCGL_RGB_FORMAT GL_RGBA
  56. #define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
  57. /*****************************************************************************
  58.  * OpenGL provider interface
  59.  *****************************************************************************/
  60. static int  CreateOpenGL ( vlc_object_t * );
  61. static void DestroyOpenGL( vlc_object_t * );
  62. static int  InitOpenGL   ( vout_thread_t * );
  63. static void SwapBuffers  ( vout_thread_t * );
  64. /*****************************************************************************
  65.  * Local prototypes
  66.  *****************************************************************************/
  67. static int  CheckGLX     ( vlc_object_t *, vlc_bool_t * );
  68. static int  InitGLX12    ( vout_thread_t * );
  69. static int  InitGLX13    ( vout_thread_t * );
  70. static void SwitchContext( vout_thread_t * );
  71. /*****************************************************************************
  72.  * Module descriptor
  73.  *****************************************************************************/
  74. #define ADAPTOR_TEXT N_("XVideo adaptor number")
  75. #define ADAPTOR_LONGTEXT N_( 
  76.     "If you graphics card provides several adaptors, this option allows you " 
  77.     "to choose which one will be used (you shouldn't have to change this).")
  78. #define ALT_FS_TEXT N_("Alternate fullscreen method")
  79. #define ALT_FS_LONGTEXT N_( 
  80.     "There are two ways to make a fullscreen window, unfortunately each one " 
  81.     "has its drawbacks.n" 
  82.     "1) Let the window manager handle your fullscreen window (default), but " 
  83.     "things like taskbars will likely show on top of the video.n" 
  84.     "2) Completely bypass the window manager, but then nothing will be able " 
  85.     "to show on top of the video.")
  86. #define DISPLAY_TEXT N_("X11 display name")
  87. #define DISPLAY_LONGTEXT N_( 
  88.     "Specify the X11 hardware display you want to use. By default VLC will " 
  89.     "use the value of the DISPLAY environment variable.")
  90. #define SCREEN_TEXT N_("Screen to be used for fullscreen mode.")
  91. #define SCREEN_LONGTEXT N_( 
  92.     "Choose the screen you want to use in fullscreen mode. For instance " 
  93.     "set it to 0 for first screen, 1 for the second.")
  94. vlc_module_begin();
  95.     set_description( _("X11 OpenGL provider") );
  96.     set_capability( "opengl provider", 50 );
  97.     set_callbacks( CreateOpenGL, DestroyOpenGL );
  98.     add_string( "glx-display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT, VLC_TRUE );
  99.     add_integer( "glx-adaptor", -1, NULL, ADAPTOR_TEXT, ADAPTOR_LONGTEXT, VLC_TRUE );
  100.     add_bool( "glx-altfullscreen", 0, NULL, ALT_FS_TEXT, ALT_FS_LONGTEXT, VLC_TRUE );
  101. #ifdef HAVE_XINERAMA
  102.     add_integer ( "glx-xineramascreen", 0, NULL, SCREEN_TEXT, SCREEN_LONGTEXT, VLC_TRUE );
  103. #endif
  104. vlc_module_end();
  105. /*****************************************************************************
  106.  * Exported prototypes
  107.  *****************************************************************************/
  108. extern int  E_(Activate)   ( vlc_object_t * );
  109. extern void E_(Deactivate) ( vlc_object_t * );
  110. /*****************************************************************************
  111.  * CreateOpenGL: initialize an OpenGL provider
  112.  *****************************************************************************/
  113. static int CreateOpenGL( vlc_object_t *p_this )
  114. {
  115.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  116.     vlc_bool_t b_glx13;
  117.     if( CheckGLX( p_this, &b_glx13 ) != VLC_SUCCESS )
  118.     {
  119.         msg_Err( p_vout, "no GLX support" );
  120.         return VLC_EGENERIC;
  121.     }
  122.     if( E_(Activate)( p_this ) != VLC_SUCCESS )
  123.     {
  124.         return VLC_EGENERIC;
  125.     }
  126.     /* Set the function pointer */
  127.     p_vout->pf_init = InitOpenGL;
  128.     p_vout->pf_swap = SwapBuffers;
  129.     p_vout->p_sys->b_glx13 = b_glx13;
  130.     return VLC_SUCCESS;
  131. }
  132. /*****************************************************************************
  133.  * DestroyOpenGL: destroys an OpenGL provider
  134.  *****************************************************************************/
  135. static void DestroyOpenGL( vlc_object_t *p_this )
  136. {
  137.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  138.     vout_sys_t *p_sys = p_vout->p_sys;
  139.     glXDestroyContext( p_sys->p_display, p_sys->gwctx );
  140.     if( p_sys->b_glx13 )
  141.     {
  142.         glXDestroyWindow( p_sys->p_display, p_sys->gwnd );
  143.     }
  144.     E_(Deactivate)( p_this );
  145. }
  146. /*****************************************************************************
  147.  * OpenDisplay: open and initialize OpenGL device
  148.  *****************************************************************************/
  149. static int CheckGLX( vlc_object_t *p_this, vlc_bool_t *b_glx13 )
  150. {
  151.     Display *p_display = NULL;
  152.     int i_opcode, i_evt, i_err = 0;
  153.     int i_maj, i_min = 0;
  154.     /* Open the display */
  155.     p_display = XOpenDisplay( NULL );
  156.     if( p_display == NULL )
  157.     {
  158.         msg_Err( p_this, "Cannot open display" );
  159.         return VLC_EGENERIC;
  160.     }
  161.     /* Check for GLX extension */
  162.     if( !XQueryExtension( p_display, "GLX", &i_opcode, &i_evt, &i_err ) )
  163.     {
  164.         msg_Err( p_this, "GLX extension not supported" );
  165.         XCloseDisplay( p_display );
  166.         return VLC_EGENERIC;
  167.     }
  168.     if( !glXQueryExtension( p_display, &i_err, &i_evt ) )
  169.     {
  170.         msg_Err( p_this, "glXQueryExtension failed" );
  171.         XCloseDisplay( p_display );
  172.         return VLC_EGENERIC;
  173.     }
  174.     /* Check GLX version */
  175.     if (!glXQueryVersion( p_display, &i_maj, &i_min ) )
  176.     {
  177.         msg_Err( p_this, "glXQueryVersion failed" );
  178.         XCloseDisplay( p_display );
  179.         return VLC_EGENERIC;
  180.     }
  181.     if( i_maj <= 0 || ((i_maj == 1) && (i_min < 3)) )
  182.     {
  183.         *b_glx13 = VLC_FALSE;
  184.         msg_Dbg( p_this, "Using GLX 1.2 API" );
  185.     }
  186.     else
  187.     {
  188.         *b_glx13 = VLC_TRUE;
  189.         msg_Dbg( p_this, "Using GLX 1.3 API" );
  190.     }
  191.     XCloseDisplay( p_display );
  192.     return VLC_SUCCESS;
  193. }
  194. /*****************************************************************************
  195.  * InitOpenGL: initializes OpenGL provider
  196.  *****************************************************************************/
  197. static int InitOpenGL( vout_thread_t *p_vout )
  198. {
  199.     /* Initialize GLX */
  200.     if( !p_vout->p_sys->b_glx13 )
  201.     {
  202.         if( InitGLX12( p_vout ) != VLC_SUCCESS )
  203.         {
  204.             return VLC_EGENERIC;
  205.         }
  206.     }
  207.     else
  208.     {
  209.         if( InitGLX13( p_vout ) != VLC_SUCCESS )
  210.         {
  211.             return VLC_EGENERIC;
  212.         }
  213.     }
  214.     /* Set the OpenGL context _for the current thread_ */
  215.     SwitchContext( p_vout );
  216.     return VLC_SUCCESS;
  217. }
  218. int InitGLX12( vout_thread_t *p_vout )
  219. {
  220.     vout_sys_t *p_sys = p_vout->p_sys;
  221.     XVisualInfo *p_vi;
  222.     int p_attr[] = { GLX_RGBA, GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 5,
  223.                      GLX_BLUE_SIZE, 5, GLX_DOUBLEBUFFER, 0 };
  224.     p_vi = glXChooseVisual( p_sys->p_display,
  225.                             DefaultScreen( p_sys->p_display), p_attr );
  226.     if(! p_vi )
  227.     {
  228.         msg_Err( p_vout, "Cannot get GLX 1.2 visual" );
  229.         return VLC_EGENERIC;
  230.     }
  231.     /* Create an OpenGL context */
  232.     p_sys->gwctx = glXCreateContext( p_sys->p_display, p_vi, 0, True );
  233.     XFree( p_vi );
  234.     if( !p_sys->gwctx )
  235.     {
  236.         msg_Err( p_vout, "Cannot create OpenGL context");
  237.         return VLC_EGENERIC;
  238.     }
  239.     return VLC_SUCCESS;
  240. }
  241. int InitGLX13( vout_thread_t *p_vout )
  242. {
  243.     vout_sys_t *p_sys = p_vout->p_sys;
  244.     int i_nbelem;
  245.     GLXFBConfig *p_fbconfs, fbconf;
  246.     XVisualInfo *p_vi;
  247.     int p_attr[] = { GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 5,
  248.                      GLX_BLUE_SIZE, 5, GLX_DOUBLEBUFFER, True,
  249.                      GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, 0 };
  250.     /* Get the FB configuration */
  251.     p_fbconfs = glXChooseFBConfig( p_sys->p_display, 0, p_attr, &i_nbelem );
  252.     if( (i_nbelem <= 0) || !p_fbconfs )
  253.     {
  254.         msg_Err( p_vout, "Cannot get FB configurations");
  255.         if( p_fbconfs ) XFree( p_fbconfs );
  256.         return VLC_EGENERIC;
  257.     }
  258.     fbconf = p_fbconfs[0];
  259.     /* Get the X11 visual */
  260.     p_vi = glXGetVisualFromFBConfig( p_sys->p_display, fbconf );
  261.     if( !p_vi )
  262.     {
  263.         msg_Err( p_vout, "Cannot get X11 visual" );
  264.         XFree( p_fbconfs );
  265.         return VLC_EGENERIC;
  266.     }
  267.     XFree( p_vi );
  268.     /* Create the GLX window */
  269.     p_sys->gwnd = glXCreateWindow( p_sys->p_display, fbconf,
  270.                                    p_sys->p_win->video_window, NULL );
  271.     if( p_sys->gwnd == None )
  272.     {
  273.         msg_Err( p_vout, "Cannot create GLX window" );
  274.         return VLC_EGENERIC;
  275.     }
  276.     /* Create an OpenGL context */
  277.     p_sys->gwctx = glXCreateNewContext( p_sys->p_display, fbconf,
  278.                                         GLX_RGBA_TYPE, NULL, True );
  279.     XFree( p_fbconfs );
  280.     if( !p_sys->gwctx )
  281.     {
  282.         msg_Err( p_vout, "Cannot create OpenGL context");
  283.         return VLC_EGENERIC;
  284.     }
  285.     return VLC_SUCCESS;
  286. }
  287. /*****************************************************************************
  288.  * SwapBuffers: swap front/back buffers
  289.  *****************************************************************************/
  290. static void SwapBuffers( vout_thread_t *p_vout )
  291. {
  292.     vout_sys_t *p_sys = p_vout->p_sys;
  293.     int i_width, i_height, i_x, i_y;
  294.     vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
  295.                        p_vout->p_sys->p_win->i_height,
  296.                        &i_x, &i_y, &i_width, &i_height );
  297.     glViewport( 0, 0, (GLint)i_width, (GLint)i_height );
  298.     if( p_sys->b_glx13 )
  299.     {
  300.         glXSwapBuffers( p_sys->p_display, p_sys->gwnd );
  301.     }
  302.     else
  303.     {
  304.         glXSwapBuffers( p_sys->p_display, p_sys->p_win->video_window );
  305.     }
  306. }
  307. void SwitchContext( vout_thread_t *p_vout )
  308. {
  309.     vout_sys_t *p_sys = p_vout->p_sys;
  310.     /* Change the current OpenGL context */
  311.     if( p_sys->b_glx13 )
  312.     {
  313.         glXMakeContextCurrent( p_sys->p_display, p_sys->gwnd,
  314.                                p_sys->gwnd, p_sys->gwctx );
  315.     }
  316.     else
  317.     {
  318.         glXMakeCurrent( p_sys->p_display, p_sys->p_win->video_window,
  319.                         p_sys->gwctx );
  320.     }
  321. }