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)
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->ActiveTexture = (PFNGLACTIVETEXTUREPROC)vlc_gl_GetProcAddress(vgl->gl, "glActiveTexture");
191 vgl->ClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)vlc_gl_GetProcAddress(vgl->gl, "glClientActiveTexture");
193 vgl->ActiveTexture = glActiveTexture;
194 vgl->ClientActiveTexture = glClientActiveTexture;
196 supports_multitexture = vgl->ActiveTexture &&
197 vgl->ClientActiveTexture;
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);
266 #if (defined (__ppc__) || defined (__ppc64__) || defined (__powerpc__)) && defined (__APPLE__)
267 /* This is a work-around for dated PowerPC-based Macs, which run OpenGL 1.3 only and don't
268 * support the GL_ARB_fragment_program extension.
269 * Affected devices are all Macs built between 2002 and 2005 with an ATI Radeon 7500,
270 * an ATI Radeon 9200 or a NVIDIA GeForceFX 5200 Ultra. */
273 vgl->tex_format = GL_YCBCR_422_APPLE;
274 vgl->tex_type = GL_UNSIGNED_SHORT_8_8_APPLE;
275 vgl->fmt.i_chroma = VLC_CODEC_YUYV;
279 vgl->chroma = vlc_fourcc_GetChromaDescription(vgl->fmt.i_chroma);
280 vgl->use_multitexture = vgl->chroma->plane_count > 1;
282 bool supports_npot = false;
283 #if USE_OPENGL_ES == 2
284 supports_npot = true;
286 supports_npot |= HasExtension(extensions, "GL_APPLE_texture_2D_limited_npot") ||
287 HasExtension(extensions, "GL_ARB_texture_non_power_of_two");
291 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
292 int w = vgl->fmt.i_width * vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den;
293 int h = vgl->fmt.i_height * vgl->chroma->p[j].h.num / vgl->chroma->p[j].h.den;
295 vgl->tex_width[j] = w;
296 vgl->tex_height[j] = h;
299 /* A texture must have a size aligned on a power of 2 */
300 vgl->tex_width[j] = GetAlignedSize(w);
301 vgl->tex_height[j] = GetAlignedSize(h);
305 /* Build fragment program if needed */
307 vgl->local_count = 0;
312 /* [R/G/B][Y U V O] from TV range to full range
313 * XXX we could also do hue/brightness/constrast/gamma
314 * by simply changing the coefficients
316 const float matrix_bt601_tv2full[3][4] = {
317 { 1.164383561643836, 0.0000, 1.596026785714286, -0.874202217873451 },
318 { 1.164383561643836, -0.391762290094914, -0.812967647237771, 0.531667823499146 },
319 { 1.164383561643836, 2.017232142857142, 0.0000, -1.085630789302022 },
321 const float matrix_bt709_tv2full[3][4] = {
322 { 1.164383561643836, 0.0000, 1.792741071428571, -0.972945075016308 },
323 { 1.164383561643836, -0.21324861427373, -0.532909328559444, 0.301482665475862 },
324 { 1.164383561643836, 2.112401785714286, 0.0000, -1.133402217873451 },
326 const float (*matrix)[4] = fmt->i_height > 576 ? matrix_bt709_tv2full
327 : matrix_bt601_tv2full;
329 /* Basic linear YUV -> RGB conversion using bilinear interpolation */
330 const char *template_yuv =
332 "OPTION ARB_precision_hint_fastest;"
335 "TEX src.x, fragment.texcoord[0], texture[0], 2D;"
336 "TEX src.%c, fragment.texcoord[1], texture[1], 2D;"
337 "TEX src.%c, fragment.texcoord[2], texture[2], 2D;"
339 "PARAM coefficient[4] = { program.local[0..3] };"
342 "MAD tmp.rgb, src.xxxx, coefficient[0], coefficient[3];"
343 "MAD tmp.rgb, src.yyyy, coefficient[1], tmp;"
344 "MAD result.color.rgb, src.zzzz, coefficient[2], tmp;"
346 bool swap_uv = vgl->fmt.i_chroma == VLC_CODEC_YV12 ||
347 vgl->fmt.i_chroma == VLC_CODEC_YV9;
348 if (asprintf(&code, template_yuv,
350 swap_uv ? 'y' : 'z') < 0)
353 for (int i = 0; i < 4; i++) {
354 float correction = i < 3 ? yuv_range_correction : 1.0;
355 for (int j = 0; j < 4; j++) {
356 vgl->local_value[vgl->local_count + i][j] = j < 3 ? correction * matrix[j][i] : 0.0;
359 vgl->local_count += 4;
362 // Here you have shaders
363 vgl->GenProgramsARB(1, &vgl->program);
364 vgl->BindProgramARB(GL_FRAGMENT_PROGRAM_ARB, vgl->program);
365 vgl->ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB,
366 GL_PROGRAM_FORMAT_ASCII_ARB,
367 strlen(code), (const GLbyte*)code);
368 if (glGetError() == GL_INVALID_OPERATION) {
369 /* FIXME if the program was needed for YUV, the video will be broken */
372 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &position);
374 const char *msg = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);
375 fprintf(stderr, "GL_INVALID_OPERATION: error at %d: %s\n", position, msg);
377 vgl->DeleteProgramsARB(1, &vgl->program);
386 glDisable(GL_DEPTH_TEST);
387 glDepthMask(GL_FALSE);
388 glDisable(GL_CULL_FACE);
389 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
390 glClear(GL_COLOR_BUFFER_BIT);
392 vlc_gl_Unlock(vgl->gl);
395 for (int i = 0; i < VLCGL_TEXTURE_COUNT; i++) {
396 for (int j = 0; j < PICTURE_PLANE_MAX; j++)
397 vgl->texture[i][j] = 0;
399 vgl->region_count = 0;
404 if (subpicture_chromas) {
405 *subpicture_chromas = NULL;
408 *subpicture_chromas = gl_subpicture_chromas;
414 void vout_display_opengl_Delete(vout_display_opengl_t *vgl)
417 if (!vlc_gl_Lock(vgl->gl)) {
421 for (int i = 0; i < VLCGL_TEXTURE_COUNT; i++)
422 glDeleteTextures(vgl->chroma->plane_count, vgl->texture[i]);
423 for (int i = 0; i < vgl->region_count; i++) {
424 if (vgl->region[i].texture)
425 glDeleteTextures(1, &vgl->region[i].texture);
430 vgl->DeleteProgramsARB(1, &vgl->program);
432 vlc_gl_Unlock(vgl->gl);
435 picture_pool_Delete(vgl->pool);
439 picture_pool_t *vout_display_opengl_GetPool(vout_display_opengl_t *vgl, unsigned requested_count)
444 /* Allocate our pictures */
445 picture_t *picture[VLCGL_PICTURE_MAX] = {NULL, };
448 for (count = 0; count < __MIN(VLCGL_PICTURE_MAX, requested_count); count++) {
449 picture[count] = picture_NewFromFormat(&vgl->fmt);
456 /* Wrap the pictures into a pool */
457 picture_pool_configuration_t cfg;
458 memset(&cfg, 0, sizeof(cfg));
459 cfg.picture_count = count;
460 cfg.picture = picture;
461 vgl->pool = picture_pool_NewExtended(&cfg);
465 /* Allocates our textures */
466 if (vlc_gl_Lock(vgl->gl))
469 for (int i = 0; i < VLCGL_TEXTURE_COUNT; i++) {
470 glGenTextures(vgl->chroma->plane_count, vgl->texture[i]);
471 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
472 if (vgl->use_multitexture)
473 vgl->ActiveTexture(GL_TEXTURE0 + j);
474 glBindTexture(vgl->tex_target, vgl->texture[i][j]);
477 /* Set the texture parameters */
478 glTexParameterf(vgl->tex_target, GL_TEXTURE_PRIORITY, 1.0);
479 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
482 glTexParameteri(vgl->tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
483 glTexParameteri(vgl->tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
484 glTexParameteri(vgl->tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
485 glTexParameteri(vgl->tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
487 /* Call glTexImage2D only once, and use glTexSubImage2D later */
488 glTexImage2D(vgl->tex_target, 0,
489 vgl->tex_internal, vgl->tex_width[j], vgl->tex_height[j],
490 0, vgl->tex_format, vgl->tex_type, NULL);
494 vlc_gl_Unlock(vgl->gl);
499 for (unsigned i = 0; i < count; i++)
500 picture_Release(picture[i]);
504 int vout_display_opengl_Prepare(vout_display_opengl_t *vgl,
505 picture_t *picture, subpicture_t *subpicture)
507 /* On Win32/GLX, we do this the usual way:
508 + Fill the buffer with new content,
509 + Reload the texture,
512 On OS X with VRAM or AGP texturing, the order has to be:
513 + Reload the texture,
514 + Fill the buffer with new content,
517 (Thanks to gcc from the Arstechnica forums for the tip)
519 Therefore on OSX, we have to use two buffers and textures and use a
520 lock(/unlock) managed picture pool.
523 if (vlc_gl_Lock(vgl->gl))
526 /* Update the texture */
527 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
528 if (vgl->use_multitexture)
529 vgl->ActiveTexture(GL_TEXTURE0 + j);
530 glBindTexture(vgl->tex_target, vgl->texture[0][j]);
531 glPixelStorei(GL_UNPACK_ROW_LENGTH, picture->p[j].i_pitch / picture->p[j].i_pixel_pitch);
532 glTexSubImage2D(vgl->tex_target, 0,
534 vgl->fmt.i_width * vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den,
535 vgl->fmt.i_height * vgl->chroma->p[j].h.num / vgl->chroma->p[j].h.den,
536 vgl->tex_format, vgl->tex_type, picture->p[j].p_pixels);
539 int last_count = vgl->region_count;
540 gl_region_t *last = vgl->region;
542 vgl->region_count = 0;
548 for (subpicture_region_t *r = subpicture->p_region; r; r = r->p_next)
551 vgl->region_count = count;
552 vgl->region = calloc(count, sizeof(*vgl->region));
554 if (vgl->use_multitexture)
555 vgl->ActiveTexture(GL_TEXTURE0 + 0);
557 for (subpicture_region_t *r = subpicture->p_region; r; r = r->p_next, i++) {
558 gl_region_t *glr = &vgl->region[i];
560 glr->format = GL_RGBA;
561 glr->type = GL_UNSIGNED_BYTE;
562 glr->width = r->fmt.i_visible_width;
563 glr->height = r->fmt.i_visible_height;
564 glr->alpha = (float)subpicture->i_alpha * r->i_alpha / 255 / 255;
565 glr->left = 2.0 * (r->i_x ) / subpicture->i_original_picture_width - 1.0;
566 glr->top = -2.0 * (r->i_y ) / subpicture->i_original_picture_height + 1.0;
567 glr->right = 2.0 * (r->i_x + r->fmt.i_visible_width ) / subpicture->i_original_picture_width - 1.0;
568 glr->bottom = -2.0 * (r->i_y + r->fmt.i_visible_height) / subpicture->i_original_picture_height + 1.0;
571 for (int j = 0; j < last_count; j++) {
572 if (last[j].texture &&
573 last[j].width == glr->width &&
574 last[j].height == glr->height &&
575 last[j].format == glr->format &&
576 last[j].type == glr->type) {
577 glr->texture = last[j].texture;
578 memset(&last[j], 0, sizeof(last[j]));
583 const int pixels_offset = r->fmt.i_y_offset * r->p_picture->p->i_pitch +
584 r->fmt.i_x_offset * r->p_picture->p->i_pixel_pitch;
586 glBindTexture(GL_TEXTURE_2D, glr->texture);
587 /* TODO set GL_UNPACK_ALIGNMENT */
588 glPixelStorei(GL_UNPACK_ROW_LENGTH, r->p_picture->p->i_pitch / r->p_picture->p->i_pixel_pitch);
589 glTexSubImage2D(GL_TEXTURE_2D, 0,
590 0, 0, glr->width, glr->height,
591 glr->format, glr->type, &r->p_picture->p->p_pixels[pixels_offset]);
593 glGenTextures(1, &glr->texture);
594 glBindTexture(GL_TEXTURE_2D, glr->texture);
595 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 1.0);
596 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
597 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
598 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
599 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
600 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
601 /* TODO set GL_UNPACK_ALIGNMENT */
602 glPixelStorei(GL_UNPACK_ROW_LENGTH, r->p_picture->p->i_pitch / r->p_picture->p->i_pixel_pitch);
603 glTexImage2D(GL_TEXTURE_2D, 0, glr->format,
604 glr->width, glr->height, 0, glr->format, glr->type,
605 &r->p_picture->p->p_pixels[pixels_offset]);
609 for (int i = 0; i < last_count; i++) {
611 glDeleteTextures(1, &last[i].texture);
615 vlc_gl_Unlock(vgl->gl);
616 VLC_UNUSED(subpicture);
620 int vout_display_opengl_Display(vout_display_opengl_t *vgl,
621 const video_format_t *source)
623 if (vlc_gl_Lock(vgl->gl))
626 /* glTexCoord works differently with GL_TEXTURE_2D and
627 GL_TEXTURE_RECTANGLE_EXT */
628 float left[PICTURE_PLANE_MAX];
629 float top[PICTURE_PLANE_MAX];
630 float right[PICTURE_PLANE_MAX];
631 float bottom[PICTURE_PLANE_MAX];
632 for (unsigned j = 0; j < vgl->chroma->plane_count; j++) {
633 float scale_w, scale_h;
634 if (vgl->tex_target == GL_TEXTURE_2D) {
635 scale_w = (float)vgl->chroma->p[j].w.num / vgl->chroma->p[j].w.den / vgl->tex_width[j];
636 scale_h = (float)vgl->chroma->p[j].h.num / vgl->chroma->p[j].h.den / vgl->tex_height[j];
642 left[j] = (source->i_x_offset + 0 ) * scale_w;
643 top[j] = (source->i_y_offset + 0 ) * scale_h;
644 right[j] = (source->i_x_offset + source->i_visible_width ) * scale_w;
645 bottom[j] = (source->i_y_offset + source->i_visible_height) * scale_h;
649 /* Why drawing here and not in Render()? Because this way, the
650 OpenGL providers can call vout_display_opengl_Display to force redraw.i
651 Currently, the OS X provider uses it to get a smooth window resizing */
653 glClear(GL_COLOR_BUFFER_BIT);
656 glEnable(GL_FRAGMENT_PROGRAM_ARB);
657 for (int i = 0; i < vgl->local_count; i++)
658 vgl->ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, vgl->local_value[i]);
660 glEnable(vgl->tex_target);
664 static const GLfloat vertexCoord[] = {
671 const GLfloat textureCoord[8] = {
678 glEnableClientState(GL_VERTEX_ARRAY);
679 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
680 glVertexPointer(2, GL_FLOAT, 0, vertexCoord);
681 glTexCoordPointer(2, GL_FLOAT, 0, textureCoord);
683 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
685 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
686 glDisableClientState(GL_VERTEX_ARRAY);
687 glDisable(vgl->tex_target);
690 const GLfloat vertexCoord[] = {
697 for( unsigned j = 0; j < vgl->chroma->plane_count; j++)
699 const GLfloat texCoord[] = {
705 vgl->ActiveTexture( GL_TEXTURE0+j);
706 vgl->ClientActiveTexture( GL_TEXTURE0+j);
707 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
708 glBindTexture(vgl->tex_target, vgl->texture[0][j]);
709 glTexCoordPointer(2, GL_FLOAT, 0, texCoord);
711 glEnableClientState(GL_VERTEX_ARRAY);
712 glVertexPointer(2, GL_FLOAT, 0, vertexCoord);
713 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4);
714 glDisableClientState(GL_VERTEX_ARRAY);
716 for( int j = vgl->chroma->plane_count; j >= 0;j--)
718 vgl->ActiveTexture( GL_TEXTURE0+j);
719 vgl->ClientActiveTexture( GL_TEXTURE0+j);
720 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
726 glDisable(GL_FRAGMENT_PROGRAM_ARB);
728 glDisable(vgl->tex_target);
730 if (vgl->use_multitexture)
731 vgl->ActiveTexture(GL_TEXTURE0 + 0);
732 glEnable(GL_TEXTURE_2D);
734 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
735 glEnableClientState(GL_VERTEX_ARRAY);
736 const GLfloat textureCoord[] = {
742 for (int i = 0; i < vgl->region_count; i++) {
743 gl_region_t *glr = &vgl->region[i];
744 const GLfloat vertexCoord[] = {
746 glr->left, glr->bottom,
747 glr->right, glr->top,
748 glr->right,glr->bottom,
750 glColor4f(1.0f, 1.0f, 1.0f, glr->alpha);
751 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
753 glBindTexture(GL_TEXTURE_2D, glr->texture);
754 glVertexPointer(2, GL_FLOAT, 0, vertexCoord);
755 glTexCoordPointer(2, GL_FLOAT, 0, textureCoord);
756 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
757 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
759 glDisableClientState(GL_VERTEX_ARRAY);
761 glDisable(GL_TEXTURE_2D);
764 vlc_gl_Swap(vgl->gl);
766 vlc_gl_Unlock(vgl->gl);