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 PFNGLACTIVETEXTUREPROC typeof(glActiveTexture)*
46 # define PFNGLCLIENTACTIVETEXTUREPROC typeof(glClientActiveTexture)*
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 PFNGLACTIVETEXTUREPROC ActiveTexture;
121 PFNGLCLIENTACTIVETEXTUREPROC ClientActiveTexture;
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)
133 #if defined(MACOS_OPENGL)
134 /* OpenGL 1.x on OS X does _not_ support 16bit shaders, but pretends to.
135 * That's why we enforce return false here, even though the actual code below
137 * This fixes playback of 10bit content on the Intel GMA 950 chipset, which is
138 * the only "GPU" supported by 10.6 and 10.7 with just an OpenGL 1.4 driver.
140 * Presumely, this also improves playback on the GMA 3100, GeForce FX 5200,
141 * GeForce4 Ti, GeForce3, GeForce2 MX/4 MX and the Radeon 8500 when
142 * running OS X 10.5. */
143 const GLubyte * p_glversion;
145 p_glversion = glGetString (GL_VERSION);
146 sscanf((char *)p_glversion, "%f", &f_glversion);
153 glGenTextures(1, &texture);
154 glBindTexture(target, texture);
155 glTexImage2D(target, 0, GL_LUMINANCE16,
156 64, 64, 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, NULL);
158 glGetTexLevelParameteriv(target, 0, GL_TEXTURE_LUMINANCE_SIZE, &size);
160 glDeleteTextures(1, &texture);
165 vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
166 const vlc_fourcc_t **subpicture_chromas,
169 vout_display_opengl_t *vgl = calloc(1, sizeof(*vgl));
174 if (vlc_gl_Lock(vgl->gl)) {
179 const char *extensions = (const char *)glGetString(GL_EXTENSIONS);
181 /* Load extensions */
182 bool supports_fp = false;
183 if (HasExtension(extensions, "GL_ARB_fragment_program")) {
184 #if !defined(MACOS_OPENGL)
185 vgl->GenProgramsARB = (PFNGLGENPROGRAMSARBPROC)vlc_gl_GetProcAddress(vgl->gl, "glGenProgramsARB");
186 vgl->BindProgramARB = (PFNGLBINDPROGRAMARBPROC)vlc_gl_GetProcAddress(vgl->gl, "glBindProgramARB");
187 vgl->ProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)vlc_gl_GetProcAddress(vgl->gl, "glProgramStringARB");
188 vgl->DeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)vlc_gl_GetProcAddress(vgl->gl, "glDeleteProgramsARB");
189 vgl->ProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)vlc_gl_GetProcAddress(vgl->gl, "glProgramLocalParameter4fvARB");
191 vgl->GenProgramsARB = glGenProgramsARB;
192 vgl->BindProgramARB = glBindProgramARB;
193 vgl->ProgramStringARB = glProgramStringARB;
194 vgl->DeleteProgramsARB = glDeleteProgramsARB;
195 vgl->ProgramLocalParameter4fvARB = glProgramLocalParameter4fvARB;
197 supports_fp = vgl->GenProgramsARB &&
198 vgl->BindProgramARB &&
199 vgl->ProgramStringARB &&
200 vgl->DeleteProgramsARB &&
201 vgl->ProgramLocalParameter4fvARB;
204 bool supports_multitexture = false;
205 GLint max_texture_units = 0;
206 if (HasExtension(extensions, "GL_ARB_multitexture")) {
207 #if !defined(MACOS_OPENGL)
208 vgl->ActiveTexture = (PFNGLACTIVETEXTUREPROC)vlc_gl_GetProcAddress(vgl->gl, "glActiveTexture");
209 vgl->ClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)vlc_gl_GetProcAddress(vgl->gl, "glClientActiveTexture");
211 vgl->ActiveTexture = glActiveTexture;
212 vgl->ClientActiveTexture = glClientActiveTexture;
214 supports_multitexture = vgl->ActiveTexture &&
215 vgl->ClientActiveTexture;
216 if (supports_multitexture)
217 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &max_texture_units);
220 /* Initialize with default chroma */
223 vgl->fmt.i_chroma = VLC_CODEC_RGB16;
224 # if defined(WORDS_BIGENDIAN)
225 vgl->fmt.i_rmask = 0x001f;
226 vgl->fmt.i_gmask = 0x07e0;
227 vgl->fmt.i_bmask = 0xf800;
229 vgl->fmt.i_rmask = 0xf800;
230 vgl->fmt.i_gmask = 0x07e0;
231 vgl->fmt.i_bmask = 0x001f;
233 vgl->tex_target = GL_TEXTURE_2D;
234 vgl->tex_format = GL_RGB;
235 vgl->tex_internal = GL_RGB;
236 vgl->tex_type = GL_UNSIGNED_SHORT_5_6_5;
238 vgl->fmt.i_chroma = VLC_CODEC_RGB32;
239 # if defined(WORDS_BIGENDIAN)
240 vgl->fmt.i_rmask = 0xff000000;
241 vgl->fmt.i_gmask = 0x00ff0000;
242 vgl->fmt.i_bmask = 0x0000ff00;
244 vgl->fmt.i_rmask = 0x000000ff;
245 vgl->fmt.i_gmask = 0x0000ff00;
246 vgl->fmt.i_bmask = 0x00ff0000;
248 vgl->tex_target = GL_TEXTURE_2D;
249 vgl->tex_format = GL_RGBA;
250 vgl->tex_internal = GL_RGBA;
251 vgl->tex_type = GL_UNSIGNED_BYTE;
253 /* Use YUV if possible and needed */
254 bool need_fs_yuv = false;
255 float yuv_range_correction = 1.0;
256 if (supports_fp && supports_multitexture && max_texture_units >= 3 &&
257 vlc_fourcc_IsYUV(fmt->i_chroma) && !vlc_fourcc_IsYUV(vgl->fmt.i_chroma)) {
258 const vlc_fourcc_t *list = vlc_fourcc_GetYUVFallback(fmt->i_chroma);
260 const vlc_chroma_description_t *dsc = vlc_fourcc_GetChromaDescription(*list);
261 if (dsc && dsc->plane_count == 3 && dsc->pixel_size == 1) {
264 vgl->fmt.i_chroma = *list;
265 vgl->tex_format = GL_LUMINANCE;
266 vgl->tex_internal = GL_LUMINANCE;
267 vgl->tex_type = GL_UNSIGNED_BYTE;
268 yuv_range_correction = 1.0;
270 } else if (dsc && dsc->plane_count == 3 && dsc->pixel_size == 2 &&
271 IsLuminance16Supported(vgl->tex_target)) {
274 vgl->fmt.i_chroma = *list;
275 vgl->tex_format = GL_LUMINANCE;
276 vgl->tex_internal = GL_LUMINANCE16;
277 vgl->tex_type = GL_UNSIGNED_SHORT;
278 yuv_range_correction = (float)((1 << 16) - 1) / ((1 << dsc->pixel_bits) - 1);
284 #if (defined (__ppc__) || defined (__ppc64__) || defined (__powerpc__)) && defined (__APPLE__)
285 /* This is a work-around for dated PowerPC-based Macs, which run OpenGL 1.3 only and don't
286 * support the GL_ARB_fragment_program extension.
287 * Affected devices are all Macs built between 2002 and 2005 with an ATI Radeon 7500,
288 * an ATI Radeon 9200 or a NVIDIA GeForceFX 5200 Ultra. */
291 vgl->tex_format = GL_YCBCR_422_APPLE;
292 vgl->tex_type = GL_UNSIGNED_SHORT_8_8_APPLE;
293 vgl->fmt.i_chroma = VLC_CODEC_YUYV;
297 vgl->chroma = vlc_fourcc_GetChromaDescription(vgl->fmt.i_chroma);
298 vgl->use_multitexture = vgl->chroma->plane_count > 1;
300 bool supports_npot = false;
301 #if USE_OPENGL_ES == 2
302 supports_npot = true;
304 supports_npot |= HasExtension(extensions, "GL_APPLE_texture_2D_limited_npot") ||
305 HasExtension(extensions, "GL_ARB_texture_non_power_of_two");
309 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
310 int w = vgl->fmt.i_width * vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den;
311 int h = vgl->fmt.i_height * vgl->chroma->p[j].h.num / vgl->chroma->p[j].h.den;
313 vgl->tex_width[j] = w;
314 vgl->tex_height[j] = h;
317 /* A texture must have a size aligned on a power of 2 */
318 vgl->tex_width[j] = GetAlignedSize(w);
319 vgl->tex_height[j] = GetAlignedSize(h);
323 /* Build fragment program if needed */
325 vgl->local_count = 0;
330 /* [R/G/B][Y U V O] from TV range to full range
331 * XXX we could also do hue/brightness/constrast/gamma
332 * by simply changing the coefficients
334 const float matrix_bt601_tv2full[3][4] = {
335 { 1.164383561643836, 0.0000, 1.596026785714286, -0.874202217873451 },
336 { 1.164383561643836, -0.391762290094914, -0.812967647237771, 0.531667823499146 },
337 { 1.164383561643836, 2.017232142857142, 0.0000, -1.085630789302022 },
339 const float matrix_bt709_tv2full[3][4] = {
340 { 1.164383561643836, 0.0000, 1.792741071428571, -0.972945075016308 },
341 { 1.164383561643836, -0.21324861427373, -0.532909328559444, 0.301482665475862 },
342 { 1.164383561643836, 2.112401785714286, 0.0000, -1.133402217873451 },
344 const float (*matrix)[4] = fmt->i_height > 576 ? matrix_bt709_tv2full
345 : matrix_bt601_tv2full;
347 /* Basic linear YUV -> RGB conversion using bilinear interpolation */
348 const char *template_yuv =
350 "OPTION ARB_precision_hint_fastest;"
353 "TEX src.x, fragment.texcoord[0], texture[0], 2D;"
354 "TEX src.%c, fragment.texcoord[1], texture[1], 2D;"
355 "TEX src.%c, fragment.texcoord[2], texture[2], 2D;"
357 "PARAM coefficient[4] = { program.local[0..3] };"
360 "MAD tmp.rgb, src.xxxx, coefficient[0], coefficient[3];"
361 "MAD tmp.rgb, src.yyyy, coefficient[1], tmp;"
362 "MAD result.color.rgb, src.zzzz, coefficient[2], tmp;"
364 bool swap_uv = vgl->fmt.i_chroma == VLC_CODEC_YV12 ||
365 vgl->fmt.i_chroma == VLC_CODEC_YV9;
366 if (asprintf(&code, template_yuv,
368 swap_uv ? 'y' : 'z') < 0)
371 for (int i = 0; i < 4; i++) {
372 float correction = i < 3 ? yuv_range_correction : 1.0;
373 for (int j = 0; j < 4; j++) {
374 vgl->local_value[vgl->local_count + i][j] = j < 3 ? correction * matrix[j][i] : 0.0;
377 vgl->local_count += 4;
380 // Here you have shaders
381 vgl->GenProgramsARB(1, &vgl->program);
382 vgl->BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, vgl->program);
383 vgl->ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
384 GL_PROGRAM_FORMAT_ASCII_ARB,
385 strlen(code), (const GLbyte*)code);
386 if (glGetError() == GL_INVALID_OPERATION) {
387 /* FIXME if the program was needed for YUV, the video will be broken */
390 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &position);
392 const char *msg = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);
393 fprintf(stderr, "GL_INVALID_OPERATION: error at %d: %s\n", position, msg);
395 vgl->DeleteProgramsARB(1, &vgl->program);
404 glDisable(GL_DEPTH_TEST);
405 glDepthMask(GL_FALSE);
406 glDisable(GL_CULL_FACE);
407 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
408 glClear(GL_COLOR_BUFFER_BIT);
410 vlc_gl_Unlock(vgl->gl);
413 for (int i = 0; i < VLCGL_TEXTURE_COUNT; i++) {
414 for (int j = 0; j < PICTURE_PLANE_MAX; j++)
415 vgl->texture[i][j] = 0;
417 vgl->region_count = 0;
422 if (subpicture_chromas) {
423 *subpicture_chromas = NULL;
426 *subpicture_chromas = gl_subpicture_chromas;
432 void vout_display_opengl_Delete(vout_display_opengl_t *vgl)
435 if (!vlc_gl_Lock(vgl->gl)) {
439 for (int i = 0; i < VLCGL_TEXTURE_COUNT; i++)
440 glDeleteTextures(vgl->chroma->plane_count, vgl->texture[i]);
441 for (int i = 0; i < vgl->region_count; i++) {
442 if (vgl->region[i].texture)
443 glDeleteTextures(1, &vgl->region[i].texture);
448 vgl->DeleteProgramsARB(1, &vgl->program);
450 vlc_gl_Unlock(vgl->gl);
453 picture_pool_Delete(vgl->pool);
457 picture_pool_t *vout_display_opengl_GetPool(vout_display_opengl_t *vgl, unsigned requested_count)
462 /* Allocate our pictures */
463 picture_t *picture[VLCGL_PICTURE_MAX] = {NULL, };
466 for (count = 0; count < __MIN(VLCGL_PICTURE_MAX, requested_count); count++) {
467 picture[count] = picture_NewFromFormat(&vgl->fmt);
474 /* Wrap the pictures into a pool */
475 picture_pool_configuration_t cfg;
476 memset(&cfg, 0, sizeof(cfg));
477 cfg.picture_count = count;
478 cfg.picture = picture;
479 vgl->pool = picture_pool_NewExtended(&cfg);
483 /* Allocates our textures */
484 if (vlc_gl_Lock(vgl->gl))
487 for (int i = 0; i < VLCGL_TEXTURE_COUNT; i++) {
488 glGenTextures(vgl->chroma->plane_count, vgl->texture[i]);
489 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
490 if (vgl->use_multitexture)
491 vgl->ActiveTexture(GL_TEXTURE0 + j);
492 glBindTexture(vgl->tex_target, vgl->texture[i][j]);
495 /* Set the texture parameters */
496 glTexParameterf(vgl->tex_target, GL_TEXTURE_PRIORITY, 1.0);
497 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
500 glTexParameteri(vgl->tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
501 glTexParameteri(vgl->tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
502 glTexParameteri(vgl->tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
503 glTexParameteri(vgl->tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
505 /* Call glTexImage2D only once, and use glTexSubImage2D later */
506 glTexImage2D(vgl->tex_target, 0,
507 vgl->tex_internal, vgl->tex_width[j], vgl->tex_height[j],
508 0, vgl->tex_format, vgl->tex_type, NULL);
512 vlc_gl_Unlock(vgl->gl);
517 for (unsigned i = 0; i < count; i++)
518 picture_Release(picture[i]);
522 int vout_display_opengl_Prepare(vout_display_opengl_t *vgl,
523 picture_t *picture, subpicture_t *subpicture)
525 /* On Win32/GLX, we do this the usual way:
526 + Fill the buffer with new content,
527 + Reload the texture,
530 On OS X with VRAM or AGP texturing, the order has to be:
531 + Reload the texture,
532 + Fill the buffer with new content,
535 (Thanks to gcc from the Arstechnica forums for the tip)
537 Therefore on OSX, we have to use two buffers and textures and use a
538 lock(/unlock) managed picture pool.
541 if (vlc_gl_Lock(vgl->gl))
544 /* Update the texture */
545 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
546 if (vgl->use_multitexture)
547 vgl->ActiveTexture(GL_TEXTURE0 + j);
548 glBindTexture(vgl->tex_target, vgl->texture[0][j]);
549 glPixelStorei(GL_UNPACK_ROW_LENGTH, picture->p[j].i_pitch / picture->p[j].i_pixel_pitch);
550 glTexSubImage2D(vgl->tex_target, 0,
552 vgl->fmt.i_width * vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den,
553 vgl->fmt.i_height * vgl->chroma->p[j].h.num / vgl->chroma->p[j].h.den,
554 vgl->tex_format, vgl->tex_type, picture->p[j].p_pixels);
557 int last_count = vgl->region_count;
558 gl_region_t *last = vgl->region;
560 vgl->region_count = 0;
566 for (subpicture_region_t *r = subpicture->p_region; r; r = r->p_next)
569 vgl->region_count = count;
570 vgl->region = calloc(count, sizeof(*vgl->region));
572 if (vgl->use_multitexture)
573 vgl->ActiveTexture(GL_TEXTURE0 + 0);
575 for (subpicture_region_t *r = subpicture->p_region; r; r = r->p_next, i++) {
576 gl_region_t *glr = &vgl->region[i];
578 glr->format = GL_RGBA;
579 glr->type = GL_UNSIGNED_BYTE;
580 glr->width = r->fmt.i_visible_width;
581 glr->height = r->fmt.i_visible_height;
582 glr->alpha = (float)subpicture->i_alpha * r->i_alpha / 255 / 255;
583 glr->left = 2.0 * (r->i_x ) / subpicture->i_original_picture_width - 1.0;
584 glr->top = -2.0 * (r->i_y ) / subpicture->i_original_picture_height + 1.0;
585 glr->right = 2.0 * (r->i_x + r->fmt.i_visible_width ) / subpicture->i_original_picture_width - 1.0;
586 glr->bottom = -2.0 * (r->i_y + r->fmt.i_visible_height) / subpicture->i_original_picture_height + 1.0;
589 for (int j = 0; j < last_count; j++) {
590 if (last[j].texture &&
591 last[j].width == glr->width &&
592 last[j].height == glr->height &&
593 last[j].format == glr->format &&
594 last[j].type == glr->type) {
595 glr->texture = last[j].texture;
596 memset(&last[j], 0, sizeof(last[j]));
601 const int pixels_offset = r->fmt.i_y_offset * r->p_picture->p->i_pitch +
602 r->fmt.i_x_offset * r->p_picture->p->i_pixel_pitch;
604 glBindTexture(GL_TEXTURE_2D, glr->texture);
605 /* TODO set GL_UNPACK_ALIGNMENT */
606 glPixelStorei(GL_UNPACK_ROW_LENGTH, r->p_picture->p->i_pitch / r->p_picture->p->i_pixel_pitch);
607 glTexSubImage2D(GL_TEXTURE_2D, 0,
608 0, 0, glr->width, glr->height,
609 glr->format, glr->type, &r->p_picture->p->p_pixels[pixels_offset]);
611 glGenTextures(1, &glr->texture);
612 glBindTexture(GL_TEXTURE_2D, glr->texture);
613 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 1.0);
614 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
615 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
616 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
617 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
618 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
619 /* TODO set GL_UNPACK_ALIGNMENT */
620 glPixelStorei(GL_UNPACK_ROW_LENGTH, r->p_picture->p->i_pitch / r->p_picture->p->i_pixel_pitch);
621 glTexImage2D(GL_TEXTURE_2D, 0, glr->format,
622 glr->width, glr->height, 0, glr->format, glr->type,
623 &r->p_picture->p->p_pixels[pixels_offset]);
627 for (int i = 0; i < last_count; i++) {
629 glDeleteTextures(1, &last[i].texture);
633 vlc_gl_Unlock(vgl->gl);
634 VLC_UNUSED(subpicture);
638 int vout_display_opengl_Display(vout_display_opengl_t *vgl,
639 const video_format_t *source)
641 if (vlc_gl_Lock(vgl->gl))
644 /* glTexCoord works differently with GL_TEXTURE_2D and
645 GL_TEXTURE_RECTANGLE_EXT */
646 float left[PICTURE_PLANE_MAX];
647 float top[PICTURE_PLANE_MAX];
648 float right[PICTURE_PLANE_MAX];
649 float bottom[PICTURE_PLANE_MAX];
650 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
651 float scale_w, scale_h;
652 if (vgl->tex_target == GL_TEXTURE_2D) {
653 scale_w = (float)vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den / vgl->tex_width[j];
654 scale_h = (float)vgl->chroma->p[j].h.num / vgl->chroma->p[j].h.den / vgl->tex_height[j];
660 left[j] = (source->i_x_offset + 0 ) * scale_w;
661 top[j] = (source->i_y_offset + 0 ) * scale_h;
662 right[j] = (source->i_x_offset + source->i_visible_width ) * scale_w;
663 bottom[j] = (source->i_y_offset + source->i_visible_height) * scale_h;
667 /* Why drawing here and not in Render()? Because this way, the
668 OpenGL providers can call vout_display_opengl_Display to force redraw.i
669 Currently, the OS X provider uses it to get a smooth window resizing */
671 glClear(GL_COLOR_BUFFER_BIT);
674 glEnable(GL_FRAGMENT_PROGRAM_ARB);
675 for (int i = 0; i < vgl->local_count; i++)
676 vgl->ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, vgl->local_value[i]);
678 glEnable(vgl->tex_target);
682 static const GLfloat vertexCoord[] = {
689 const GLfloat textureCoord[8] = {
696 glEnableClientState(GL_VERTEX_ARRAY);
697 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
698 glVertexPointer(2, GL_FLOAT, 0, vertexCoord);
699 glTexCoordPointer(2, GL_FLOAT, 0, textureCoord);
701 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
703 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
704 glDisableClientState(GL_VERTEX_ARRAY);
705 glDisable(vgl->tex_target);
708 const GLfloat vertexCoord[] = {
715 for( unsigned j = 0; j < vgl->chroma->plane_count; j++)
717 const GLfloat texCoord[] = {
723 vgl->ActiveTexture( GL_TEXTURE0+j);
724 vgl->ClientActiveTexture( GL_TEXTURE0+j);
725 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
726 glBindTexture(vgl->tex_target, vgl->texture[0][j]);
727 glTexCoordPointer(2, GL_FLOAT, 0, texCoord);
729 glEnableClientState(GL_VERTEX_ARRAY);
730 glVertexPointer(2, GL_FLOAT, 0, vertexCoord);
731 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4);
732 glDisableClientState(GL_VERTEX_ARRAY);
734 for( int j = vgl->chroma->plane_count; j >= 0;j--)
736 vgl->ActiveTexture( GL_TEXTURE0+j);
737 vgl->ClientActiveTexture( GL_TEXTURE0+j);
738 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
744 glDisable(GL_FRAGMENT_PROGRAM_ARB);
746 glDisable(vgl->tex_target);
748 if (vgl->use_multitexture)
749 vgl->ActiveTexture(GL_TEXTURE0 + 0);
750 glEnable(GL_TEXTURE_2D);
752 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
753 glEnableClientState(GL_VERTEX_ARRAY);
754 const GLfloat textureCoord[] = {
760 for (int i = 0; i < vgl->region_count; i++) {
761 gl_region_t *glr = &vgl->region[i];
762 const GLfloat vertexCoord[] = {
764 glr->left, glr->bottom,
765 glr->right, glr->top,
766 glr->right,glr->bottom,
768 glColor4f(1.0f, 1.0f, 1.0f, glr->alpha);
769 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
771 glBindTexture(GL_TEXTURE_2D, glr->texture);
772 glVertexPointer(2, GL_FLOAT, 0, vertexCoord);
773 glTexCoordPointer(2, GL_FLOAT, 0, textureCoord);
774 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
775 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
777 glDisableClientState(GL_VERTEX_ARRAY);
779 glDisable(GL_TEXTURE_2D);
782 vlc_gl_Swap(vgl->gl);
784 vlc_gl_Unlock(vgl->gl);