glx.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:10k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * glx.c: GLX OpenGL provider
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 the VideoLAN team
  5.  * $Id: b82984aafb589df770c7fa995fd17cf582cb8e8f $
  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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <errno.h>                                                 /* ENOMEM */
  31. #include <vlc_common.h>
  32. #include <vlc_plugin.h>
  33. #include <vlc_interface.h>
  34. #include <vlc_vout.h>
  35. #ifdef HAVE_SYS_SHM_H
  36. #   include <sys/shm.h>                                /* shmget(), shmctl() */
  37. #endif
  38. #include <X11/Xlib.h>
  39. #include <X11/Xmd.h>
  40. #include <X11/Xutil.h>
  41. #include <X11/keysym.h>
  42. #ifdef HAVE_SYS_SHM_H
  43. #   include <X11/extensions/XShm.h>
  44. #endif
  45. #ifdef DPMSINFO_IN_DPMS_H
  46. #   include <X11/extensions/dpms.h>
  47. #endif
  48. #include <GL/glx.h>
  49. #include "xcommon.h"
  50. /* RV16 */
  51. //#define VLCGL_RGB_FORMAT GL_RGB
  52. //#define VLCGL_RGB_TYPE GL_UNSIGNED_SHORT_5_6_5
  53. /* RV24 */
  54. //#define VLCGL_RGB_FORMAT GL_RGB
  55. //#define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
  56. /* RV32 */
  57. #define VLCGL_RGB_FORMAT GL_RGBA
  58. #define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
  59. /*****************************************************************************
  60.  * OpenGL provider interface
  61.  *****************************************************************************/
  62. static int  CreateOpenGL ( vlc_object_t * );
  63. static void DestroyOpenGL( vlc_object_t * );
  64. static int  InitOpenGL   ( vout_thread_t * );
  65. static void SwapBuffers  ( vout_thread_t * );
  66. /*****************************************************************************
  67.  * Local prototypes
  68.  *****************************************************************************/
  69. static int  InitGLX12    ( vout_thread_t * );
  70. static int  InitGLX13    ( vout_thread_t * );
  71. static void SwitchContext( vout_thread_t * );
  72. /*****************************************************************************
  73.  * Module descriptor
  74.  *****************************************************************************/
  75. #define ALT_FS_TEXT N_("Alternate fullscreen method")
  76. #define ALT_FS_LONGTEXT N_( 
  77.     "There are two ways to make a fullscreen window, unfortunately each one " 
  78.     "has its drawbacks.n" 
  79.     "1) Let the window manager handle your fullscreen window (default), but " 
  80.     "things like taskbars will likely show on top of the video.n" 
  81.     "2) Completely bypass the window manager, but then nothing will be able " 
  82.     "to show on top of the video.")
  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.")
  87. #define SCREEN_TEXT N_("Screen for fullscreen mode.")
  88. #define SCREEN_LONGTEXT N_( 
  89.     "Screen to use in fullscreen mode. For instance " 
  90.     "set it to 0 for first screen, 1 for the second.")
  91. vlc_module_begin ()
  92.     set_shortname( "OpenGL(GLX)" )
  93.     set_category( CAT_VIDEO )
  94.     set_subcategory( SUBCAT_VIDEO_VOUT )
  95.     set_description( N_("OpenGL(GLX) provider") )
  96.     set_capability( "opengl provider", 50 )
  97.     set_callbacks( CreateOpenGL, DestroyOpenGL )
  98.     add_string( "glx-display", NULL, NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT, true )
  99.     add_obsolete_integer( "glx-adaptor" ) /* Deprecated since 1.0.4 */
  100.     add_bool( "glx-altfullscreen", 0, NULL, ALT_FS_TEXT, ALT_FS_LONGTEXT, true )
  101. #ifdef HAVE_SYS_SHM_H
  102.     add_obsolete_bool( "glx-shm" ) /* Deprecated since 1.0.4 */
  103. #endif
  104. #ifdef HAVE_XINERAMA
  105.     add_integer ( "glx-xineramascreen", -1, NULL, SCREEN_TEXT, SCREEN_LONGTEXT, true )
  106. #endif
  107. vlc_module_end ()
  108. /*****************************************************************************
  109.  * Exported prototypes
  110.  *****************************************************************************/
  111. extern int  Activate   ( vlc_object_t * );
  112. extern void Deactivate ( vlc_object_t * );
  113. /*****************************************************************************
  114.  * CreateOpenGL: initialize an OpenGL provider
  115.  *****************************************************************************/
  116. static int CreateOpenGL( vlc_object_t *p_this )
  117. {
  118.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  119.     if( Activate( p_this ) != VLC_SUCCESS )
  120.     {
  121.         return VLC_EGENERIC;
  122.     }
  123.     /* Set the function pointer */
  124.     p_vout->pf_init = InitOpenGL;
  125.     p_vout->pf_swap = SwapBuffers;
  126.     return VLC_SUCCESS;
  127. }
  128. /*****************************************************************************
  129.  * DestroyOpenGL: destroys an OpenGL provider
  130.  *****************************************************************************/
  131. static void DestroyOpenGL( vlc_object_t *p_this )
  132. {
  133.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  134.     vout_sys_t *p_sys = p_vout->p_sys;
  135.     glXDestroyContext( p_sys->p_display, p_sys->gwctx );
  136.     if( p_sys->b_glx13 )
  137.     {
  138.         glXDestroyWindow( p_sys->p_display, p_sys->gwnd );
  139.     }
  140.     Deactivate( p_this );
  141. }
  142. /*****************************************************************************
  143.  * InitOpenGL: initializes OpenGL provider
  144.  *****************************************************************************/
  145. static int InitOpenGL( vout_thread_t *p_vout )
  146. {
  147.     /* Initialize GLX */
  148.     if( !p_vout->p_sys->b_glx13 )
  149.     {
  150.         if( InitGLX12( p_vout ) != VLC_SUCCESS )
  151.         {
  152.             return VLC_EGENERIC;
  153.         }
  154.     }
  155.     else
  156.     {
  157.         if( InitGLX13( p_vout ) != VLC_SUCCESS )
  158.         {
  159.             return VLC_EGENERIC;
  160.         }
  161.     }
  162.     /* Set the OpenGL context _for the current thread_ */
  163.     SwitchContext( p_vout );
  164.     return VLC_SUCCESS;
  165. }
  166. int InitGLX12( vout_thread_t *p_vout )
  167. {
  168.     vout_sys_t *p_sys = p_vout->p_sys;
  169.     XVisualInfo *p_vi;
  170.     int p_attr[] = { GLX_RGBA, GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 5,
  171.                      GLX_BLUE_SIZE, 5, GLX_DOUBLEBUFFER, 0 };
  172.     p_vi = glXChooseVisual( p_sys->p_display,
  173.                             DefaultScreen( p_sys->p_display), p_attr );
  174.     if(! p_vi )
  175.     {
  176.         msg_Err( p_vout, "Cannot get GLX 1.2 visual" );
  177.         return VLC_EGENERIC;
  178.     }
  179.     /* Create an OpenGL context */
  180.     p_sys->gwctx = glXCreateContext( p_sys->p_display, p_vi, 0, True );
  181.     XFree( p_vi );
  182.     if( !p_sys->gwctx )
  183.     {
  184.         msg_Err( p_vout, "Cannot create OpenGL context");
  185.         return VLC_EGENERIC;
  186.     }
  187.     return VLC_SUCCESS;
  188. }
  189. int InitGLX13( vout_thread_t *p_vout )
  190. {
  191.     vout_sys_t *p_sys = p_vout->p_sys;
  192.     int i_nb, ret = VLC_EGENERIC;
  193.     GLXFBConfig *p_fbconfs = NULL, fbconf = NULL;
  194.     XWindowAttributes att;
  195.     static const int p_attr[] = {
  196.         GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 5, GLX_BLUE_SIZE, 5,
  197.         GLX_DOUBLEBUFFER, True, GLX_X_RENDERABLE, True,
  198.         GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
  199.         None,
  200.     };
  201.     /* Get the FB configuration */
  202.     p_fbconfs = glXChooseFBConfig( p_sys->p_display, p_sys->i_screen, p_attr, &i_nb );
  203.     if( p_fbconfs == NULL )
  204.     {
  205.         msg_Err( p_vout, "Cannot get FB configurations");
  206.         return VLC_EGENERIC;
  207.     }
  208.     /* We should really create the window _after_ the frame buffer
  209.      * configuration was chosen, instead of selecting the frame buffer from
  210.      * the window. That requires reworking xcommon.c though.
  211.      * -- Courmisch */
  212.     XGetWindowAttributes( p_sys->p_display, p_sys->p_win->video_window, &att );
  213.     for( int i = 0; i < i_nb && !fbconf; i++ )
  214.     {
  215.         XVisualInfo *p_vi;
  216.         /* Get the X11 visual */
  217.         p_vi = glXGetVisualFromFBConfig( p_sys->p_display, p_fbconfs[i] );
  218.         if( !p_vi )
  219.             continue; /* OoM? */
  220.         if( p_vi->visualid == att.visual->visualid )
  221.             fbconf = p_fbconfs[i];
  222.         XFree( p_vi );
  223.     }
  224.     if( !fbconf )
  225.     {
  226.         msg_Err( p_vout, "Cannot find matching frame buffer" );
  227.         goto out;
  228.     }
  229.     /* Create the GLX window */
  230.     p_sys->gwnd = glXCreateWindow( p_sys->p_display, fbconf,
  231.                                    p_sys->p_win->video_window, NULL );
  232.     if( p_sys->gwnd == None )
  233.     {
  234.         msg_Err( p_vout, "Cannot create GLX window" );
  235.         goto out;
  236.     }
  237.     /* Create an OpenGL context */
  238.     p_sys->gwctx = glXCreateNewContext( p_sys->p_display, fbconf,
  239.                                         GLX_RGBA_TYPE, NULL, True );
  240.     if( !p_sys->gwctx )
  241.         msg_Err( p_vout, "Cannot create OpenGL context");
  242.     else
  243.         ret = VLC_SUCCESS;
  244. out:
  245.     XFree( p_fbconfs );
  246.     return ret;
  247. }
  248. /*****************************************************************************
  249.  * SwapBuffers: swap front/back buffers
  250.  *****************************************************************************/
  251. static void SwapBuffers( vout_thread_t *p_vout )
  252. {
  253.     vout_sys_t *p_sys = p_vout->p_sys;
  254.     unsigned int i_width, i_height, i_x, i_y;
  255.     vout_PlacePicture( p_vout, p_vout->p_sys->p_win->i_width,
  256.                        p_vout->p_sys->p_win->i_height,
  257.                        &i_x, &i_y, &i_width, &i_height );
  258.     glViewport( 0, 0, (GLint)i_width, (GLint)i_height );
  259.     if( p_sys->b_glx13 )
  260.     {
  261.         glXSwapBuffers( p_sys->p_display, p_sys->gwnd );
  262.     }
  263.     else
  264.     {
  265.         glXSwapBuffers( p_sys->p_display, p_sys->p_win->video_window );
  266.     }
  267. }
  268. void SwitchContext( vout_thread_t *p_vout )
  269. {
  270.     vout_sys_t *p_sys = p_vout->p_sys;
  271.     /* Change the current OpenGL context */
  272.     if( p_sys->b_glx13 )
  273.     {
  274.         glXMakeContextCurrent( p_sys->p_display, p_sys->gwnd,
  275.                                p_sys->gwnd, p_sys->gwctx );
  276.     }
  277.     else
  278.     {
  279.         glXMakeCurrent( p_sys->p_display, p_sys->p_win->video_window,
  280.                         p_sys->gwctx );
  281.     }
  282. }