1 /*****************************************************************************
2 * opengl.c: OpenGL and OpenGL ES output common code
3 *****************************************************************************
4 * Copyright (C) 2004-2011 VLC authors and VideoLAN
5 * Copyright (C) 2009, 2011 Laurent Aimar
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 * Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_picture_pool.h>
33 #include <vlc_subpicture.h>
34 #include <vlc_opengl.h>
37 // Define USE_OPENGL_ES to the GL ES Version you want to select
40 # define PFNGLGENPROGRAMSARBPROC typeof(glGenProgramsARB)*
41 # define PFNGLBINDPROGRAMARBPROC typeof(glBindProgramARB)*
42 # define PFNGLPROGRAMSTRINGARBPROC typeof(glProgramStringARB)*
43 # define PFNGLDELETEPROGRAMSARBPROC typeof(glDeleteProgramsARB)*
44 # define PFNGLPROGRAMLOCALPARAMETER4FVARBPROC typeof(glProgramLocalParameter4fvARB)*
45 # define PFNGLACTIVETEXTUREARBPROC typeof(glActiveTextureARB)*
46 # define PFNGLMULTITEXCOORD2FARBPROC typeof(glMultiTexCoord2fARB)*
50 #ifndef GL_UNSIGNED_SHORT_5_6_5
51 # define GL_UNSIGNED_SHORT_5_6_5 0x8363
53 #ifndef GL_CLAMP_TO_EDGE
54 # define GL_CLAMP_TO_EDGE 0x812F
58 # define VLCGL_TEXTURE_COUNT 1
59 # define VLCGL_PICTURE_MAX 1
61 # define VLCGL_TEXTURE_COUNT 1
62 # define VLCGL_PICTURE_MAX 128
65 static const vlc_fourcc_t gl_subpicture_chromas[] = {
85 struct vout_display_opengl_t {
89 const vlc_chroma_description_t *chroma;
96 int tex_width[PICTURE_PLANE_MAX];
97 int tex_height[PICTURE_PLANE_MAX];
99 GLuint texture[VLCGL_TEXTURE_COUNT][PICTURE_PLANE_MAX];
105 picture_pool_t *pool;
109 GLfloat local_value[16][4];
111 /* fragment_program */
112 PFNGLGENPROGRAMSARBPROC GenProgramsARB;
113 PFNGLBINDPROGRAMARBPROC BindProgramARB;
114 PFNGLPROGRAMSTRINGARBPROC ProgramStringARB;
115 PFNGLDELETEPROGRAMSARBPROC DeleteProgramsARB;
116 PFNGLPROGRAMLOCALPARAMETER4FVARBPROC ProgramLocalParameter4fvARB;
119 bool use_multitexture;
120 PFNGLACTIVETEXTUREARBPROC ActiveTextureARB;
121 PFNGLMULTITEXCOORD2FARBPROC MultiTexCoord2fARB;
124 static inline int GetAlignedSize(unsigned size)
126 /* Return the smallest larger or equal power of 2 */
127 unsigned align = 1 << (8 * sizeof (unsigned) - clz(size));
128 return ((align >> 1) == size) ? size : align;
131 static bool IsLuminance16Supported(int target)
135 glGenTextures(1, &texture);
136 glBindTexture(target, texture);
137 glTexImage2D(target, 0, GL_LUMINANCE16,
138 64, 64, 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, NULL);
140 glGetTexLevelParameteriv(target, 0, GL_TEXTURE_LUMINANCE_SIZE, &size);
142 glDeleteTextures(1, &texture);
147 vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
148 const vlc_fourcc_t **subpicture_chromas,
151 vout_display_opengl_t *vgl = calloc(1, sizeof(*vgl));
156 if (vlc_gl_Lock(vgl->gl)) {
161 const char *extensions = (const char *)glGetString(GL_EXTENSIONS);
163 /* Load extensions */
164 bool supports_fp = false;
165 if (HasExtension(extensions, "GL_ARB_fragment_program")) {
166 #if !defined(MACOS_OPENGL)
167 vgl->GenProgramsARB = (PFNGLGENPROGRAMSARBPROC)vlc_gl_GetProcAddress(vgl->gl, "glGenProgramsARB");
168 vgl->BindProgramARB = (PFNGLBINDPROGRAMARBPROC)vlc_gl_GetProcAddress(vgl->gl, "glBindProgramARB");
169 vgl->ProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)vlc_gl_GetProcAddress(vgl->gl, "glProgramStringARB");
170 vgl->DeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)vlc_gl_GetProcAddress(vgl->gl, "glDeleteProgramsARB");
171 vgl->ProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)vlc_gl_GetProcAddress(vgl->gl, "glProgramLocalParameter4fvARB");
173 vgl->GenProgramsARB = glGenProgramsARB;
174 vgl->BindProgramARB = glBindProgramARB;
175 vgl->ProgramStringARB = glProgramStringARB;
176 vgl->DeleteProgramsARB = glDeleteProgramsARB;
177 vgl->ProgramLocalParameter4fvARB = glProgramLocalParameter4fvARB;
179 supports_fp = vgl->GenProgramsARB &&
180 vgl->BindProgramARB &&
181 vgl->ProgramStringARB &&
182 vgl->DeleteProgramsARB &&
183 vgl->ProgramLocalParameter4fvARB;
186 bool supports_multitexture = false;
187 GLint max_texture_units = 0;
188 if (HasExtension(extensions, "GL_ARB_multitexture")) {
189 #if !defined(MACOS_OPENGL)
190 vgl->ActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)vlc_gl_GetProcAddress(vgl->gl, "glActiveTextureARB");
191 vgl->MultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)vlc_gl_GetProcAddress(vgl->gl, "glMultiTexCoord2fARB");
193 vgl->ActiveTextureARB = glActiveTextureARB;
194 vgl->MultiTexCoord2fARB = glMultiTexCoord2fARB;
196 supports_multitexture = vgl->ActiveTextureARB &&
197 vgl->MultiTexCoord2fARB;
198 if (supports_multitexture)
199 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &max_texture_units);
202 /* Initialize with default chroma */
205 vgl->fmt.i_chroma = VLC_CODEC_RGB16;
206 # if defined(WORDS_BIGENDIAN)
207 vgl->fmt.i_rmask = 0x001f;
208 vgl->fmt.i_gmask = 0x07e0;
209 vgl->fmt.i_bmask = 0xf800;
211 vgl->fmt.i_rmask = 0xf800;
212 vgl->fmt.i_gmask = 0x07e0;
213 vgl->fmt.i_bmask = 0x001f;
215 vgl->tex_target = GL_TEXTURE_2D;
216 vgl->tex_format = GL_RGB;
217 vgl->tex_internal = GL_RGB;
218 vgl->tex_type = GL_UNSIGNED_SHORT_5_6_5;
220 vgl->fmt.i_chroma = VLC_CODEC_RGB32;
221 # if defined(WORDS_BIGENDIAN)
222 vgl->fmt.i_rmask = 0xff000000;
223 vgl->fmt.i_gmask = 0x00ff0000;
224 vgl->fmt.i_bmask = 0x0000ff00;
226 vgl->fmt.i_rmask = 0x000000ff;
227 vgl->fmt.i_gmask = 0x0000ff00;
228 vgl->fmt.i_bmask = 0x00ff0000;
230 vgl->tex_target = GL_TEXTURE_2D;
231 vgl->tex_format = GL_RGBA;
232 vgl->tex_internal = GL_RGBA;
233 vgl->tex_type = GL_UNSIGNED_BYTE;
235 /* Use YUV if possible and needed */
236 bool need_fs_yuv = false;
237 float yuv_range_correction = 1.0;
238 if (supports_fp && supports_multitexture && max_texture_units >= 3 &&
239 vlc_fourcc_IsYUV(fmt->i_chroma) && !vlc_fourcc_IsYUV(vgl->fmt.i_chroma)) {
240 const vlc_fourcc_t *list = vlc_fourcc_GetYUVFallback(fmt->i_chroma);
242 const vlc_chroma_description_t *dsc = vlc_fourcc_GetChromaDescription(*list);
243 if (dsc && dsc->plane_count == 3 && dsc->pixel_size == 1) {
246 vgl->fmt.i_chroma = *list;
247 vgl->tex_format = GL_LUMINANCE;
248 vgl->tex_internal = GL_LUMINANCE;
249 vgl->tex_type = GL_UNSIGNED_BYTE;
250 yuv_range_correction = 1.0;
252 } else if (dsc && dsc->plane_count == 3 && dsc->pixel_size == 2 &&
253 IsLuminance16Supported(vgl->tex_target)) {
256 vgl->fmt.i_chroma = *list;
257 vgl->tex_format = GL_LUMINANCE;
258 vgl->tex_internal = GL_LUMINANCE16;
259 vgl->tex_type = GL_UNSIGNED_SHORT;
260 yuv_range_correction = (float)((1 << 16) - 1) / ((1 << dsc->pixel_bits) - 1);
267 vgl->chroma = vlc_fourcc_GetChromaDescription(vgl->fmt.i_chroma);
268 vgl->use_multitexture = vgl->chroma->plane_count > 1;
270 bool supports_npot = false;
271 #if USE_OPENGL_ES == 2
272 supports_npot = true;
274 supports_npot |= HasExtension(extensions, "GL_APPLE_texture_2D_limited_npot") ||
275 HasExtension(extensions, "GL_ARB_texture_non_power_of_two");
279 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
280 int w = vgl->fmt.i_width * vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den;
281 int h = vgl->fmt.i_height * vgl->chroma->p[j].h.num / vgl->chroma->p[j].h.den;
283 vgl->tex_width[j] = w;
284 vgl->tex_height[j] = h;
287 /* A texture must have a size aligned on a power of 2 */
288 vgl->tex_width[j] = GetAlignedSize(w);
289 vgl->tex_height[j] = GetAlignedSize(h);
293 /* Build fragment program if needed */
295 vgl->local_count = 0;
300 /* [R/G/B][Y U V O] from TV range to full range
301 * XXX we could also do hue/brightness/constrast/gamma
302 * by simply changing the coefficients
304 const float matrix_bt601_tv2full[3][4] = {
305 { 1.1640, 0.0000, 1.4030, -0.7773 },
306 { 1.1640, -0.3440, -0.7140, 0.4580 },
307 { 1.1640, 1.7730, 0.0000, -0.9630 },
309 const float matrix_bt709_tv2full[3][4] = {
310 { 1.1640, 0.0000, 1.5701, -0.8612 },
311 { 1.1640, -0.1870, -0.4664, 0.2549 },
312 { 1.1640, 1.8556, 0.0000, -1.0045 },
314 const float (*matrix)[4] = fmt->i_height > 576 ? matrix_bt709_tv2full
315 : matrix_bt601_tv2full;
317 /* Basic linear YUV -> RGB conversion using bilinear interpolation */
318 const char *template_yuv =
320 "OPTION ARB_precision_hint_fastest;"
323 "TEX src.x, fragment.texcoord[0], texture[0], 2D;"
324 "TEX src.%c, fragment.texcoord[1], texture[1], 2D;"
325 "TEX src.%c, fragment.texcoord[2], texture[2], 2D;"
327 "PARAM coefficient[4] = { program.local[0..3] };"
330 "MAD tmp.rgb, src.xxxx, coefficient[0], coefficient[3];"
331 "MAD tmp.rgb, src.yyyy, coefficient[1], tmp;"
332 "MAD result.color.rgb, src.zzzz, coefficient[2], tmp;"
334 bool swap_uv = vgl->fmt.i_chroma == VLC_CODEC_YV12 ||
335 vgl->fmt.i_chroma == VLC_CODEC_YV9;
336 if (asprintf(&code, template_yuv,
338 swap_uv ? 'y' : 'z') < 0)
341 for (int i = 0; i < 4; i++) {
342 float correction = i < 3 ? yuv_range_correction : 1.0;
343 for (int j = 0; j < 4; j++) {
344 vgl->local_value[vgl->local_count + i][j] = j < 3 ? correction * matrix[j][i] : 0.0;
347 vgl->local_count += 4;
350 // Here you have shaders
351 vgl->GenProgramsARB(1, &vgl->program);
352 vgl->BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, vgl->program);
353 vgl->ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
354 GL_PROGRAM_FORMAT_ASCII_ARB,
355 strlen(code), (const GLbyte*)code);
356 if (glGetError() == GL_INVALID_OPERATION) {
357 /* FIXME if the program was needed for YUV, the video will be broken */
360 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &position);
362 const char *msg = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);
363 fprintf(stderr, "GL_INVALID_OPERATION: error at %d: %s\n", position, msg);
365 vgl->DeleteProgramsARB(1, &vgl->program);
374 glDisable(GL_DEPTH_TEST);
375 glDepthMask(GL_FALSE);
376 glDisable(GL_CULL_FACE);
377 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
378 glClear(GL_COLOR_BUFFER_BIT);
380 vlc_gl_Unlock(vgl->gl);
383 for (int i = 0; i < VLCGL_TEXTURE_COUNT; i++) {
384 for (int j = 0; j < PICTURE_PLANE_MAX; j++)
385 vgl->texture[i][j] = 0;
387 vgl->region_count = 0;
392 if (subpicture_chromas) {
393 *subpicture_chromas = NULL;
396 *subpicture_chromas = gl_subpicture_chromas;
402 void vout_display_opengl_Delete(vout_display_opengl_t *vgl)
405 if (!vlc_gl_Lock(vgl->gl)) {
409 for (int i = 0; i < VLCGL_TEXTURE_COUNT; i++)
410 glDeleteTextures(vgl->chroma->plane_count, vgl->texture[i]);
411 for (int i = 0; i < vgl->region_count; i++) {
412 if (vgl->region[i].texture)
413 glDeleteTextures(1, &vgl->region[i].texture);
418 vgl->DeleteProgramsARB(1, &vgl->program);
420 vlc_gl_Unlock(vgl->gl);
423 picture_pool_Delete(vgl->pool);
427 picture_pool_t *vout_display_opengl_GetPool(vout_display_opengl_t *vgl, unsigned requested_count)
432 /* Allocate our pictures */
433 picture_t *picture[VLCGL_PICTURE_MAX] = {NULL, };
436 for (count = 0; count < __MIN(VLCGL_PICTURE_MAX, requested_count); count++) {
437 picture[count] = picture_NewFromFormat(&vgl->fmt);
444 /* Wrap the pictures into a pool */
445 picture_pool_configuration_t cfg;
446 memset(&cfg, 0, sizeof(cfg));
447 cfg.picture_count = count;
448 cfg.picture = picture;
449 vgl->pool = picture_pool_NewExtended(&cfg);
453 /* Allocates our textures */
454 if (vlc_gl_Lock(vgl->gl))
457 for (int i = 0; i < VLCGL_TEXTURE_COUNT; i++) {
458 glGenTextures(vgl->chroma->plane_count, vgl->texture[i]);
459 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
460 if (vgl->use_multitexture)
461 vgl->ActiveTextureARB(GL_TEXTURE0_ARB + j);
462 glBindTexture(vgl->tex_target, vgl->texture[i][j]);
465 /* Set the texture parameters */
466 glTexParameterf(vgl->tex_target, GL_TEXTURE_PRIORITY, 1.0);
467 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
470 glTexParameteri(vgl->tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
471 glTexParameteri(vgl->tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
472 glTexParameteri(vgl->tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
473 glTexParameteri(vgl->tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
475 /* Call glTexImage2D only once, and use glTexSubImage2D later */
476 glTexImage2D(vgl->tex_target, 0,
477 vgl->tex_internal, vgl->tex_width[j], vgl->tex_height[j],
478 0, vgl->tex_format, vgl->tex_type, NULL);
482 vlc_gl_Unlock(vgl->gl);
487 for (unsigned i = 0; i < count; i++)
488 picture_Delete(picture[i]);
492 int vout_display_opengl_Prepare(vout_display_opengl_t *vgl,
493 picture_t *picture, subpicture_t *subpicture)
495 /* On Win32/GLX, we do this the usual way:
496 + Fill the buffer with new content,
497 + Reload the texture,
500 On OS X with VRAM or AGP texturing, the order has to be:
501 + Reload the texture,
502 + Fill the buffer with new content,
505 (Thanks to gcc from the Arstechnica forums for the tip)
507 Therefore on OSX, we have to use two buffers and textures and use a
508 lock(/unlock) managed picture pool.
511 if (vlc_gl_Lock(vgl->gl))
514 /* Update the texture */
515 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
516 const int plane = vgl->fmt.i_chroma == VLC_CODEC_YV12 && j > 0 ? (3 - j) : j;
517 if (vgl->use_multitexture)
518 vgl->ActiveTextureARB(GL_TEXTURE0_ARB + j);
519 glBindTexture(vgl->tex_target, vgl->texture[0][j]);
520 glPixelStorei(GL_UNPACK_ROW_LENGTH, picture->p[plane].i_pitch / picture->p[plane].i_pixel_pitch);
521 glTexSubImage2D(vgl->tex_target, 0,
523 vgl->fmt.i_width * vgl->chroma->p[plane].w.num / vgl->chroma->p[plane].w.den,
524 vgl->fmt.i_height * vgl->chroma->p[plane].h.num / vgl->chroma->p[plane].h.den,
525 vgl->tex_format, vgl->tex_type, picture->p[plane].p_pixels);
528 int last_count = vgl->region_count;
529 gl_region_t *last = vgl->region;
531 vgl->region_count = 0;
537 for (subpicture_region_t *r = subpicture->p_region; r; r = r->p_next)
540 vgl->region_count = count;
541 vgl->region = calloc(count, sizeof(*vgl->region));
543 if (vgl->use_multitexture)
544 vgl->ActiveTextureARB(GL_TEXTURE0_ARB + 0);
546 for (subpicture_region_t *r = subpicture->p_region; r; r = r->p_next, i++) {
547 gl_region_t *glr = &vgl->region[i];
549 glr->format = GL_RGBA;
550 glr->type = GL_UNSIGNED_BYTE;
551 glr->width = r->fmt.i_visible_width;
552 glr->height = r->fmt.i_visible_height;
553 glr->alpha = (float)subpicture->i_alpha * r->i_alpha / 255 / 255;
554 glr->left = 2.0 * (r->i_x ) / subpicture->i_original_picture_width - 1.0;
555 glr->top = -2.0 * (r->i_y ) / subpicture->i_original_picture_height + 1.0;
556 glr->right = 2.0 * (r->i_x + r->fmt.i_visible_width ) / subpicture->i_original_picture_width - 1.0;
557 glr->bottom = -2.0 * (r->i_y + r->fmt.i_visible_height) / subpicture->i_original_picture_height + 1.0;
560 for (int j = 0; j < last_count; j++) {
561 if (last[j].texture &&
562 last[j].width == glr->width &&
563 last[j].height == glr->height &&
564 last[j].format == glr->format &&
565 last[j].type == glr->type) {
566 glr->texture = last[j].texture;
567 memset(&last[j], 0, sizeof(last[j]));
573 glBindTexture(GL_TEXTURE_2D, glr->texture);
574 /* TODO set GL_UNPACK_ALIGNMENT */
575 glPixelStorei(GL_UNPACK_ROW_LENGTH, r->p_picture->p->i_pitch / r->p_picture->p->i_pixel_pitch);
576 glTexSubImage2D(GL_TEXTURE_2D, 0,
577 0, 0, glr->width, glr->height,
578 glr->format, glr->type, r->p_picture->p->p_pixels);
580 glGenTextures(1, &glr->texture);
581 glBindTexture(GL_TEXTURE_2D, glr->texture);
582 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 1.0);
583 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
584 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
585 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
586 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
587 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
588 /* TODO set GL_UNPACK_ALIGNMENT */
589 glPixelStorei(GL_UNPACK_ROW_LENGTH, r->p_picture->p->i_pitch / r->p_picture->p->i_pixel_pitch);
590 glTexImage2D(GL_TEXTURE_2D, 0, glr->format,
591 glr->width, glr->height, 0, glr->format, glr->type,
592 r->p_picture->p->p_pixels);
596 for (int i = 0; i < last_count; i++) {
598 glDeleteTextures(1, &last[i].texture);
602 vlc_gl_Unlock(vgl->gl);
603 VLC_UNUSED(subpicture);
607 int vout_display_opengl_Display(vout_display_opengl_t *vgl,
608 const video_format_t *source)
610 if (vlc_gl_Lock(vgl->gl))
613 /* glTexCoord works differently with GL_TEXTURE_2D and
614 GL_TEXTURE_RECTANGLE_EXT */
615 float left[PICTURE_PLANE_MAX];
616 float top[PICTURE_PLANE_MAX];
617 float right[PICTURE_PLANE_MAX];
618 float bottom[PICTURE_PLANE_MAX];
619 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
620 float scale_w, scale_h;
621 if (vgl->tex_target == GL_TEXTURE_2D) {
622 scale_w = (float)vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den / vgl->tex_width[j];
623 scale_h = (float)vgl->chroma->p[j].h.num / vgl->chroma->p[j].h.den / vgl->tex_height[j];
629 left[j] = (source->i_x_offset + 0 ) * scale_w;
630 top[j] = (source->i_y_offset + 0 ) * scale_h;
631 right[j] = (source->i_x_offset + source->i_visible_width ) * scale_w;
632 bottom[j] = (source->i_y_offset + source->i_visible_height) * scale_h;
636 /* Why drawing here and not in Render()? Because this way, the
637 OpenGL providers can call vout_display_opengl_Display to force redraw.i
638 Currently, the OS X provider uses it to get a smooth window resizing */
640 glClear(GL_COLOR_BUFFER_BIT);
643 glEnable(GL_FRAGMENT_PROGRAM_ARB);
644 for (int i = 0; i < vgl->local_count; i++)
645 vgl->ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, vgl->local_value[i]);
647 glEnable(vgl->tex_target);
651 static const GLfloat vertexCoord[] = {
658 const GLfloat textureCoord[8] = {
665 glEnableClientState(GL_VERTEX_ARRAY);
666 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
667 glVertexPointer(2, GL_FLOAT, 0, vertexCoord);
668 glTexCoordPointer(2, GL_FLOAT, 0, textureCoord);
670 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
672 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
673 if (vgl->use_multitexture)
674 vgl->ActiveTextureARB(GL_TEXTURE0_ARB + j);
675 glBindTexture(vgl->tex_target, vgl->texture[0][j]);
679 glTexCoord2f(left[0], top[0]);
680 for (unsigned j = 1; j < vgl->chroma->plane_count; j++)
681 vgl->MultiTexCoord2fARB(GL_TEXTURE0_ARB + j, left[j], top[j]);
682 glVertex2f(-1.0, 1.0);
684 glTexCoord2f(right[0], top[0]);
685 for (unsigned j = 1; j < vgl->chroma->plane_count; j++)
686 vgl->MultiTexCoord2fARB(GL_TEXTURE0_ARB + j, right[j], top[j]);
687 glVertex2f( 1.0, 1.0);
689 glTexCoord2f(right[0], bottom[0]);
690 for (unsigned j = 1; j < vgl->chroma->plane_count; j++)
691 vgl->MultiTexCoord2fARB(GL_TEXTURE0_ARB + j, right[j], bottom[j]);
692 glVertex2f( 1.0, -1.0);
694 glTexCoord2f(left[0], bottom[0]);
695 for (unsigned j = 1; j < vgl->chroma->plane_count; j++)
696 vgl->MultiTexCoord2fARB(GL_TEXTURE0_ARB + j, left[j], bottom[j]);
697 glVertex2f(-1.0, -1.0);
703 glDisable(GL_FRAGMENT_PROGRAM_ARB);
705 glDisable(vgl->tex_target);
708 if (vgl->use_multitexture)
709 vgl->ActiveTextureARB(GL_TEXTURE0_ARB + 0);
710 glEnable(GL_TEXTURE_2D);
712 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
713 for (int i = 0; i < vgl->region_count; i++) {
714 gl_region_t *glr = &vgl->region[i];
716 glBindTexture(GL_TEXTURE_2D, glr->texture);
720 glColor4f(1.0, 1.0, 1.0, glr->alpha);
722 glTexCoord2f(0.0, 0.0);
723 glVertex2f(glr->left, glr->top);
725 glTexCoord2f(1.0, 0.0);
726 glVertex2f(glr->right, glr->top);
728 glTexCoord2f(1.0, 1.0);
729 glVertex2f(glr->right, glr->bottom);
731 glTexCoord2f(0.0, 1.0);
732 glVertex2f(glr->left, glr->bottom);
737 glDisable(GL_TEXTURE_2D);
740 vlc_gl_Swap(vgl->gl);
742 vlc_gl_Unlock(vgl->gl);