opengl.c 36.9 KB
Newer Older
1 2 3
/*****************************************************************************
 * opengl.c: OpenGL video output
 *****************************************************************************
4
 * Copyright (C) 2004 the VideoLAN team
5 6 7 8
 * $Id$
 *
 * Authors: Cyril Deguet <asmax@videolan.org>
 *          Gildas Bazin <gbazin@videolan.org>
9
 *          Eric Petit <titer@m0k.org>
10
 * 		    Cedric Cocquebert <cedric.cocquebert@supelec.fr>
11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
bigben's avatar
bigben committed
24
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 26 27 28 29 30 31 32 33 34 35 36
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <errno.h>                                                 /* ENOMEM */
#include <stdlib.h>                                      /* malloc(), free() */
#include <string.h>

#include <vlc/vlc.h>
#include <vlc/vout.h>

37
#ifdef __APPLE__
38
#include <OpenGL/gl.h>
39 40 41 42 43 44 45 46 47 48 49 50 51
#include <OpenGL/glext.h>

/* On OS X, use GL_TEXTURE_RECTANGLE_EXT instead of GL_TEXTURE_2D.
   This allows sizes which are not powers of 2 */
#define VLCGL_TARGET GL_TEXTURE_RECTANGLE_EXT

/* OS X OpenGL supports YUV. Hehe. */
#define VLCGL_FORMAT GL_YCBCR_422_APPLE
#define VLCGL_TYPE   GL_UNSIGNED_SHORT_8_8_APPLE
#else

#include <GL/gl.h>
#define VLCGL_TARGET GL_TEXTURE_2D
52 53

/* RV16 */
54 55 56
#ifndef GL_UNSIGNED_SHORT_5_6_5
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
#endif
57 58 59 60 61 62 63 64 65 66 67
//#define VLCGL_RGB_FORMAT GL_RGB
//#define VLCGL_RGB_TYPE GL_UNSIGNED_SHORT_5_6_5

/* RV24 */
//#define VLCGL_RGB_FORMAT GL_RGB
//#define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE

/* RV32 */
#define VLCGL_RGB_FORMAT GL_RGBA
#define VLCGL_RGB_TYPE GL_UNSIGNED_BYTE

68 69 70 71 72 73 74 75 76 77
/* YUY2 */
#ifndef YCBCR_MESA
#define YCBCR_MESA 0x8757
#endif
#ifndef UNSIGNED_SHORT_8_8_MESA
#define UNSIGNED_SHORT_8_8_MESA 0x85BA
#endif
#define VLCGL_YUV_FORMAT YCBCR_MESA
#define VLCGL_YUV_TYPE UNSIGNED_SHORT_8_8_MESA

78 79 80
/* Use RGB on Win32/GLX */
#define VLCGL_FORMAT VLCGL_RGB_FORMAT
#define VLCGL_TYPE   VLCGL_RGB_TYPE
81 82
//#define VLCGL_FORMAT VLCGL_YUV_FORMAT
//#define VLCGL_TYPE   VLCGL_YUV_TYPE
83 84
#endif

dionoea's avatar
dionoea committed
85 86 87 88
#ifndef GL_CLAMP_TO_EDGE
#   define GL_CLAMP_TO_EDGE 0x812F
#endif

89 90 91 92
/* OpenGL effects */
#define OPENGL_EFFECT_NONE             1
#define OPENGL_EFFECT_CUBE             2
#define OPENGL_EFFECT_TRANSPARENT_CUBE 4
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
#if defined( HAVE_GL_GLU_H ) || defined( SYS_DARWIN )
    #define OPENGL_MORE_EFFECT		   8
#endif

#ifdef OPENGL_MORE_EFFECT
	#include <math.h>
	#ifdef SYS_DARWIN
		#include <OpenGL/glu.h>
	#else
		#include <GL/glu.h>
	#endif
/* 3D MODEL */
	#define CYLINDER 8
	#define TORUS	 16
	#define SPHERE   32
/*GRID2D TRANSFORMATION */
	#define SQUAREXY 64
	#define SQUARER  128
	#define ASINXY   256
	#define ASINR    512
	#define SINEXY   1024
	#define SINER    2048
	#define INIFILE	 4096					// not used, just for mark end ...
	#define SIGN(x)	 (x < 0 ? (-1) : 1)
	#define PID2     1.570796326794896619231322

	static char *ppsz_effects[] = {
			"none", "cube", "transparent-cube", "cylinder", "torus", "sphere","SQUAREXY","SQUARER", "ASINXY", "ASINR", "SINEXY", "SINER" };
	static char *ppsz_effects_text[] = {
			N_("None"), N_("Cube"), N_("Transparent Cube"), 
			N_("Cylinder"), N_("Torus"), N_("Sphere"), N_("SQUAREXY"),N_("SQUARER"), N_("ASINXY"), N_("ASINR"), N_("SINEXY"), N_("SINER") };
#endif
125

126 127 128 129 130 131 132
/*****************************************************************************
 * Vout interface
 *****************************************************************************/
static int  CreateVout   ( vlc_object_t * );
static void DestroyVout  ( vlc_object_t * );
static int  Init         ( vout_thread_t * );
static void End          ( vout_thread_t * );
133 134
static int  Manage       ( vout_thread_t * );
static void Render       ( vout_thread_t *, picture_t * );
135
static void DisplayVideo ( vout_thread_t *, picture_t * );
136
static int  Control      ( vout_thread_t *, int, va_list );
137

138
static inline int GetAlignedSize( int );
139

Eric Petit's avatar
Eric Petit committed
140
static int InitTextures( vout_thread_t * );
141 142 143
static int SendEvents( vlc_object_t *, char const *,
                       vlc_value_t, vlc_value_t, void * );

144 145 146
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
#ifdef OPENGL_MORE_EFFECT
#define ACCURACY_TEXT N_( "OpenGL sampling accuracy " )
#define ACCURACY_LONGTEXT N_( "Select the accuracy of 3D object sampling(1 = min and 10 = max)" )
#define RADIUS_TEXT N_( "OpenGL Cylinder radius" )
#define RADIUS_LONGTEXT N_( "Radius of the OpenGL cylinder effect, if enabled" )
#define POV_X_TEXT N_("Point of view x-coordinate")
#define POV_X_LONGTEXT N_("Point of view (X coordinate) of the cube/cylinder "\
                           "effect, if enabled.")
#define POV_Y_TEXT N_("Point of view y-coordinate")
#define POV_Y_LONGTEXT N_("Point of view (Y coordinate) of the cube/cylinder "\
                           "effect, if enabled.")
#define POV_Z_TEXT N_("Point of view z-coordinate")
#define POV_Z_LONGTEXT N_("Point of view (Z coordinate) of the cube/cylinder "\
                           "effect, if enabled.")
#endif
zorglub's avatar
zorglub committed
162
#define SPEED_TEXT N_( "OpenGL cube rotation speed" )
163 164
#define SPEED_LONGTEXT N_( "Rotation speed of the OpenGL cube effect, if " \
        "enabled." )
165
#define EFFECT_TEXT N_("Effect")
166
#define EFFECT_LONGTEXT N_( \
167
    "Several visual OpenGL effects are available." )
168

169
#ifndef OPENGL_MORE_EFFECT
170
static char *ppsz_effects[] = {
171
        "none", "cube", "transparent-cube" };
172
static char *ppsz_effects_text[] = {
173
        N_("None"), N_("Cube"), N_("Transparent Cube") };
174
#endif
175

176
vlc_module_begin();
177 178 179
    set_shortname( "OpenGL" );
    set_category( CAT_VIDEO );
    set_subcategory( SUBCAT_VIDEO_VOUT );
180
    set_description( _("OpenGL video output") );
181
#ifdef __APPLE__
182
    set_capability( "video output", 200 );
Eric Petit's avatar
Eric Petit committed
183
#else
184
    set_capability( "video output", 20 );
Eric Petit's avatar
Eric Petit committed
185
#endif
186
    add_shortcut( "opengl" );
zorglub's avatar
zorglub committed
187
    add_float( "opengl-cube-speed", 2.0, NULL, SPEED_TEXT,
188
                    SPEED_LONGTEXT, VLC_TRUE );
189 190 191 192 193 194 195 196 197 198 199 200 201
#ifdef OPENGL_MORE_EFFECT
    add_integer_with_range( "opengl-accuracy", 4, 1, 10, NULL, ACCURACY_TEXT,
                    ACCURACY_LONGTEXT, VLC_TRUE );
    add_float_with_range( "opengl-pov-x", 0.0, -1.0, 1.0, NULL, POV_X_TEXT,
                    POV_X_LONGTEXT, VLC_TRUE );
    add_float_with_range( "opengl-pov-y", 0.0, -1.0, 1.0, NULL, POV_Y_TEXT,
                    POV_Y_LONGTEXT, VLC_TRUE );
    add_float_with_range( "opengl-pov-z", -1.0, -1.0, 1.0, NULL, POV_Z_TEXT,
                    POV_Z_LONGTEXT, VLC_TRUE );
    add_float( "opengl-cylinder-radius", -100.0, NULL, RADIUS_TEXT,
                    RADIUS_LONGTEXT, VLC_TRUE );

#endif
202
    set_callbacks( CreateVout, DestroyVout );
203
    add_string( "opengl-effect", "none", NULL, EFFECT_TEXT,
204
                 EFFECT_LONGTEXT, VLC_FALSE );
205
		change_string_list( ppsz_effects, ppsz_effects_text, 0 );
206 207 208 209 210 211 212 213 214 215 216 217
vlc_module_end();

/*****************************************************************************
 * vout_sys_t: video output method descriptor
 *****************************************************************************
 * This structure is part of the video output thread descriptor.
 * It describes the OpenGL specific properties of the output thread.
 *****************************************************************************/
struct vout_sys_t
{
    vout_thread_t *p_vout;

218
    uint8_t    *pp_buffer[2];
219 220 221
    int         i_index;
    int         i_tex_width;
    int         i_tex_height;
222
    GLuint      p_textures[2];
223

224
    int         i_effect;
zorglub's avatar
zorglub committed
225 226

    float       f_speed;
227
    float       f_radius;
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
};

/*****************************************************************************
 * CreateVout: This function allocates and initializes the OpenGL vout method.
 *****************************************************************************/
static int CreateVout( vlc_object_t *p_this )
{
    vout_thread_t *p_vout = (vout_thread_t *)p_this;
    vout_sys_t *p_sys;

    /* Allocate structure */
    p_vout->p_sys = p_sys = malloc( sizeof( vout_sys_t ) );
    if( p_sys == NULL )
    {
        msg_Err( p_vout, "out of memory" );
        return VLC_EGENERIC;
    }

246
    var_Create( p_vout, "opengl-effect", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
247

248
    p_sys->i_index = 0;
249
#ifdef __APPLE__
250 251
    p_sys->i_tex_width  = p_vout->fmt_in.i_width;
    p_sys->i_tex_height = p_vout->fmt_in.i_height;
252
#else
253
    /* A texture must have a size aligned on a power of 2 */
254 255
    p_sys->i_tex_width  = GetAlignedSize( p_vout->fmt_in.i_width );
    p_sys->i_tex_height = GetAlignedSize( p_vout->fmt_in.i_height );
256
#endif
257 258 259 260 261 262 263 264 265 266 267 268

    msg_Dbg( p_vout, "Texture size: %dx%d", p_sys->i_tex_width,
             p_sys->i_tex_height );

    /* Get window */
    p_sys->p_vout =
        (vout_thread_t *)vlc_object_create( p_this, VLC_OBJECT_OPENGL );
    if( p_sys->p_vout == NULL )
    {
        msg_Err( p_vout, "out of memory" );
        return VLC_ENOMEM;
    }
269
    vlc_object_attach( p_sys->p_vout, p_this );
270 271 272 273

    p_sys->p_vout->i_window_width = p_vout->i_window_width;
    p_sys->p_vout->i_window_height = p_vout->i_window_height;
    p_sys->p_vout->b_fullscreen = p_vout->b_fullscreen;
274 275 276
    p_sys->p_vout->render.i_width = p_vout->render.i_width;
    p_sys->p_vout->render.i_height = p_vout->render.i_height;
    p_sys->p_vout->render.i_aspect = p_vout->render.i_aspect;
277 278
    p_sys->p_vout->fmt_render = p_vout->fmt_render;
    p_sys->p_vout->fmt_in = p_vout->fmt_in;
279 280
    p_sys->p_vout->b_scale = p_vout->b_scale;
    p_sys->p_vout->i_alignment = p_vout->i_alignment;
281 282 283 284 285

    p_sys->p_vout->p_module =
        module_Need( p_sys->p_vout, "opengl provider", NULL, 0 );
    if( p_sys->p_vout->p_module == NULL )
    {
Eric Petit's avatar
Eric Petit committed
286
        msg_Warn( p_vout, "No OpenGL provider found" );
287
        vlc_object_detach( p_sys->p_vout );
288 289 290 291
        vlc_object_destroy( p_sys->p_vout );
        return VLC_ENOOBJ;
    }

zorglub's avatar
zorglub committed
292
    p_sys->f_speed = var_CreateGetFloat( p_vout, "opengl-cube-speed" );
293
    p_sys->f_radius = var_CreateGetFloat( p_vout, "opengl-cylinder-radius" );
zorglub's avatar
zorglub committed
294

295 296
    p_vout->pf_init = Init;
    p_vout->pf_end = End;
297
    p_vout->pf_manage = Manage;
298 299
    p_vout->pf_render = Render;
    p_vout->pf_display = DisplayVideo;
300
    p_vout->pf_control = Control;
301

302
    /* Forward events from the opengl provider */
Eric Petit's avatar
Eric Petit committed
303 304
    var_Create( p_sys->p_vout, "mouse-x", VLC_VAR_INTEGER );
    var_Create( p_sys->p_vout, "mouse-y", VLC_VAR_INTEGER );
305
    var_Create( p_sys->p_vout, "mouse-moved", VLC_VAR_BOOL );
Eric Petit's avatar
Eric Petit committed
306
    var_Create( p_sys->p_vout, "mouse-clicked", VLC_VAR_INTEGER );
307
    var_Create( p_sys->p_vout, "mouse-button-down", VLC_VAR_INTEGER );
308 309
    var_Create( p_sys->p_vout, "video-on-top",
                VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
Eric Petit's avatar
Eric Petit committed
310

311 312 313 314
    var_AddCallback( p_sys->p_vout, "mouse-x", SendEvents, p_vout );
    var_AddCallback( p_sys->p_vout, "mouse-y", SendEvents, p_vout );
    var_AddCallback( p_sys->p_vout, "mouse-moved", SendEvents, p_vout );
    var_AddCallback( p_sys->p_vout, "mouse-clicked", SendEvents, p_vout );
315
    var_AddCallback( p_sys->p_vout, "mouse-button-down", SendEvents, p_vout );
316

317 318 319 320 321 322 323 324 325
    return VLC_SUCCESS;
}

/*****************************************************************************
 * Init: initialize the OpenGL video thread output method
 *****************************************************************************/
static int Init( vout_thread_t *p_vout )
{
    vout_sys_t *p_sys = p_vout->p_sys;
Eric Petit's avatar
Eric Petit committed
326
    int i_pixel_pitch;
327
    vlc_value_t val;
328

329 330
    p_sys->p_vout->pf_init( p_sys->p_vout );

331
/* TODO: We use YCbCr on Mac which is Y422, but on OSX it seems to == YUY2. Verify */
332
#if ( defined( WORDS_BIGENDIAN ) && VLCGL_FORMAT == GL_YCBCR_422_APPLE ) || (VLCGL_FORMAT == YCBCR_MESA)
333 334
    p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
    i_pixel_pitch = 2;
335

336
#elif (VLCGL_FORMAT == GL_YCBCR_422_APPLE)
337
    p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
338 339
    i_pixel_pitch = 2;

340 341
#elif VLCGL_FORMAT == GL_RGB
#   if VLCGL_TYPE == GL_UNSIGNED_BYTE
342
    p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
343 344 345 346 347
#       if defined( WORDS_BIGENDIAN )
    p_vout->output.i_rmask = 0x00ff0000;
    p_vout->output.i_gmask = 0x0000ff00;
    p_vout->output.i_bmask = 0x000000ff;
#       else
348 349 350
    p_vout->output.i_rmask = 0x000000ff;
    p_vout->output.i_gmask = 0x0000ff00;
    p_vout->output.i_bmask = 0x00ff0000;
351
#       endif
352 353 354
    i_pixel_pitch = 3;
#   else
    p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
355 356 357 358 359
#       if defined( WORDS_BIGENDIAN )
    p_vout->output.i_rmask = 0x001f;
    p_vout->output.i_gmask = 0x07e0;
    p_vout->output.i_bmask = 0xf800;
#       else
360 361 362
    p_vout->output.i_rmask = 0xf800;
    p_vout->output.i_gmask = 0x07e0;
    p_vout->output.i_bmask = 0x001f;
363
#       endif
364 365 366 367
    i_pixel_pitch = 2;
#   endif
#else
    p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
368 369 370 371 372
#       if defined( WORDS_BIGENDIAN )
    p_vout->output.i_rmask = 0xff000000;
    p_vout->output.i_gmask = 0x00ff0000;
    p_vout->output.i_bmask = 0x0000ff00;
#       else
373 374 375
    p_vout->output.i_rmask = 0x000000ff;
    p_vout->output.i_gmask = 0x0000ff00;
    p_vout->output.i_bmask = 0x00ff0000;
376
#       endif
377 378 379 380 381 382 383 384 385
    i_pixel_pitch = 4;
#endif

    /* Since OpenGL can do rescaling for us, stick to the default
     * coordinates and aspect. */
    p_vout->output.i_width  = p_vout->render.i_width;
    p_vout->output.i_height = p_vout->render.i_height;
    p_vout->output.i_aspect = p_vout->render.i_aspect;

386 387 388
    p_vout->fmt_out = p_vout->fmt_in;
    p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;

389
    /* We know the chroma, allocate one buffer which will be used
390
     * directly by the decoder */
391 392 393 394
    p_sys->pp_buffer[0] =
        malloc( p_sys->i_tex_width * p_sys->i_tex_height * i_pixel_pitch );
    if( !p_sys->pp_buffer[0] )
    {
395
        msg_Err( p_vout, "out of memory" );
396 397 398
        return -1;
    }
    p_sys->pp_buffer[1] =
399
        malloc( p_sys->i_tex_width * p_sys->i_tex_height * i_pixel_pitch );
400
    if( !p_sys->pp_buffer[1] )
401
    {
402
        msg_Err( p_vout, "out of memory" );
403 404 405
        return -1;
    }

406 407
    p_vout->p_picture[0].i_planes = 1;
    p_vout->p_picture[0].p->p_pixels = p_sys->pp_buffer[0];
408
    p_vout->p_picture[0].p->i_lines = p_vout->output.i_height;
409
    p_vout->p_picture[0].p->i_visible_lines = p_vout->output.i_height;
410
    p_vout->p_picture[0].p->i_pixel_pitch = i_pixel_pitch;
411
    p_vout->p_picture[0].p->i_pitch = p_vout->output.i_width *
412 413 414 415 416 417 418 419
        p_vout->p_picture[0].p->i_pixel_pitch;
    p_vout->p_picture[0].p->i_visible_pitch = p_vout->output.i_width *
        p_vout->p_picture[0].p->i_pixel_pitch;

    p_vout->p_picture[0].i_status = DESTROYED_PICTURE;
    p_vout->p_picture[0].i_type   = DIRECT_PICTURE;

    PP_OUTPUTPICTURE[ 0 ] = &p_vout->p_picture[0];
420

421
    I_OUTPUTPICTURES = 1;
422

423 424 425 426 427 428 429
    if( p_sys->p_vout->pf_lock &&
        p_sys->p_vout->pf_lock( p_sys->p_vout ) )
    {
        msg_Warn( p_vout, "could not lock OpenGL provider" );
        return 0;
    }

Eric Petit's avatar
Eric Petit committed
430
    InitTextures( p_vout );
431

432 433 434 435
    glDisable(GL_BLEND);
    glDisable(GL_DEPTH_TEST);
    glDepthMask(GL_FALSE);
    glDisable(GL_CULL_FACE);
436
    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
437 438
    glClear( GL_COLOR_BUFFER_BIT );

439 440 441 442 443 444 445
    /* Check if the user asked for useless visual effects */
    var_Get( p_vout, "opengl-effect", &val );
    if( !val.psz_string || !strcmp( val.psz_string, "none" ))
    {
        p_sys->i_effect = OPENGL_EFFECT_NONE;
    }
    else if( !strcmp( val.psz_string, "cube" ) )
446
    {
447 448
        p_sys->i_effect = OPENGL_EFFECT_CUBE;

449
        glEnable( GL_CULL_FACE);
450 451 452 453
    }
    else if( !strcmp( val.psz_string, "transparent-cube" ) )
    {
        p_sys->i_effect = OPENGL_EFFECT_TRANSPARENT_CUBE;
454

455 456 457 458 459 460
        glDisable( GL_DEPTH_TEST );
        glEnable( GL_BLEND );
        glBlendFunc( GL_SRC_ALPHA, GL_ONE );
    }
    else
    {
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
#ifdef OPENGL_MORE_EFFECT
		p_sys->i_effect = 3;
        while (( strcmp( val.psz_string, ppsz_effects[p_sys->i_effect]) ) && (pow(2,p_sys->i_effect) < INIFILE))
        {
            p_sys->i_effect ++;
        }
		if (pow(2,p_sys->i_effect) < INIFILE) 
			p_sys->i_effect = pow(2,p_sys->i_effect);
		else if ( strcmp( val.psz_string, ppsz_effects[p_sys->i_effect]))
		{
			msg_Warn( p_vout, "no valid opengl effect provided, using "
					  "\"none\"" );
			p_sys->i_effect = OPENGL_EFFECT_NONE;
		}
#else
476 477 478
        msg_Warn( p_vout, "no valid opengl effect provided, using "
                  "\"none\"" );
        p_sys->i_effect = OPENGL_EFFECT_NONE;
479
#endif
480 481 482 483 484 485
    }
    if( val.psz_string ) free( val.psz_string );

    if( p_sys->i_effect & ( OPENGL_EFFECT_CUBE |
                OPENGL_EFFECT_TRANSPARENT_CUBE ) )
    {
486 487 488 489 490 491 492 493
        /* Set the perpective */
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
        glFrustum( -1.0, 1.0, -1.0, 1.0, 3.0, 20.0 );
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();
        glTranslatef( 0.0, 0.0, - 5.0 );
    }
494 495 496 497 498 499 500 501 502 503
#ifdef OPENGL_MORE_EFFECT
	else 
    {
        /* Set the perpective */
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
        glFrustum( -1.0, 1.0, -1.0, 1.0, 3.0, 20.0 );
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();
        glTranslatef( 0.0, 0.0, -3.0 );
504

505 506 507 508 509 510 511
		float f_pov_x, f_pov_y, f_pov_z;
		f_pov_x = var_CreateGetFloat( p_vout, "opengl-pov-x");
		f_pov_y = var_CreateGetFloat( p_vout, "opengl-pov-y");
		f_pov_z = var_CreateGetFloat( p_vout, "opengl-pov-z");
		gluLookAt(0, 0, 0, f_pov_x, f_pov_y, f_pov_z, 0, 1, 0);
    }
#endif
512 513 514 515 516
    if( p_sys->p_vout->pf_unlock )
    {
        p_sys->p_vout->pf_unlock( p_sys->p_vout );
    }

517 518 519 520 521 522 523 524
    return 0;
}

/*****************************************************************************
 * End: terminate GLX video thread output method
 *****************************************************************************/
static void End( vout_thread_t *p_vout )
{
525 526 527 528 529 530 531 532 533
    vout_sys_t *p_sys = p_vout->p_sys;

    if( p_sys->p_vout->pf_lock &&
        p_sys->p_vout->pf_lock( p_sys->p_vout ) )
    {
        msg_Warn( p_vout, "could not lock OpenGL provider" );
        return;
    }

534 535
    glFinish();
    glFlush();
536

537 538 539 540 541
    /* Free the texture buffer*/
    glDeleteTextures( 2, p_sys->p_textures );
    if( p_sys->pp_buffer[0] ) free( p_sys->pp_buffer[0] );
    if( p_sys->pp_buffer[1] ) free( p_sys->pp_buffer[1] );

542 543 544 545
    if( p_sys->p_vout->pf_unlock )
    {
        p_sys->p_vout->pf_unlock( p_sys->p_vout );
    }
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
}

/*****************************************************************************
 * Destroy: destroy GLX video thread output method
 *****************************************************************************
 * Terminate an output method created by CreateVout
 *****************************************************************************/
static void DestroyVout( vlc_object_t *p_this )
{
    vout_thread_t *p_vout = (vout_thread_t *)p_this;
    vout_sys_t *p_sys = p_vout->p_sys;

    module_Unneed( p_sys->p_vout, p_sys->p_vout->p_module );
    vlc_object_detach( p_sys->p_vout );
    vlc_object_destroy( p_sys->p_vout );

    free( p_sys );
}

565 566 567 568
/*****************************************************************************
 * Manage: handle Sys events
 *****************************************************************************
 * This function should be called regularly by video output thread. It returns
Sam Hocevar's avatar
Sam Hocevar committed
569
 * a non null value if an error occurred.
570 571 572 573
 *****************************************************************************/
static int Manage( vout_thread_t *p_vout )
{
    vout_sys_t *p_sys = p_vout->p_sys;
Eric Petit's avatar
Eric Petit committed
574 575 576 577
    int i_ret, i_fullscreen_change;

    i_fullscreen_change = ( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE );

578 579 580 581 582 583 584 585
    p_vout->fmt_out.i_x_offset = p_sys->p_vout->fmt_in.i_x_offset =
        p_vout->fmt_in.i_x_offset;
    p_vout->fmt_out.i_y_offset = p_sys->p_vout->fmt_in.i_y_offset =
        p_vout->fmt_in.i_y_offset;
    p_vout->fmt_out.i_visible_width = p_sys->p_vout->fmt_in.i_visible_width =
        p_vout->fmt_in.i_visible_width;
    p_vout->fmt_out.i_visible_height = p_sys->p_vout->fmt_in.i_visible_height =
        p_vout->fmt_in.i_visible_height;
586 587 588 589 590 591 592
    p_vout->fmt_out.i_aspect = p_sys->p_vout->fmt_in.i_aspect =
        p_vout->fmt_in.i_aspect;
    p_vout->fmt_out.i_sar_num = p_sys->p_vout->fmt_in.i_sar_num =
        p_vout->fmt_in.i_sar_num;
    p_vout->fmt_out.i_sar_den = p_sys->p_vout->fmt_in.i_sar_den =
        p_vout->fmt_in.i_sar_den;
    p_vout->output.i_aspect = p_vout->fmt_in.i_aspect;
593

Eric Petit's avatar
Eric Petit committed
594 595 596 597
    p_sys->p_vout->i_changes = p_vout->i_changes;
    i_ret = p_sys->p_vout->pf_manage( p_sys->p_vout );
    p_vout->i_changes = p_sys->p_vout->i_changes;

598
#ifdef __APPLE__
599 600 601 602 603 604 605
    if( p_sys->p_vout->pf_lock &&
        p_sys->p_vout->pf_lock( p_sys->p_vout ) )
    {
        msg_Warn( p_vout, "could not lock OpenGL provider" );
        return i_ret;
    }

Eric Petit's avatar
Eric Petit committed
606 607 608 609 610 611 612 613 614
    /* On OS X, we create the window and the GL view when entering
       fullscreen - the textures have to be inited again */
    if( i_fullscreen_change )
    {
        InitTextures( p_vout );

        switch( p_sys->i_effect )
        {
            case OPENGL_EFFECT_CUBE:
615 616 617 618 619 620 621 622 623 624 625
#ifdef OPENGL_MORE_EFFECT
			case CYLINDER:
			case TORUS:
			case SPHERE:
			case SQUAREXY:
			case SQUARER:
			case ASINXY:
			case ASINR:
			case SINEXY:
			case SINER:
#endif            
Eric Petit's avatar
Eric Petit committed
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
                glEnable( GL_CULL_FACE );
                break;

            case OPENGL_EFFECT_TRANSPARENT_CUBE:
                glDisable( GL_DEPTH_TEST );
                glEnable( GL_BLEND );
                glBlendFunc( GL_SRC_ALPHA, GL_ONE );
                break;
        }

        if( p_sys->i_effect & ( OPENGL_EFFECT_CUBE |
                    OPENGL_EFFECT_TRANSPARENT_CUBE ) )
        {
            /* Set the perpective */
            glMatrixMode( GL_PROJECTION );
            glLoadIdentity();
            glFrustum( -1.0, 1.0, -1.0, 1.0, 3.0, 20.0 );
            glMatrixMode( GL_MODELVIEW );
            glLoadIdentity();
            glTranslatef( 0.0, 0.0, - 5.0 );
        }
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
#ifdef OPENGL_MORE_EFFECT
		else 
	    {
	        glMatrixMode( GL_PROJECTION );
	        glLoadIdentity();
	        glFrustum( -1.0, 1.0, -1.0, 1.0, 3.0, 20.0 );
	        glMatrixMode( GL_MODELVIEW );
	        glLoadIdentity();
	        glTranslatef( 0.0, 0.0, -3.0 );
	
			float f_pov_x, f_pov_y, f_pov_z;
			f_pov_x = var_CreateGetFloat( p_vout, "opengl-pov-x");
			f_pov_y = var_CreateGetFloat( p_vout, "opengl-pov-y");
			f_pov_z = var_CreateGetFloat( p_vout, "opengl-pov-z");
			gluLookAt(0, 0, 0, f_pov_x, f_pov_y, f_pov_z, 0, 1, 0);
	    }
#endif        
Eric Petit's avatar
Eric Petit committed
664
    }
665 666 667 668 669

    if( p_sys->p_vout->pf_unlock )
    {
        p_sys->p_vout->pf_unlock( p_sys->p_vout );
    }
Eric Petit's avatar
Eric Petit committed
670 671 672
#endif

    return i_ret;
673 674
}

675 676 677 678 679 680
/*****************************************************************************
 * Render: render previously calculated output
 *****************************************************************************/
static void Render( vout_thread_t *p_vout, picture_t *p_pic )
{
    vout_sys_t *p_sys = p_vout->p_sys;
681

682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
    /* On Win32/GLX, we do this the usual way:
       + Fill the buffer with new content,
       + Reload the texture,
       + Use the texture.

       On OS X with VRAM or AGP texturing, the order has to be:
       + Reload the texture,
       + Fill the buffer with new content,
       + Use the texture.

       (Thanks to gcc from the Arstechnica forums for the tip)

       Therefore, we have to use two buffers and textures. On Win32/GLX,
       we reload the texture to be displayed and use it right away. On
       OS X, we first render, then reload the texture to be used next
       time. */

699 700 701 702 703 704 705
    if( p_sys->p_vout->pf_lock &&
        p_sys->p_vout->pf_lock( p_sys->p_vout ) )
    {
        msg_Warn( p_vout, "could not lock OpenGL provider" );
        return;
    }

706
#ifdef __APPLE__
707 708 709
    int i_new_index;
    i_new_index = ( p_sys->i_index + 1 ) & 1;

710

711 712
    /* Update the texture */
    glBindTexture( VLCGL_TARGET, p_sys->p_textures[i_new_index] );
713 714 715
    glTexSubImage2D( VLCGL_TARGET, 0, 0, 0,
                     p_vout->fmt_out.i_width,
                     p_vout->fmt_out.i_height,
716
                     VLCGL_FORMAT, VLCGL_TYPE, p_sys->pp_buffer[i_new_index] );
717 718

    /* Bind to the previous texture for drawing */
719 720
    glBindTexture( VLCGL_TARGET, p_sys->p_textures[p_sys->i_index] );

721 722 723 724 725
    /* Switch buffers */
    p_sys->i_index = i_new_index;
    p_pic->p->p_pixels = p_sys->pp_buffer[p_sys->i_index];

#else
726
    /* Update the texture */
727 728 729
    glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0,
                     p_vout->fmt_out.i_width,
                     p_vout->fmt_out.i_height,
730
                     VLCGL_FORMAT, VLCGL_TYPE, p_sys->pp_buffer[0] );
731
#endif
732 733 734 735 736

    if( p_sys->p_vout->pf_unlock )
    {
        p_sys->p_vout->pf_unlock( p_sys->p_vout );
    }
737 738
}

739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848

#ifdef OPENGL_MORE_EFFECT
/*****************************************************************************
 *   Transform: Calculate the distorted grid coordinates
 *****************************************************************************/
void Transform(float p, int distortion, float width, float height,int i, int j, int i_visible_width, int i_visible_height, double *ix,double *iy)
{
   double x,y,xnew,ynew;
   double r,theta,rnew,thetanew;

   x = (double)i * (width / ((double)i_visible_width));
   y = (double)j * (height / ((double)i_visible_height));

   x = (2.0 * (double)x / width) - 1;
   y = (2.0 * (double)y / height) - 1;
   xnew = x;
   ynew = y;
   r = sqrt(x*x+y*y);
   theta = atan2(y,x);

   switch (distortion) 
   {
/* GRID2D TRANSFORMATION */
	   case SINEXY:
		  xnew = sin(PID2*x);
		  ynew = sin(PID2*y);
		  break;
	   case SINER:
		  rnew = sin(PID2*r);
		  thetanew = theta;
		  xnew = rnew * cos(thetanew);
		  ynew = rnew * sin(thetanew);
		  break;
	   case SQUAREXY:
		  xnew = x*x*SIGN(x);
		  ynew = y*y*SIGN(y);
		  break;
	   case SQUARER:
		  rnew = r*r;
		  thetanew = theta;
		  xnew = rnew * cos(thetanew);
		  ynew = rnew * sin(thetanew);
		  break;
	   case ASINXY:
		  xnew = asin(x) / PID2;
		  ynew = asin(y) / PID2;
		  break;
	   case ASINR:
		  rnew = asin(r) / PID2;
		  thetanew = theta;
		  xnew = rnew * cos(thetanew);
		  ynew = rnew * sin(thetanew);
		  break;
/* OTHER WAY: 3D MODEL */
	   default:
		  xnew = x;
		  ynew = y;
   }

   *ix = width * (xnew + 1) / (2.0);
   *iy = height * (ynew + 1) / (2.0);
}


/*****************************************************************************
 *   Z_Compute: Calculate the Z-coordinate
 *****************************************************************************/
float Z_Compute(float p, int distortion, float x, float y)
{
  float f_z = 0.0;
  double d_p = p / 100.0;

  switch (distortion) 
   {
/* 3D MODEL */
	   case CYLINDER:
		  if (d_p > 0) 
			f_z = (1 - d_p * d_p) / (2 * d_p) - sqrt(fabs((d_p * d_p + 1) / (2 * d_p) * (d_p * d_p + 1) / (2 * d_p) - x * x));
		  else
			f_z = (1 - d_p * d_p) / (2 * d_p) + d_p + sqrt(fabs((d_p * d_p + 1) / (2 * d_p) * (d_p * d_p + 1) / (2 * d_p) - x * x));
		  break;
	   case TORUS:
		  if (d_p > 0) 
		    f_z =  (1 - d_p * d_p) / (d_p) - sqrt(fabs((d_p * d_p + 1) / (2 * d_p) * (d_p * d_p + 1) / (2 * d_p) - x * x)) - sqrt(fabs((d_p * d_p + 1) / (2 * d_p) * (d_p * d_p + 1) / (2 * d_p) - y * y));
		  else
			f_z =  (1 - d_p * d_p) / (d_p) + 2 * d_p + sqrt(fabs((d_p * d_p + 1) / (2 * d_p) * (d_p * d_p + 1) / (2 * d_p) - x * x)) + sqrt(fabs((d_p * d_p + 1) / (2 * d_p) * (d_p * d_p + 1) / (2 * d_p) - y * y));
		  break;
	   case SPHERE:
		  if (d_p > 0) 
   		    f_z = (1 - d_p * d_p) / (2 * d_p) - sqrt(fabs((d_p * d_p + 1) / (2 * d_p) * (d_p * d_p + 1) / (2 * d_p) - x * x - y * y));
		  else
			f_z = (1 - d_p * d_p) / (2 * d_p) + d_p + sqrt(fabs((d_p * d_p + 1) / (2 * d_p) * (d_p * d_p + 1) / (2 * d_p) - x * x - y * y));
		  break;
/* OTHER WAY: GRID2D TRANSFORMATION */
	   case SINEXY:;
	   case SINER:
	   case SQUAREXY:
	   case SQUARER:;
	   case ASINXY:
	   case ASINR:
		  f_z = 0.0;
		  break;
	   default:
		   f_z = 0.0;
   }
  return f_z;
}
#endif


849 850 851 852 853 854
/*****************************************************************************
 * DisplayVideo: displays previously rendered output
 *****************************************************************************/
static void DisplayVideo( vout_thread_t *p_vout, picture_t *p_pic )
{
    vout_sys_t *p_sys = p_vout->p_sys;
855
    float f_width, f_height, f_x, f_y;
856

857 858 859 860 861 862 863
    if( p_sys->p_vout->pf_lock &&
        p_sys->p_vout->pf_lock( p_sys->p_vout ) )
    {
        msg_Warn( p_vout, "could not lock OpenGL provider" );
        return;
    }

864 865
    /* glTexCoord works differently with GL_TEXTURE_2D and
       GL_TEXTURE_RECTANGLE_EXT */
866
#ifdef __APPLE__
867 868 869 870 871 872
    f_x = (float)p_vout->fmt_out.i_x_offset;
    f_y = (float)p_vout->fmt_out.i_y_offset;
    f_width = (float)p_vout->fmt_out.i_x_offset +
              (float)p_vout->fmt_out.i_visible_width;
    f_height = (float)p_vout->fmt_out.i_y_offset +
               (float)p_vout->fmt_out.i_visible_height;
873
#else
874 875 876 877 878 879
    f_x = (float)p_vout->fmt_out.i_x_offset / p_sys->i_tex_width;
    f_y = (float)p_vout->fmt_out.i_y_offset / p_sys->i_tex_height;
    f_width = ( (float)p_vout->fmt_out.i_x_offset +
                p_vout->fmt_out.i_visible_width ) / p_sys->i_tex_width;
    f_height = ( (float)p_vout->fmt_out.i_y_offset +
                 p_vout->fmt_out.i_visible_height ) / p_sys->i_tex_height;
880
#endif
881 882 883 884 885 886

    /* Why drawing here and not in Render()? Because this way, the
       OpenGL providers can call pf_display to force redraw. Currently,
       the OS X provider uses it to get a smooth window resizing */

    glClear( GL_COLOR_BUFFER_BIT );
887

888
    if( p_sys->i_effect == OPENGL_EFFECT_NONE )
889
    {
890
        glEnable( VLCGL_TARGET );
891
        glBegin( GL_POLYGON );
892 893
        glTexCoord2f( f_x, f_y ); glVertex2f( -1.0, 1.0 );
        glTexCoord2f( f_width, f_y ); glVertex2f( 1.0, 1.0 );
hartman's avatar
hartman committed
894
        glTexCoord2f( f_width, f_height ); glVertex2f( 1.0, -1.0 );
895
        glTexCoord2f( f_x, f_height ); glVertex2f( -1.0, -1.0 );
896 897 898
        glEnd();
    }
    else
899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948
#ifdef OPENGL_MORE_EFFECT
		if ((p_sys->i_effect > OPENGL_EFFECT_TRANSPARENT_CUBE) || 
			((p_sys->i_effect == OPENGL_EFFECT_NONE)))
		{
		   unsigned int i_i, i_j;
		   unsigned int i_accuracy  = config_GetInt( p_vout, "opengl-accuracy");
		   unsigned int i_n = pow(2, i_accuracy);	
		   unsigned int i_n_x = (p_vout->fmt_out.i_visible_width / (i_n * 2));
		   unsigned int i_n_y = (p_vout->fmt_out.i_visible_height / i_n);
		   double d_x, d_y;
		   int i_distortion = p_sys->i_effect;
		   float f_p = p_sys->f_radius; 
                
		   glEnable( VLCGL_TARGET );
		   glBegin(GL_QUADS);								   
		   for (i_i = 0; i_i < p_vout->fmt_out.i_visible_width; i_i += i_n_x) 
		   {
			  if ( i_i == i_n_x * i_n / 2) i_n_x += p_vout->fmt_out.i_visible_width % i_n;
			  if ((i_i == (p_vout->fmt_out.i_visible_width / i_n) * i_n / 2 + i_n_x) &&
				  (p_vout->fmt_out.i_visible_width / i_n != i_n_x))
					i_n_x -= p_vout->fmt_out.i_visible_width % i_n; 
	
			  int i_m;
			  int i_index_max = 0;
					
			  for (i_j = 0; i_j < p_vout->fmt_out.i_visible_height; i_j += i_n_y) 
			  {
				if ( i_j == i_n_y * i_n / 2) i_n_y += p_vout->fmt_out.i_visible_height % i_n;
				if ((i_j == (p_vout->fmt_out.i_visible_height / i_n) * i_n / 2 + i_n_y) &&
					(p_vout->fmt_out.i_visible_height / i_n != i_n_y))
						i_n_y -= p_vout->fmt_out.i_visible_height % i_n;

				for (i_m = i_index_max; i_m < i_index_max + 4; i_m++)
				{
					int i_k = ((i_m % 4) == 1) || ((i_m % 4) == 2);
					int i_l = ((i_m % 4) == 2) || ((i_m % 4) == 3);

					Transform(f_p, i_distortion, f_width, f_height, i_i + i_k * i_n_x, i_j + i_l * i_n_y, p_vout->fmt_out.i_visible_width, p_vout->fmt_out.i_visible_height, &d_x, &d_y);								
					glTexCoord2f(f_x + d_x, f_y + d_y);
					d_x =  - 1.0 + 2.0 * ((double)(i_k * i_n_x + i_i) / (double)p_vout->fmt_out.i_visible_width);
					d_y =    1.0 - 2.0 * (((double)i_l * i_n_y + i_j) / (double)p_vout->fmt_out.i_visible_height);
					glVertex3f((float)d_x, (float)d_y, Z_Compute(f_p, i_distortion, (float)d_x, (float)d_y));	
				}
			  }
		   } 
		   glEnd();
		}
		else
#endif
	{
zorglub's avatar
zorglub committed
949
        glRotatef( 0.5 * p_sys->f_speed , 0.3, 0.5, 0.7 );
950

951
        glEnable( VLCGL_TARGET );
952 953 954
        glBegin( GL_QUADS );

        /* Front */
955 956
        glTexCoord2f( f_x, f_y ); glVertex3f( - 1.0, 1.0, 1.0 );
        glTexCoord2f( f_x, f_height ); glVertex3f( - 1.0, - 1.0, 1.0 );
hartman's avatar
hartman committed
957
        glTexCoord2f( f_width, f_height ); glVertex3f( 1.0, - 1.0, 1.0 );
958
        glTexCoord2f( f_width, f_y ); glVertex3f( 1.0, 1.0, 1.0 );
959 960

        /* Left */
961 962
        glTexCoord2f( f_x, f_y ); glVertex3f( - 1.0, 1.0, - 1.0 );
        glTexCoord2f( f_x, f_height ); glVertex3f( - 1.0, - 1.0, - 1.0 );
hartman's avatar
hartman committed
963
        glTexCoord2f( f_width, f_height ); glVertex3f( - 1.0, - 1.0, 1.0 );
964
        glTexCoord2f( f_width, f_y ); glVertex3f( - 1.0, 1.0, 1.0 );
965 966

        /* Back */
967 968
        glTexCoord2f( f_x, f_y ); glVertex3f( 1.0, 1.0, - 1.0 );
        glTexCoord2f( f_x, f_height ); glVertex3f( 1.0, - 1.0, - 1.0 );
hartman's avatar
hartman committed
969
        glTexCoord2f( f_width, f_height ); glVertex3f( - 1.0, - 1.0, - 1.0 );
970
        glTexCoord2f( f_width, f_y ); glVertex3f( - 1.0, 1.0, - 1.0 );
971 972

        /* Right */
973 974
        glTexCoord2f( f_x, f_y ); glVertex3f( 1.0, 1.0, 1.0 );
        glTexCoord2f( f_x, f_height ); glVertex3f( 1.0, - 1.0, 1.0 );
hartman's avatar
hartman committed
975
        glTexCoord2f( f_width, f_height ); glVertex3f( 1.0, - 1.0, - 1.0 );
976
        glTexCoord2f( f_width, f_y ); glVertex3f( 1.0, 1.0, - 1.0 );
977 978

        /* Top */
979 980
        glTexCoord2f( f_x, f_y ); glVertex3f( - 1.0, 1.0, - 1.0 );
        glTexCoord2f( f_x, f_height ); glVertex3f( - 1.0, 1.0, 1.0 );
hartman's avatar
hartman committed
981
        glTexCoord2f( f_width, f_height ); glVertex3f( 1.0, 1.0, 1.0 );
982
        glTexCoord2f( f_width, f_y ); glVertex3f( 1.0, 1.0, - 1.0 );
hartman's avatar
hartman committed
983 984

        /* Bottom */
985 986
        glTexCoord2f( f_x, f_y ); glVertex3f( - 1.0, - 1.0, 1.0 );
        glTexCoord2f( f_x, f_height ); glVertex3f( - 1.0, - 1.0, - 1.0 );
hartman's avatar
hartman committed
987
        glTexCoord2f( f_width, f_height ); glVertex3f( 1.0, - 1.0, - 1.0 );
988
        glTexCoord2f( f_width, f_y ); glVertex3f( 1.0, - 1.0, 1.0 );
989 990 991
        glEnd();
    }

992 993
    glDisable( VLCGL_TARGET );

994
    p_sys->p_vout->pf_swap( p_sys->p_vout );
995 996 997 998 999

    if( p_sys->p_vout->pf_unlock )
    {
        p_sys->p_vout->pf_unlock( p_sys->p_vout );
    }
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
}

int GetAlignedSize( int i_size )
{
    /* Return the nearest power of 2 */
    int i_result = 1;
    while( i_result < i_size )
    {
        i_result *= 2;
    }
    return i_result;
}
1012 1013 1014 1015 1016 1017 1018 1019

/*****************************************************************************
 * Control: control facility for the vout
 *****************************************************************************/
static int Control( vout_thread_t *p_vout, int i_query, va_list args )
{
    vout_sys_t *p_sys = p_vout->p_sys;

1020 1021 1022
    switch( i_query )
    {
    case VOUT_SNAPSHOT:
1023
        return vout_vaControlDefault( p_vout, i_query, args );
1024 1025 1026 1027 1028 1029 1030

    default:
        if( p_sys->p_vout->pf_control )
            return p_sys->p_vout->pf_control( p_sys->p_vout, i_query, args );
        else
            return vout_vaControlDefault( p_vout, i_query, args );
    }
1031
}
1032

Eric Petit's avatar
Eric Petit committed
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
static int InitTextures( vout_thread_t *p_vout )
{
    vout_sys_t *p_sys = p_vout->p_sys;
    int i_index;

    glDeleteTextures( 2, p_sys->p_textures );
    glGenTextures( 2, p_sys->p_textures );

    for( i_index = 0; i_index < 2; i_index++ )
    {
        glBindTexture( VLCGL_TARGET, p_sys->p_textures[i_index] );
1044

Eric Petit's avatar
Eric Petit committed
1045 1046
        /* Set the texture parameters */
        glTexParameterf( VLCGL_TARGET, GL_TEXTURE_PRIORITY, 1.0 );
1047

1048 1049
        glTexParameteri( VLCGL_TARGET, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
        glTexParameteri( VLCGL_TARGET, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
1050

1051 1052 1053
        glTexParameteri( VLCGL_TARGET, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
        glTexParameteri( VLCGL_TARGET, GL_TEXTURE_MIN_FILTER, GL_LINEAR );

Eric Petit's avatar
Eric Petit committed
1054 1055
        glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

1056
#ifdef __APPLE__
Eric Petit's avatar
Eric Petit committed
1057 1058 1059 1060
        /* Tell the driver not to make a copy of the texture but to use
           our buffer */
        glEnable( GL_UNPACK_CLIENT_STORAGE_APPLE );
        glPixelStorei( GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE );
1061

Eric Petit's avatar
Eric Petit committed
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081