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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * opengl.c: OpenGL video output
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 the VideoLAN team
  5.  * $Id: 21b08bacedd8b3ba2bff288bf7160c40df33fddd $
  6.  *
  7.  * Authors: Cyril Deguet <asmax@videolan.org>
  8.  *          Gildas Bazin <gbazin@videolan.org>
  9.  *          Eric Petit <titer@m0k.org>
  10.  *          Cedric Cocquebert <cedric.cocquebert@supelec.fr>
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or
  15.  * (at your option) any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; if not, write to the Free Software
  24.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  25.  *****************************************************************************/
  26. /*****************************************************************************
  27.  * Preamble
  28.  *****************************************************************************/
  29. #ifdef HAVE_CONFIG_H
  30. # include "config.h"
  31. #endif
  32. #include <errno.h>                                                 /* ENOMEM */
  33. #include <vlc_common.h>
  34. #include <vlc_plugin.h>
  35. #include <vlc_vout.h>
  36. #ifdef __APPLE__
  37. #include <OpenGL/gl.h>
  38. #include <OpenGL/glext.h>
  39. /* On OS X, use GL_TEXTURE_RECTANGLE_EXT instead of GL_TEXTURE_2D.
  40.    This allows sizes which are not powers of 2 */
  41. #define VLCGL_TARGET GL_TEXTURE_RECTANGLE_EXT
  42. /* OS X OpenGL supports YUV. Hehe. */
  43. #define VLCGL_FORMAT GL_YCBCR_422_APPLE
  44. #define VLCGL_TYPE   GL_UNSIGNED_SHORT_8_8_APPLE
  45. #else
  46. #include <GL/gl.h>
  47. #define VLCGL_TARGET GL_TEXTURE_2D
  48. /* RV16 */
  49. #ifndef GL_UNSIGNED_SHORT_5_6_5
  50. #define GL_UNSIGNED_SHORT_5_6_5 0x8363
  51. #endif
  52. //#define VLCGL_RGB_FORMAT GL_RGB
  53. //#define VLCGL_RGB_TYPE GL_UNSIGNED_SHORT_5_6_5
  54. /* RV24 */
  55. //#define VLCGL_RGB_FORMAT GL_RGB
  56. //#define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
  57. /* RV32 */
  58. #define VLCGL_RGB_FORMAT GL_RGBA
  59. #define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE
  60. /* YUY2 */
  61. #ifndef YCBCR_MESA
  62. #define YCBCR_MESA 0x8757
  63. #endif
  64. #ifndef UNSIGNED_SHORT_8_8_MESA
  65. #define UNSIGNED_SHORT_8_8_MESA 0x85BA
  66. #endif
  67. #define VLCGL_YUV_FORMAT YCBCR_MESA
  68. #define VLCGL_YUV_TYPE UNSIGNED_SHORT_8_8_MESA
  69. /* Use RGB on Win32/GLX */
  70. #define VLCGL_FORMAT VLCGL_RGB_FORMAT
  71. #define VLCGL_TYPE   VLCGL_RGB_TYPE
  72. //#define VLCGL_FORMAT VLCGL_YUV_FORMAT
  73. //#define VLCGL_TYPE   VLCGL_YUV_TYPE
  74. #endif
  75. #ifndef GL_CLAMP_TO_EDGE
  76. #   define GL_CLAMP_TO_EDGE 0x812F
  77. #endif
  78. /*****************************************************************************
  79.  * Vout interface
  80.  *****************************************************************************/
  81. static int  CreateVout   ( vlc_object_t * );
  82. static void DestroyVout  ( vlc_object_t * );
  83. static int  Init         ( vout_thread_t * );
  84. static void End          ( vout_thread_t * );
  85. static int  Manage       ( vout_thread_t * );
  86. static void Render       ( vout_thread_t *, picture_t * );
  87. static void DisplayVideo ( vout_thread_t *, picture_t * );
  88. static int  Control      ( vout_thread_t *, int, va_list );
  89. static inline int GetAlignedSize( int );
  90. static int InitTextures  ( vout_thread_t * );
  91. static int SendEvents    ( vlc_object_t *, char const *,
  92.                            vlc_value_t, vlc_value_t, void * );
  93. #define PROVIDER_TEXT N_("OpenGL Provider")
  94. #define PROVIDER_LONGTEXT N_("Allows you to modify what OpenGL provider should be used")
  95. vlc_module_begin ()
  96.     set_shortname( "OpenGL" )
  97.     set_category( CAT_VIDEO )
  98.     set_subcategory( SUBCAT_VIDEO_VOUT )
  99.     set_description( N_("OpenGL video output") )
  100. #ifdef __APPLE__
  101.     set_capability( "video output", 200 )
  102. #else
  103.     set_capability( "video output", 20 )
  104. #endif
  105.     add_shortcut( "opengl" )
  106.     /* Allow opengl provider plugin selection */
  107.     add_module( "opengl-provider", "opengl provider", NULL, NULL,
  108.                 PROVIDER_TEXT, PROVIDER_LONGTEXT, true )
  109.     set_callbacks( CreateVout, DestroyVout )
  110. vlc_module_end ()
  111. /*****************************************************************************
  112.  * vout_sys_t: video output method descriptor
  113.  *****************************************************************************
  114.  * This structure is part of the video output thread descriptor.
  115.  * It describes the OpenGL specific properties of the output thread.
  116.  *****************************************************************************/
  117. struct vout_sys_t
  118. {
  119.     vout_thread_t *p_vout;
  120.     uint8_t    *pp_buffer[2];
  121.     int         i_index;
  122.     int         i_tex_width;
  123.     int         i_tex_height;
  124.     GLuint      p_textures[2];
  125. };
  126. /*****************************************************************************
  127.  * CreateVout: This function allocates and initializes the OpenGL vout method.
  128.  *****************************************************************************/
  129. static int CreateVout( vlc_object_t *p_this )
  130. {
  131.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  132.     vout_sys_t *p_sys;
  133.     char * psz;
  134.     /* Allocate structure */
  135.     p_vout->p_sys = p_sys = malloc( sizeof( vout_sys_t ) );
  136.     if( p_sys == NULL )
  137.         return VLC_ENOMEM;
  138.     p_sys->i_index = 0;
  139. #ifdef __APPLE__
  140.     p_sys->i_tex_width  = p_vout->fmt_in.i_width;
  141.     p_sys->i_tex_height = p_vout->fmt_in.i_height;
  142. #else
  143.     /* A texture must have a size aligned on a power of 2 */
  144.     p_sys->i_tex_width  = GetAlignedSize( p_vout->fmt_in.i_width );
  145.     p_sys->i_tex_height = GetAlignedSize( p_vout->fmt_in.i_height );
  146. #endif
  147.     msg_Dbg( p_vout, "Texture size: %dx%d", p_sys->i_tex_width,
  148.              p_sys->i_tex_height );
  149.     /* Get window */
  150.     p_sys->p_vout =
  151.         (vout_thread_t *)vlc_object_create( p_this, sizeof( vout_thread_t ) );
  152.     if( p_sys->p_vout == NULL )
  153.     {
  154.         free( p_sys );
  155.         return VLC_ENOMEM;
  156.     }
  157.     vlc_object_attach( p_sys->p_vout, p_this );
  158.     p_sys->p_vout->i_window_width = p_vout->i_window_width;
  159.     p_sys->p_vout->i_window_height = p_vout->i_window_height;
  160.     p_sys->p_vout->b_fullscreen = p_vout->b_fullscreen;
  161.     p_sys->p_vout->render.i_width = p_vout->render.i_width;
  162.     p_sys->p_vout->render.i_height = p_vout->render.i_height;
  163.     p_sys->p_vout->render.i_aspect = p_vout->render.i_aspect;
  164.     p_sys->p_vout->fmt_render = p_vout->fmt_render;
  165.     p_sys->p_vout->fmt_in = p_vout->fmt_in;
  166.     p_sys->p_vout->b_autoscale = p_vout->b_autoscale;
  167.     p_sys->p_vout->i_zoom = p_vout->i_zoom;
  168.     p_sys->p_vout->i_alignment = p_vout->i_alignment;
  169.     var_Create( p_sys->p_vout, "video-deco",
  170.                 VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  171.     /* Forward events from the opengl provider */
  172.     var_Create( p_sys->p_vout, "mouse-x", VLC_VAR_INTEGER );
  173.     var_Create( p_sys->p_vout, "mouse-y", VLC_VAR_INTEGER );
  174.     var_Create( p_sys->p_vout, "mouse-moved", VLC_VAR_BOOL );
  175.     var_Create( p_sys->p_vout, "mouse-clicked", VLC_VAR_BOOL );
  176.     var_Create( p_sys->p_vout, "mouse-button-down", VLC_VAR_INTEGER );
  177.     var_Create( p_sys->p_vout, "video-on-top",
  178.                 VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  179.     var_Create( p_sys->p_vout, "autoscale",
  180.                 VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  181.     var_Create( p_sys->p_vout, "scale",
  182.                 VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
  183.     var_AddCallback( p_sys->p_vout, "mouse-x", SendEvents, p_vout );
  184.     var_AddCallback( p_sys->p_vout, "mouse-y", SendEvents, p_vout );
  185.     var_AddCallback( p_sys->p_vout, "mouse-moved", SendEvents, p_vout );
  186.     var_AddCallback( p_sys->p_vout, "mouse-clicked", SendEvents, p_vout );
  187.     var_AddCallback( p_sys->p_vout, "mouse-button-down", SendEvents, p_vout );
  188.     var_AddCallback( p_sys->p_vout, "video-on-top", SendEvents, p_vout );
  189.     var_AddCallback( p_vout, "autoscale", SendEvents, p_sys->p_vout );
  190.     var_AddCallback( p_vout, "scale", SendEvents, p_sys->p_vout );
  191.     psz = var_CreateGetString( p_vout, "opengl-provider" );
  192.     p_sys->p_vout->p_module =
  193.         module_need( p_sys->p_vout, "opengl provider", psz, false );
  194.     free( psz );
  195.     if( p_sys->p_vout->p_module == NULL )
  196.     {
  197.         msg_Warn( p_vout, "No OpenGL provider found" );
  198.         vlc_object_detach( p_sys->p_vout );
  199.         /* no need for var_DelCallback here :-) */
  200.         vlc_object_release( p_sys->p_vout );
  201.         free( p_sys );
  202.         return VLC_ENOOBJ;
  203.     }
  204.     p_vout->pf_init = Init;
  205.     p_vout->pf_end = End;
  206.     p_vout->pf_manage = Manage;
  207.     p_vout->pf_render = Render;
  208.     p_vout->pf_display = DisplayVideo;
  209.     p_vout->pf_control = Control;
  210.     return VLC_SUCCESS;
  211. }
  212. /*****************************************************************************
  213.  * Init: initialize the OpenGL video thread output method
  214.  *****************************************************************************/
  215. static int Init( vout_thread_t *p_vout )
  216. {
  217.     vout_sys_t *p_sys = p_vout->p_sys;
  218.     int i_pixel_pitch;
  219.     p_sys->p_vout->pf_init( p_sys->p_vout );
  220. /* TODO: We use YCbCr on Mac which is Y422, but on OSX it seems to == YUY2. Verify */
  221. #if ( defined( WORDS_BIGENDIAN ) && VLCGL_FORMAT == GL_YCBCR_422_APPLE ) || (VLCGL_FORMAT == YCBCR_MESA)
  222.     p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
  223.     i_pixel_pitch = 2;
  224. #elif (VLCGL_FORMAT == GL_YCBCR_422_APPLE)
  225.     p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
  226.     i_pixel_pitch = 2;
  227. #elif VLCGL_FORMAT == GL_RGB
  228. #   if VLCGL_TYPE == GL_UNSIGNED_BYTE
  229.     p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
  230. #       if defined( WORDS_BIGENDIAN )
  231.     p_vout->output.i_rmask = 0x00ff0000;
  232.     p_vout->output.i_gmask = 0x0000ff00;
  233.     p_vout->output.i_bmask = 0x000000ff;
  234. #       else
  235.     p_vout->output.i_rmask = 0x000000ff;
  236.     p_vout->output.i_gmask = 0x0000ff00;
  237.     p_vout->output.i_bmask = 0x00ff0000;
  238. #       endif
  239.     i_pixel_pitch = 3;
  240. #   else
  241.     p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
  242. #       if defined( WORDS_BIGENDIAN )
  243.     p_vout->output.i_rmask = 0x001f;
  244.     p_vout->output.i_gmask = 0x07e0;
  245.     p_vout->output.i_bmask = 0xf800;
  246. #       else
  247.     p_vout->output.i_rmask = 0xf800;
  248.     p_vout->output.i_gmask = 0x07e0;
  249.     p_vout->output.i_bmask = 0x001f;
  250. #       endif
  251.     i_pixel_pitch = 2;
  252. #   endif
  253. #else
  254.     p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
  255. #       if defined( WORDS_BIGENDIAN )
  256.     p_vout->output.i_rmask = 0xff000000;
  257.     p_vout->output.i_gmask = 0x00ff0000;
  258.     p_vout->output.i_bmask = 0x0000ff00;
  259. #       else
  260.     p_vout->output.i_rmask = 0x000000ff;
  261.     p_vout->output.i_gmask = 0x0000ff00;
  262.     p_vout->output.i_bmask = 0x00ff0000;
  263. #       endif
  264.     i_pixel_pitch = 4;
  265. #endif
  266.     /* Since OpenGL can do rescaling for us, stick to the default
  267.      * coordinates and aspect. */
  268.     p_vout->output.i_width  = p_vout->render.i_width;
  269.     p_vout->output.i_height = p_vout->render.i_height;
  270.     p_vout->output.i_aspect = p_vout->render.i_aspect;
  271.     p_vout->fmt_out = p_vout->fmt_in;
  272.     p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
  273.     /* We know the chroma, allocate one buffer which will be used
  274.      * directly by the decoder */
  275.     p_sys->pp_buffer[0] =
  276.         malloc( p_sys->i_tex_width * p_sys->i_tex_height * i_pixel_pitch );
  277.     if( !p_sys->pp_buffer[0] )
  278.         return -1;
  279.     p_sys->pp_buffer[1] =
  280.         malloc( p_sys->i_tex_width * p_sys->i_tex_height * i_pixel_pitch );
  281.     if( !p_sys->pp_buffer[1] )
  282.         return -1;
  283.     p_vout->p_picture[0].i_planes = 1;
  284.     p_vout->p_picture[0].p->p_pixels = p_sys->pp_buffer[0];
  285.     p_vout->p_picture[0].p->i_lines = p_vout->output.i_height;
  286.     p_vout->p_picture[0].p->i_visible_lines = p_vout->output.i_height;
  287.     p_vout->p_picture[0].p->i_pixel_pitch = i_pixel_pitch;
  288.     p_vout->p_picture[0].p->i_pitch = p_vout->output.i_width *
  289.         p_vout->p_picture[0].p->i_pixel_pitch;
  290.     p_vout->p_picture[0].p->i_visible_pitch = p_vout->output.i_width *
  291.         p_vout->p_picture[0].p->i_pixel_pitch;
  292.     p_vout->p_picture[0].i_status = DESTROYED_PICTURE;
  293.     p_vout->p_picture[0].i_type   = DIRECT_PICTURE;
  294.     PP_OUTPUTPICTURE[ 0 ] = &p_vout->p_picture[0];
  295.     I_OUTPUTPICTURES = 1;
  296.     if( p_sys->p_vout->pf_lock &&
  297.         p_sys->p_vout->pf_lock( p_sys->p_vout ) )
  298.     {
  299.         msg_Warn( p_vout, "could not lock OpenGL provider" );
  300.         return 0;
  301.     }
  302.     InitTextures( p_vout );
  303.     glDisable(GL_BLEND);
  304.     glDisable(GL_DEPTH_TEST);
  305.     glDepthMask(GL_FALSE);
  306.     glDisable(GL_CULL_FACE);
  307.     glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
  308.     glClear( GL_COLOR_BUFFER_BIT );
  309.     if( p_sys->p_vout->pf_unlock )
  310.     {
  311.         p_sys->p_vout->pf_unlock( p_sys->p_vout );
  312.     }
  313.     return 0;
  314. }
  315. /*****************************************************************************
  316.  * End: terminate GLX video thread output method
  317.  *****************************************************************************/
  318. static void End( vout_thread_t *p_vout )
  319. {
  320.     vout_sys_t *p_sys = p_vout->p_sys;
  321.     if( p_sys->p_vout->pf_lock &&
  322.         p_sys->p_vout->pf_lock( p_sys->p_vout ) )
  323.     {
  324.         msg_Warn( p_vout, "could not lock OpenGL provider" );
  325.         return;
  326.     }
  327.     glFinish();
  328.     glFlush();
  329.     /* Free the texture buffer*/
  330.     glDeleteTextures( 2, p_sys->p_textures );
  331.     free( p_sys->pp_buffer[0] );
  332.     free( p_sys->pp_buffer[1] );
  333.     if( p_sys->p_vout->pf_unlock )
  334.     {
  335.         p_sys->p_vout->pf_unlock( p_sys->p_vout );
  336.     }
  337.     /* We must release the opengl provider here: opengl requiere init and end
  338.        to be done in the same thread */
  339.     module_unneed( p_sys->p_vout, p_sys->p_vout->p_module );
  340.     vlc_object_release( p_sys->p_vout );
  341. }
  342. /*****************************************************************************
  343.  * Destroy: destroy GLX video thread output method
  344.  *****************************************************************************
  345.  * Terminate an output method created by CreateVout
  346.  *****************************************************************************/
  347. static void DestroyVout( vlc_object_t *p_this )
  348. {
  349.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  350.     vout_sys_t *p_sys = p_vout->p_sys;
  351.     free( p_sys );
  352. }
  353. /*****************************************************************************
  354.  * Manage: handle Sys events
  355.  *****************************************************************************
  356.  * This function should be called regularly by video output thread. It returns
  357.  * a non null value if an error occurred.
  358.  *****************************************************************************/
  359. static int Manage( vout_thread_t *p_vout )
  360. {
  361.     vout_sys_t *p_sys = p_vout->p_sys;
  362.     int i_ret, i_fullscreen_change;
  363.     i_fullscreen_change = ( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE );
  364.     p_vout->fmt_out.i_x_offset = p_sys->p_vout->fmt_in.i_x_offset =
  365.         p_vout->fmt_in.i_x_offset;
  366.     p_vout->fmt_out.i_y_offset = p_sys->p_vout->fmt_in.i_y_offset =
  367.         p_vout->fmt_in.i_y_offset;
  368.     p_vout->fmt_out.i_visible_width = p_sys->p_vout->fmt_in.i_visible_width =
  369.         p_vout->fmt_in.i_visible_width;
  370.     p_vout->fmt_out.i_visible_height = p_sys->p_vout->fmt_in.i_visible_height =
  371.         p_vout->fmt_in.i_visible_height;
  372.     p_vout->fmt_out.i_aspect = p_sys->p_vout->fmt_in.i_aspect =
  373.         p_vout->fmt_in.i_aspect;
  374.     p_vout->fmt_out.i_sar_num = p_sys->p_vout->fmt_in.i_sar_num =
  375.         p_vout->fmt_in.i_sar_num;
  376.     p_vout->fmt_out.i_sar_den = p_sys->p_vout->fmt_in.i_sar_den =
  377.         p_vout->fmt_in.i_sar_den;
  378.     p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
  379.     p_sys->p_vout->i_changes = p_vout->i_changes;
  380.     i_ret = p_sys->p_vout->pf_manage( p_sys->p_vout );
  381.     p_vout->i_changes = p_sys->p_vout->i_changes;
  382. #ifdef __APPLE__
  383.     if( p_sys->p_vout->pf_lock &&
  384.         p_sys->p_vout->pf_lock( p_sys->p_vout ) )
  385.     {
  386.         msg_Warn( p_vout, "could not lock OpenGL provider" );
  387.         return i_ret;
  388.     }
  389.     /* On OS X, we create the window and the GL view when entering
  390.        fullscreen - the textures have to be inited again */
  391.     if( i_fullscreen_change )
  392.     {
  393.         InitTextures( p_vout );
  394.     }
  395.     if( p_sys->p_vout->pf_unlock )
  396.     {
  397.         p_sys->p_vout->pf_unlock( p_sys->p_vout );
  398.     }
  399. #endif
  400. // to align in real time in OPENGL
  401.     if (p_sys->p_vout->i_alignment != p_vout->i_alignment)
  402.     {
  403.         p_vout->i_changes |= VOUT_CROP_CHANGE;        //to force change
  404.         p_sys->p_vout->i_alignment = p_vout->i_alignment;    
  405.     }
  406.     /* forward signal that autoscale toggle has changed */
  407.     if (p_vout->i_changes & VOUT_SCALE_CHANGE )
  408.     {
  409.         p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
  410.         p_sys->p_vout->i_changes |= VOUT_SCALE_CHANGE;
  411.     }
  412.     /* forward signal that scale has changed */
  413.     if (p_vout->i_changes & VOUT_ZOOM_CHANGE )
  414.     {
  415.         p_vout->i_changes &= ~VOUT_ZOOM_CHANGE;
  416.         p_sys->p_vout->i_changes |= VOUT_ZOOM_CHANGE;
  417.     }
  418.     return i_ret;
  419. }
  420. /*****************************************************************************
  421.  * Render: render previously calculated output
  422.  *****************************************************************************/
  423. static void Render( vout_thread_t *p_vout, picture_t *p_pic )
  424. {
  425.     VLC_UNUSED(p_pic);
  426.     vout_sys_t *p_sys = p_vout->p_sys;
  427.     /* On Win32/GLX, we do this the usual way:
  428.        + Fill the buffer with new content,
  429.        + Reload the texture,
  430.        + Use the texture.
  431.        On OS X with VRAM or AGP texturing, the order has to be:
  432.        + Reload the texture,
  433.        + Fill the buffer with new content,
  434.        + Use the texture.
  435.        (Thanks to gcc from the Arstechnica forums for the tip)
  436.        Therefore, we have to use two buffers and textures. On Win32/GLX,
  437.        we reload the texture to be displayed and use it right away. On
  438.        OS X, we first render, then reload the texture to be used next
  439.        time. */
  440.     if( p_sys->p_vout->pf_lock &&
  441.         p_sys->p_vout->pf_lock( p_sys->p_vout ) )
  442.     {
  443.         msg_Warn( p_vout, "could not lock OpenGL provider" );
  444.         return;
  445.     }
  446. #ifdef __APPLE__
  447.     int i_new_index;
  448.     i_new_index = ( p_sys->i_index + 1 ) & 1;
  449.     /* Update the texture */
  450.     glBindTexture( VLCGL_TARGET, p_sys->p_textures[i_new_index] );
  451.     glTexSubImage2D( VLCGL_TARGET, 0, 0, 0,
  452.                      p_vout->fmt_out.i_width,
  453.                      p_vout->fmt_out.i_height,
  454.                      VLCGL_FORMAT, VLCGL_TYPE, p_sys->pp_buffer[i_new_index] );
  455.     /* Bind to the previous texture for drawing */
  456.     glBindTexture( VLCGL_TARGET, p_sys->p_textures[p_sys->i_index] );
  457.     /* Switch buffers */
  458.     p_sys->i_index = i_new_index;
  459.     p_pic->p->p_pixels = p_sys->pp_buffer[p_sys->i_index];
  460. #else
  461.     /* Update the texture */
  462.     glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0,
  463.                      p_vout->fmt_out.i_width,
  464.                      p_vout->fmt_out.i_height,
  465.                      VLCGL_FORMAT, VLCGL_TYPE, p_sys->pp_buffer[0] );
  466. #endif
  467.     if( p_sys->p_vout->pf_unlock )
  468.     {
  469.         p_sys->p_vout->pf_unlock( p_sys->p_vout );
  470.     }
  471. }
  472. /*****************************************************************************
  473.  * DisplayVideo: displays previously rendered output
  474.  *****************************************************************************/
  475. static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
  476. {
  477.     VLC_UNUSED(p_pic);
  478.     vout_sys_t *p_sys = p_vout->p_sys;
  479.     float f_width, f_height, f_x, f_y;
  480.     if( p_sys->p_vout->pf_lock &&
  481.         p_sys->p_vout->pf_lock( p_sys->p_vout ) )
  482.     {
  483.         msg_Warn( p_vout, "could not lock OpenGL provider" );
  484.         return;
  485.     }
  486.     /* glTexCoord works differently with GL_TEXTURE_2D and
  487.        GL_TEXTURE_RECTANGLE_EXT */
  488. #ifdef __APPLE__
  489.     f_x = (float)p_vout->fmt_out.i_x_offset;
  490.     f_y = (float)p_vout->fmt_out.i_y_offset;
  491.     f_width = (float)p_vout->fmt_out.i_x_offset +
  492.               (float)p_vout->fmt_out.i_visible_width;
  493.     f_height = (float)p_vout->fmt_out.i_y_offset +
  494.                (float)p_vout->fmt_out.i_visible_height;
  495. #else
  496.     f_x = (float)p_vout->fmt_out.i_x_offset / p_sys->i_tex_width;
  497.     f_y = (float)p_vout->fmt_out.i_y_offset / p_sys->i_tex_height;
  498.     f_width = ( (float)p_vout->fmt_out.i_x_offset +
  499.                 p_vout->fmt_out.i_visible_width ) / p_sys->i_tex_width;
  500.     f_height = ( (float)p_vout->fmt_out.i_y_offset +
  501.                  p_vout->fmt_out.i_visible_height ) / p_sys->i_tex_height;
  502. #endif
  503.     /* Why drawing here and not in Render()? Because this way, the
  504.        OpenGL providers can call pf_display to force redraw. Currently,
  505.        the OS X provider uses it to get a smooth window resizing */
  506.     glClear( GL_COLOR_BUFFER_BIT );
  507.     glEnable( VLCGL_TARGET );
  508.     glBegin( GL_POLYGON );
  509.     glTexCoord2f( f_x, f_y ); glVertex2f( -1.0, 1.0 );
  510.     glTexCoord2f( f_width, f_y ); glVertex2f( 1.0, 1.0 );
  511.     glTexCoord2f( f_width, f_height ); glVertex2f( 1.0, -1.0 );
  512.     glTexCoord2f( f_x, f_height ); glVertex2f( -1.0, -1.0 );
  513.     glEnd();
  514.     glDisable( VLCGL_TARGET );
  515.     p_sys->p_vout->pf_swap( p_sys->p_vout );
  516.     if( p_sys->p_vout->pf_unlock )
  517.     {
  518.         p_sys->p_vout->pf_unlock( p_sys->p_vout );
  519.     }
  520. }
  521. int GetAlignedSize( int i_size )
  522. {
  523.     /* Return the nearest power of 2 */
  524.     int i_result = 1;
  525.     while( i_result < i_size )
  526.     {
  527.         i_result *= 2;
  528.     }
  529.     return i_result;
  530. }
  531. /*****************************************************************************
  532.  * Control: control facility for the vout
  533.  *****************************************************************************/
  534. static int Control( vout_thread_t *p_vout, int i_query, va_list args )
  535. {
  536.     vout_sys_t *p_sys = p_vout->p_sys;
  537.     if( p_sys->p_vout->pf_control )
  538.         return p_sys->p_vout->pf_control( p_sys->p_vout, i_query, args );
  539.     return VLC_EGENERIC;
  540. }
  541. static int InitTextures( vout_thread_t *p_vout )
  542. {
  543.     vout_sys_t *p_sys = p_vout->p_sys;
  544.     int i_index;
  545.     glDeleteTextures( 2, p_sys->p_textures );
  546.     glGenTextures( 2, p_sys->p_textures );
  547.     for( i_index = 0; i_index < 2; i_index++ )
  548.     {
  549.         glBindTexture( VLCGL_TARGET, p_sys->p_textures[i_index] );
  550.         /* Set the texture parameters */
  551.         glTexParameterf( VLCGL_TARGET, GL_TEXTURE_PRIORITY, 1.0 );
  552.         glTexParameteri( VLCGL_TARGET, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
  553.         glTexParameteri( VLCGL_TARGET, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
  554.         glTexParameteri( VLCGL_TARGET, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  555.         glTexParameteri( VLCGL_TARGET, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  556.         glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
  557. #ifdef __APPLE__
  558.         /* Tell the driver not to make a copy of the texture but to use
  559.            our buffer */
  560.         glEnable( GL_UNPACK_CLIENT_STORAGE_APPLE );
  561.         glPixelStorei( GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE );
  562. #if 0
  563.         /* Use VRAM texturing */
  564.         glTexParameteri( VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE,
  565.                          GL_STORAGE_CACHED_APPLE );
  566. #else
  567.         /* Use AGP texturing */
  568.         glTexParameteri( VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE,
  569.                          GL_STORAGE_SHARED_APPLE );
  570. #endif
  571. #endif
  572.         /* Call glTexImage2D only once, and use glTexSubImage2D later */
  573.         glTexImage2D( VLCGL_TARGET, 0, 3, p_sys->i_tex_width,
  574.                       p_sys->i_tex_height, 0, VLCGL_FORMAT, VLCGL_TYPE,
  575.                       p_sys->pp_buffer[i_index] );
  576.     }
  577.     return 0;
  578. }
  579. /*****************************************************************************
  580.  * SendEvents: forward mouse and keyboard events to the parent p_vout
  581.  *****************************************************************************/
  582. static int SendEvents( vlc_object_t *p_this, char const *psz_var,
  583.                        vlc_value_t oldval, vlc_value_t newval, void *_p_vout )
  584. {
  585.     VLC_UNUSED(p_this); VLC_UNUSED(oldval);
  586.     return var_Set( (vlc_object_t *)_p_vout, psz_var, newval );
  587. }