2 * common OpenGL routines
4 * copyleft (C) 2005-2010 Reimar Döffinger <Reimar.Doeffinger@gmx.de>
5 * Special thanks go to the xine team and Matthias Hopf, whose video_out_opengl.c
6 * gave me lots of good ideas.
8 * This file is part of MPlayer.
10 * MPlayer is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * MPlayer is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * You can alternatively redistribute this file and/or
25 * modify it under the terms of the GNU Lesser General Public
26 * License as published by the Free Software Foundation; either
27 * version 2.1 of the License, or (at your option) any later version.
32 * \brief OpenGL helper functions used by vo_gl.c and vo_gl2.c
42 #include "gl_common.h"
43 #include "old_vo_wrapper.h"
46 #include "pnm_loader.h"
49 //! \defgroup glgeneral OpenGL general helper functions
51 //! \defgroup glcontext OpenGL context management helper functions
53 //! \defgroup gltexture OpenGL texture handling helper functions
55 //! \defgroup glconversion OpenGL conversion helper functions
58 * \brief adjusts the GL_UNPACK_ALIGNMENT to fit the stride.
59 * \param stride number of bytes per line for which alignment should fit.
62 void glAdjustAlignment(GL
*gl
, int stride
)
67 else if (stride
% 4 == 0)
69 else if (stride
% 2 == 0)
73 gl
->PixelStorei(GL_UNPACK_ALIGNMENT
, gl_alignment
);
76 struct gl_name_map_struct
{
82 #define MAP(a) {a, # a}
83 //! mapping table for the glValName function
84 static const struct gl_name_map_struct gl_name_map
[] = {
86 MAP(GL_R3_G3_B2
), MAP(GL_RGB4
), MAP(GL_RGB5
), MAP(GL_RGB8
),
87 MAP(GL_RGB10
), MAP(GL_RGB12
), MAP(GL_RGB16
), MAP(GL_RGBA2
),
88 MAP(GL_RGBA4
), MAP(GL_RGB5_A1
), MAP(GL_RGBA8
), MAP(GL_RGB10_A2
),
89 MAP(GL_RGBA12
), MAP(GL_RGBA16
), MAP(GL_LUMINANCE8
), MAP(GL_LUMINANCE16
),
92 MAP(GL_RGB
), MAP(GL_RGBA
), MAP(GL_RED
), MAP(GL_GREEN
), MAP(GL_BLUE
),
93 MAP(GL_ALPHA
), MAP(GL_LUMINANCE
), MAP(GL_LUMINANCE_ALPHA
),
96 MAP(GL_BGR
), MAP(GL_BGRA
),
99 MAP(GL_BYTE
), MAP(GL_UNSIGNED_BYTE
), MAP(GL_SHORT
), MAP(GL_UNSIGNED_SHORT
),
100 MAP(GL_INT
), MAP(GL_UNSIGNED_INT
), MAP(GL_FLOAT
), MAP(GL_DOUBLE
),
101 MAP(GL_2_BYTES
), MAP(GL_3_BYTES
), MAP(GL_4_BYTES
),
103 MAP(GL_UNSIGNED_BYTE_3_3_2
), MAP(GL_UNSIGNED_BYTE_2_3_3_REV
),
104 MAP(GL_UNSIGNED_SHORT_5_6_5
), MAP(GL_UNSIGNED_SHORT_5_6_5_REV
),
105 MAP(GL_UNSIGNED_SHORT_4_4_4_4
), MAP(GL_UNSIGNED_SHORT_4_4_4_4_REV
),
106 MAP(GL_UNSIGNED_SHORT_5_5_5_1
), MAP(GL_UNSIGNED_SHORT_1_5_5_5_REV
),
107 MAP(GL_UNSIGNED_INT_8_8_8_8
), MAP(GL_UNSIGNED_INT_8_8_8_8_REV
),
108 MAP(GL_UNSIGNED_INT_10_10_10_2
), MAP(GL_UNSIGNED_INT_2_10_10_10_REV
),
114 * \brief return the name of an OpenGL constant
115 * \param value the constant
116 * \return name of the constant or "Unknown format!"
119 const char *glValName(GLint value
)
123 while (gl_name_map
[i
].name
) {
124 if (gl_name_map
[i
].value
== value
)
125 return gl_name_map
[i
].name
;
128 return "Unknown format!";
131 //! always return this format as internal texture format in glFindFormat
132 #define TEXTUREFORMAT_ALWAYS GL_RGB8
133 #undef TEXTUREFORMAT_ALWAYS
136 * \brief find the OpenGL settings coresponding to format.
138 * All parameters may be NULL.
139 * \param fmt MPlayer format to analyze.
140 * \param bpp [OUT] bits per pixel of that format.
141 * \param gl_texfmt [OUT] internal texture format that fits the
142 * image format, not necessarily the best for performance.
143 * \param gl_format [OUT] OpenGL format for this image format.
144 * \param gl_type [OUT] OpenGL type for this image format.
145 * \return 1 if format is supported by OpenGL, 0 if not.
148 int glFindFormat(uint32_t fmt
, int *bpp
, GLint
*gl_texfmt
,
149 GLenum
*gl_format
, GLenum
*gl_type
)
164 if (mp_get_chroma_shift(fmt
, NULL
, NULL
, NULL
)) {
165 // reduce the possible cases a bit
166 if (IMGFMT_IS_YUVP16_LE(fmt
))
167 fmt
= IMGFMT_420P16_LE
;
168 else if (IMGFMT_IS_YUVP16_BE(fmt
))
169 fmt
= IMGFMT_420P16_BE
;
174 *bpp
= IMGFMT_IS_BGR(fmt
) ? IMGFMT_BGR_DEPTH(fmt
) : IMGFMT_RGB_DEPTH(fmt
);
179 *gl_type
= GL_UNSIGNED_SHORT
;
183 *gl_type
= GL_UNSIGNED_BYTE
;
187 *gl_format
= GL_RGBA
;
188 *gl_type
= GL_UNSIGNED_BYTE
;
191 supported
= 0; // no native YUV support
192 *gl_texfmt
= GL_LUMINANCE16
;
194 *gl_format
= GL_LUMINANCE
;
195 *gl_type
= GL_UNSIGNED_SHORT
;
198 supported
= 0; // no native YV12 support
203 *gl_format
= GL_LUMINANCE
;
204 *gl_type
= GL_UNSIGNED_BYTE
;
207 // IMGFMT_YUY2 would be more logical for the _REV format,
208 // but gives clearly swapped colors.
210 *gl_texfmt
= GL_YCBCR_MESA
;
212 *gl_format
= GL_YCBCR_MESA
;
213 *gl_type
= fmt
== IMGFMT_UYVY
? GL_UNSIGNED_SHORT_8_8
: GL_UNSIGNED_SHORT_8_8_REV
;
216 // we do not support palettized formats, although the format the
217 // swscale produces works
220 gl_type
= GL_UNSIGNED_BYTE_2_3_3_REV
;
224 *gl_format
= GL_RGBA
;
225 *gl_type
= GL_UNSIGNED_SHORT_1_5_5_5_REV
;
229 *gl_type
= GL_UNSIGNED_SHORT_5_6_5_REV
;
233 // special case as red and blue have a differen number of bits.
234 // GL_BGR and GL_UNSIGNED_BYTE_3_3_2 isn't supported at least
235 // by nVidia drivers, and in addition would give more bits to
236 // blue than to red, which isn't wanted
238 gl_type
= GL_UNSIGNED_BYTE_3_3_2
;
242 *gl_format
= GL_BGRA
;
243 *gl_type
= GL_UNSIGNED_SHORT_1_5_5_5_REV
;
247 *gl_type
= GL_UNSIGNED_SHORT_5_6_5
;
251 *gl_type
= GL_UNSIGNED_BYTE
;
255 *gl_format
= GL_BGRA
;
256 *gl_type
= GL_UNSIGNED_BYTE
;
260 *gl_format
= GL_RGBA
;
261 *gl_type
= GL_UNSIGNED_BYTE
;
264 #ifdef TEXTUREFORMAT_ALWAYS
265 *gl_texfmt
= TEXTUREFORMAT_ALWAYS
;
274 * \brief find address of a linked function
275 * \param s name of function to find
276 * \return address of function or NULL if not found
278 static void *getdladdr(const char *s
)
282 void *handle
= dlopen(NULL
, RTLD_LAZY
);
285 ret
= dlsym(handle
, s
);
292 ptrdiff_t offset
; // offset to the function pointer in struct GL
294 const char *funcnames
[7];
298 #define DEF_FUNC_DESC(name) \
299 {offsetof(GL, name), NULL, {"gl" # name, NULL}, gl ## name}
300 #define DEF_EXT_FUNCS(...) __VA_ARGS__
301 #define DEF_EXT_DESC(name, ext, funcnames) \
302 {offsetof(GL, name), ext, {DEF_EXT_FUNCS funcnames}}
304 static const extfunc_desc_t extfuncs
[] = {
305 // these aren't extension functions but we query them anyway to allow
306 // different "backends" with one binary
307 DEF_FUNC_DESC(Begin
),
309 DEF_FUNC_DESC(Viewport
),
310 DEF_FUNC_DESC(MatrixMode
),
311 DEF_FUNC_DESC(LoadIdentity
),
312 DEF_FUNC_DESC(Translated
),
313 DEF_FUNC_DESC(Scaled
),
314 DEF_FUNC_DESC(Ortho
),
315 DEF_FUNC_DESC(Frustum
),
316 DEF_FUNC_DESC(PushMatrix
),
317 DEF_FUNC_DESC(PopMatrix
),
318 DEF_FUNC_DESC(Clear
),
319 DEF_FUNC_DESC(GenLists
),
320 DEF_FUNC_DESC(DeleteLists
),
321 DEF_FUNC_DESC(NewList
),
322 DEF_FUNC_DESC(EndList
),
323 DEF_FUNC_DESC(CallList
),
324 DEF_FUNC_DESC(CallLists
),
325 DEF_FUNC_DESC(GenTextures
),
326 DEF_FUNC_DESC(DeleteTextures
),
327 DEF_FUNC_DESC(TexEnvf
),
328 DEF_FUNC_DESC(TexEnvi
),
329 DEF_FUNC_DESC(Color4ub
),
330 DEF_FUNC_DESC(Color3f
),
331 DEF_FUNC_DESC(Color4f
),
332 DEF_FUNC_DESC(ClearColor
),
333 DEF_FUNC_DESC(ClearDepth
),
334 DEF_FUNC_DESC(DepthFunc
),
335 DEF_FUNC_DESC(Enable
),
336 DEF_FUNC_DESC(Disable
),
337 DEF_FUNC_DESC(DrawBuffer
),
338 DEF_FUNC_DESC(DepthMask
),
339 DEF_FUNC_DESC(BlendFunc
),
340 DEF_FUNC_DESC(Flush
),
341 DEF_FUNC_DESC(Finish
),
342 DEF_FUNC_DESC(PixelStorei
),
343 DEF_FUNC_DESC(TexImage1D
),
344 DEF_FUNC_DESC(TexImage2D
),
345 DEF_FUNC_DESC(TexSubImage2D
),
346 DEF_FUNC_DESC(GetTexImage
),
347 DEF_FUNC_DESC(TexParameteri
),
348 DEF_FUNC_DESC(TexParameterf
),
349 DEF_FUNC_DESC(TexParameterfv
),
350 DEF_FUNC_DESC(TexCoord2f
),
351 DEF_FUNC_DESC(Vertex2f
),
352 DEF_FUNC_DESC(Vertex3f
),
353 DEF_FUNC_DESC(Normal3f
),
354 DEF_FUNC_DESC(Lightfv
),
355 DEF_FUNC_DESC(ColorMaterial
),
356 DEF_FUNC_DESC(ShadeModel
),
357 DEF_FUNC_DESC(GetIntegerv
),
358 DEF_FUNC_DESC(ColorMask
),
359 DEF_FUNC_DESC(ReadPixels
),
360 DEF_FUNC_DESC(ReadBuffer
),
362 DEF_EXT_DESC(GenBuffers
, NULL
,
363 ("glGenBuffers", "glGenBuffersARB")),
364 DEF_EXT_DESC(DeleteBuffers
, NULL
,
365 ("glDeleteBuffers", "glDeleteBuffersARB")),
366 DEF_EXT_DESC(BindBuffer
, NULL
,
367 ("glBindBuffer", "glBindBufferARB")),
368 DEF_EXT_DESC(MapBuffer
, NULL
,
369 ("glMapBuffer", "glMapBufferARB")),
370 DEF_EXT_DESC(UnmapBuffer
, NULL
,
371 ("glUnmapBuffer", "glUnmapBufferARB")),
372 DEF_EXT_DESC(BufferData
, NULL
,
373 ("glBufferData", "glBufferDataARB")),
374 DEF_EXT_DESC(CombinerParameterfv
, "NV_register_combiners",
375 ("glCombinerParameterfv", "glCombinerParameterfvNV")),
376 DEF_EXT_DESC(CombinerParameteri
, "NV_register_combiners",
377 ("glCombinerParameteri", "glCombinerParameteriNV")),
378 DEF_EXT_DESC(CombinerInput
, "NV_register_combiners",
379 ("glCombinerInput", "glCombinerInputNV")),
380 DEF_EXT_DESC(CombinerOutput
, "NV_register_combiners",
381 ("glCombinerOutput", "glCombinerOutputNV")),
382 DEF_EXT_DESC(BeginFragmentShader
, "ATI_fragment_shader",
383 ("glBeginFragmentShaderATI")),
384 DEF_EXT_DESC(EndFragmentShader
, "ATI_fragment_shader",
385 ("glEndFragmentShaderATI")),
386 DEF_EXT_DESC(SampleMap
, "ATI_fragment_shader",
388 DEF_EXT_DESC(ColorFragmentOp2
, "ATI_fragment_shader",
389 ("glColorFragmentOp2ATI")),
390 DEF_EXT_DESC(ColorFragmentOp3
, "ATI_fragment_shader",
391 ("glColorFragmentOp3ATI")),
392 DEF_EXT_DESC(SetFragmentShaderConstant
, "ATI_fragment_shader",
393 ("glSetFragmentShaderConstantATI")),
394 DEF_EXT_DESC(ActiveTexture
, NULL
,
395 ("glActiveTexture", "glActiveTextureARB")),
396 DEF_EXT_DESC(BindTexture
, NULL
,
397 ("glBindTexture", "glBindTextureARB", "glBindTextureEXT")),
398 DEF_EXT_DESC(MultiTexCoord2f
, NULL
,
399 ("glMultiTexCoord2f", "glMultiTexCoord2fARB")),
400 DEF_EXT_DESC(GenPrograms
, "_program",
401 ("glGenProgramsARB")),
402 DEF_EXT_DESC(DeletePrograms
, "_program",
403 ("glDeleteProgramsARB")),
404 DEF_EXT_DESC(BindProgram
, "_program",
405 ("glBindProgramARB")),
406 DEF_EXT_DESC(ProgramString
, "_program",
407 ("glProgramStringARB")),
408 DEF_EXT_DESC(GetProgramiv
, "_program",
409 ("glGetProgramivARB")),
410 DEF_EXT_DESC(ProgramEnvParameter4f
, "_program",
411 ("glProgramEnvParameter4fARB")),
412 DEF_EXT_DESC(SwapInterval
, "_swap_control",
413 ("glXSwapIntervalSGI", "glXSwapInterval", "wglSwapIntervalSGI",
414 "wglSwapInterval", "wglSwapIntervalEXT")),
415 DEF_EXT_DESC(TexImage3D
, NULL
,
417 DEF_EXT_DESC(AllocateMemoryMESA
, "GLX_MESA_allocate_memory",
418 ("glXAllocateMemoryMESA")),
419 DEF_EXT_DESC(FreeMemoryMESA
, "GLX_MESA_allocate_memory",
420 ("glXFreeMemoryMESA")),
425 * \brief find the function pointers of some useful OpenGL extensions
426 * \param getProcAddress function to resolve function names, may be NULL
427 * \param ext2 an extra extension string
429 static void getFunctions(GL
*gl
, void *(*getProcAddress
)(const GLubyte
*),
432 const extfunc_desc_t
*dsc
;
433 const char *extensions
;
437 getProcAddress
= (void *)getdladdr
;
439 // special case, we need glGetString before starting to find the other functions
440 gl
->GetString
= getProcAddress("glGetString");
442 gl
->GetString
= glGetString
;
444 extensions
= (const char *)gl
->GetString(GL_EXTENSIONS
);
449 allexts
= malloc(strlen(extensions
) + strlen(ext2
) + 2);
450 strcpy(allexts
, extensions
);
451 strcat(allexts
, " ");
452 strcat(allexts
, ext2
);
453 mp_msg(MSGT_VO
, MSGL_DBG2
, "OpenGL extensions string:\n%s\n", allexts
);
454 for (dsc
= extfuncs
; dsc
->offset
>= 0; dsc
++) {
457 if (!dsc
->extstr
|| strstr(allexts
, dsc
->extstr
)) {
458 for (i
= 0; !ptr
&& dsc
->funcnames
[i
]; i
++)
459 ptr
= getProcAddress((const GLubyte
*)dsc
->funcnames
[i
]);
463 void **funcptr
= (void**)(((char*)gl
) + dsc
->offset
);
470 * \brief create a texture and set some defaults
471 * \param target texture taget, usually GL_TEXTURE_2D
472 * \param fmt internal texture format
473 * \param format texture host data format
474 * \param type texture host data type
475 * \param filter filter used for scaling, e.g. GL_LINEAR
476 * \param w texture width
477 * \param h texture height
478 * \param val luminance value to fill texture with
481 void glCreateClearTex(GL
*gl
, GLenum target
, GLenum fmt
, GLenum format
,
482 GLenum type
, GLint filter
, int w
, int h
,
485 GLfloat fval
= (GLfloat
)val
/ 255.0;
486 GLfloat border
[4] = {
487 fval
, fval
, fval
, fval
495 stride
= w
* glFmt2bpp(format
, type
);
498 init
= malloc(stride
* h
);
499 memset(init
, val
, stride
* h
);
500 glAdjustAlignment(gl
, stride
);
501 gl
->PixelStorei(GL_UNPACK_ROW_LENGTH
, w
);
502 gl
->TexImage2D(target
, 0, fmt
, w
, h
, 0, format
, type
, init
);
503 gl
->TexParameterf(target
, GL_TEXTURE_PRIORITY
, 1.0);
504 gl
->TexParameteri(target
, GL_TEXTURE_MIN_FILTER
, filter
);
505 gl
->TexParameteri(target
, GL_TEXTURE_MAG_FILTER
, filter
);
506 gl
->TexParameteri(target
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
507 gl
->TexParameteri(target
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
508 // Border texels should not be used with CLAMP_TO_EDGE
509 // We set a sane default anyway.
510 gl
->TexParameterfv(target
, GL_TEXTURE_BORDER_COLOR
, border
);
514 static GLint
detect_hqtexfmt(GL
*gl
)
516 const char *extensions
= (const char *)gl
->GetString(GL_EXTENSIONS
);
517 if (strstr(extensions
, "_texture_float"))
519 else if (strstr(extensions
, "NV_float_buffer"))
520 return GL_FLOAT_RGB32_NV
;
525 * \brief creates a texture from a PPM file
526 * \param target texture taget, usually GL_TEXTURE_2D
527 * \param fmt internal texture format, 0 for default
528 * \param filter filter used for scaling, e.g. GL_LINEAR
529 * \param f file to read PPM from
530 * \param width [out] width of texture
531 * \param height [out] height of texture
532 * \param maxval [out] maxval value from PPM file
533 * \return 0 on error, 1 otherwise
536 int glCreatePPMTex(GL
*gl
, GLenum target
, GLenum fmt
, GLint filter
,
537 FILE *f
, int *width
, int *height
, int *maxval
)
541 uint8_t *data
= read_pnm(f
, &w
, &h
, &bpp
, &m
);
542 GLint hqtexfmt
= detect_hqtexfmt(gl
);
543 if (!data
|| (bpp
!= 3 && bpp
!= 6)) {
548 fmt
= bpp
== 6 ? hqtexfmt
: 3;
549 if (fmt
== GL_FLOAT_RGB32_NV
&& target
!= GL_TEXTURE_RECTANGLE
)
552 type
= bpp
== 6 ? GL_UNSIGNED_SHORT
: GL_UNSIGNED_BYTE
;
553 glCreateClearTex(gl
, target
, fmt
, GL_RGB
, type
, filter
, w
, h
, 0);
554 glUploadTex(gl
, target
, GL_RGB
, type
,
555 data
, w
* bpp
, 0, 0, w
, h
, 0);
567 * \brief return the number of bytes per pixel for the given format
568 * \param format OpenGL format
569 * \param type OpenGL type
570 * \return bytes per pixel
573 * Does not handle all possible variants, just those used by MPlayer
575 int glFmt2bpp(GLenum format
, GLenum type
)
577 int component_size
= 0;
579 case GL_UNSIGNED_BYTE_3_3_2
:
580 case GL_UNSIGNED_BYTE_2_3_3_REV
:
582 case GL_UNSIGNED_SHORT_5_5_5_1
:
583 case GL_UNSIGNED_SHORT_1_5_5_5_REV
:
584 case GL_UNSIGNED_SHORT_5_6_5
:
585 case GL_UNSIGNED_SHORT_5_6_5_REV
:
587 case GL_UNSIGNED_BYTE
:
590 case GL_UNSIGNED_SHORT
:
597 return component_size
;
602 return 3 * component_size
;
605 return 4 * component_size
;
611 * \brief upload a texture, handling things like stride and slices
612 * \param target texture target, usually GL_TEXTURE_2D
613 * \param format OpenGL format of data
614 * \param type OpenGL type of data
615 * \param dataptr data to upload
616 * \param stride data stride
617 * \param x x offset in texture
618 * \param y y offset in texture
619 * \param w width of the texture part to upload
620 * \param h height of the texture part to upload
621 * \param slice height of an upload slice, 0 for all at once
624 void glUploadTex(GL
*gl
, GLenum target
, GLenum format
, GLenum type
,
625 const void *dataptr
, int stride
,
626 int x
, int y
, int w
, int h
, int slice
)
628 const uint8_t *data
= dataptr
;
630 if (w
<= 0 || h
<= 0)
635 data
+= (h
- 1) * stride
;
638 // this is not always correct, but should work for MPlayer
639 glAdjustAlignment(gl
, stride
);
640 gl
->PixelStorei(GL_UNPACK_ROW_LENGTH
, stride
/ glFmt2bpp(format
, type
));
641 for (; y
+ slice
<= y_max
; y
+= slice
) {
642 gl
->TexSubImage2D(target
, 0, x
, y
, w
, slice
, format
, type
, data
);
643 data
+= stride
* slice
;
646 gl
->TexSubImage2D(target
, 0, x
, y
, w
, y_max
- y
, format
, type
, data
);
649 static void fillUVcoeff(GLfloat
*ucoef
, GLfloat
*vcoef
,
650 float uvcos
, float uvsin
)
653 ucoef
[0] = 0 * uvcos
+ 1.403 * uvsin
;
654 vcoef
[0] = 0 * uvsin
+ 1.403 * uvcos
;
655 ucoef
[1] = -0.344 * uvcos
+ -0.714 * uvsin
;
656 vcoef
[1] = -0.344 * uvsin
+ -0.714 * uvcos
;
657 ucoef
[2] = 1.770 * uvcos
+ 0 * uvsin
;
658 vcoef
[2] = 1.770 * uvsin
+ 0 * uvcos
;
661 // Coefficients (probably) must be in [0, 1] range, whereas they originally
662 // are in [-2, 2] range, so here comes the trick:
663 // First put them in the [-0.5, 0.5] range, then add 0.5.
664 // This can be undone with the HALF_BIAS and SCALE_BY_FOUR arguments
665 // for CombinerInput and CombinerOutput (or the respective ATI variants)
666 for (i
= 0; i
< 4; i
++) {
667 ucoef
[i
] = ucoef
[i
] * 0.25 + 0.5;
668 vcoef
[i
] = vcoef
[i
] * 0.25 + 0.5;
673 * \brief Setup register combiners for YUV to RGB conversion.
674 * \param uvcos used for saturation and hue adjustment
675 * \param uvsin used for saturation and hue adjustment
677 static void glSetupYUVCombiners(GL
*gl
, float uvcos
, float uvsin
)
682 if (!gl
->CombinerInput
|| !gl
->CombinerOutput
||
683 !gl
->CombinerParameterfv
|| !gl
->CombinerParameteri
) {
684 mp_msg(MSGT_VO
, MSGL_FATAL
, "[gl] Combiner functions missing!\n");
687 gl
->GetIntegerv(GL_MAX_GENERAL_COMBINERS_NV
, &i
);
689 mp_msg(MSGT_VO
, MSGL_ERR
,
690 "[gl] 2 general combiners needed for YUV combiner support (found %i)\n", i
);
691 gl
->GetIntegerv(GL_MAX_TEXTURE_UNITS
, &i
);
693 mp_msg(MSGT_VO
, MSGL_ERR
,
694 "[gl] 3 texture units needed for YUV combiner support (found %i)\n", i
);
695 fillUVcoeff(ucoef
, vcoef
, uvcos
, uvsin
);
696 gl
->CombinerParameterfv(GL_CONSTANT_COLOR0_NV
, ucoef
);
697 gl
->CombinerParameterfv(GL_CONSTANT_COLOR1_NV
, vcoef
);
699 // UV first, like this green component cannot overflow
700 gl
->CombinerInput(GL_COMBINER0_NV
, GL_RGB
, GL_VARIABLE_A_NV
,
701 GL_TEXTURE1
, GL_HALF_BIAS_NORMAL_NV
, GL_RGB
);
702 gl
->CombinerInput(GL_COMBINER0_NV
, GL_RGB
, GL_VARIABLE_B_NV
,
703 GL_CONSTANT_COLOR0_NV
, GL_HALF_BIAS_NORMAL_NV
, GL_RGB
);
704 gl
->CombinerInput(GL_COMBINER0_NV
, GL_RGB
, GL_VARIABLE_C_NV
,
705 GL_TEXTURE2
, GL_HALF_BIAS_NORMAL_NV
, GL_RGB
);
706 gl
->CombinerInput(GL_COMBINER0_NV
, GL_RGB
, GL_VARIABLE_D_NV
,
707 GL_CONSTANT_COLOR1_NV
, GL_HALF_BIAS_NORMAL_NV
, GL_RGB
);
708 gl
->CombinerOutput(GL_COMBINER0_NV
, GL_RGB
, GL_DISCARD_NV
, GL_DISCARD_NV
,
709 GL_SPARE0_NV
, GL_SCALE_BY_FOUR_NV
, GL_NONE
, GL_FALSE
,
713 gl
->CombinerInput(GL_COMBINER1_NV
, GL_RGB
, GL_VARIABLE_A_NV
, GL_SPARE0_NV
,
714 GL_SIGNED_IDENTITY_NV
, GL_RGB
);
715 gl
->CombinerInput(GL_COMBINER1_NV
, GL_RGB
, GL_VARIABLE_B_NV
, GL_ZERO
,
716 GL_UNSIGNED_INVERT_NV
, GL_RGB
);
717 gl
->CombinerInput(GL_COMBINER1_NV
, GL_RGB
, GL_VARIABLE_C_NV
,
718 GL_TEXTURE0
, GL_SIGNED_IDENTITY_NV
, GL_RGB
);
719 gl
->CombinerInput(GL_COMBINER1_NV
, GL_RGB
, GL_VARIABLE_D_NV
, GL_ZERO
,
720 GL_UNSIGNED_INVERT_NV
, GL_RGB
);
721 gl
->CombinerOutput(GL_COMBINER1_NV
, GL_RGB
, GL_DISCARD_NV
, GL_DISCARD_NV
,
722 GL_SPARE0_NV
, GL_NONE
, GL_NONE
, GL_FALSE
,
725 // leave final combiner stage in default mode
726 gl
->CombinerParameteri(GL_NUM_GENERAL_COMBINERS_NV
, 2);
730 * \brief Setup ATI version of register combiners for YUV to RGB conversion.
731 * \param csp_params parameters used for colorspace conversion
732 * \param text if set use the GL_ATI_text_fragment_shader API as
735 static void glSetupYUVFragmentATI(GL
*gl
, struct mp_csp_params
*csp_params
,
741 gl
->GetIntegerv(GL_MAX_TEXTURE_UNITS
, &i
);
743 mp_msg(MSGT_VO
, MSGL_ERR
,
744 "[gl] 3 texture units needed for YUV combiner (ATI) support (found %i)\n", i
);
746 mp_get_yuv2rgb_coeffs(csp_params
, yuv2rgb
);
747 for (i
= 0; i
< 3; i
++) {
749 yuv2rgb
[i
][3] -= -0.5 * (yuv2rgb
[i
][1] + yuv2rgb
[i
][2]);
750 for (j
= 0; j
< 4; j
++) {
751 yuv2rgb
[i
][j
] *= 0.125;
752 yuv2rgb
[i
][j
] += 0.5;
753 if (yuv2rgb
[i
][j
] > 1)
755 if (yuv2rgb
[i
][j
] < 0)
760 GLfloat c0
[4] = { yuv2rgb
[0][0], yuv2rgb
[1][0], yuv2rgb
[2][0] };
761 GLfloat c1
[4] = { yuv2rgb
[0][1], yuv2rgb
[1][1], yuv2rgb
[2][1] };
762 GLfloat c2
[4] = { yuv2rgb
[0][2], yuv2rgb
[1][2], yuv2rgb
[2][2] };
763 GLfloat c3
[4] = { yuv2rgb
[0][3], yuv2rgb
[1][3], yuv2rgb
[2][3] };
764 if (!gl
->BeginFragmentShader
|| !gl
->EndFragmentShader
||
765 !gl
->SetFragmentShaderConstant
|| !gl
->SampleMap
||
766 !gl
->ColorFragmentOp2
|| !gl
->ColorFragmentOp3
) {
767 mp_msg(MSGT_VO
, MSGL_FATAL
, "[gl] Combiner (ATI) functions missing!\n");
770 gl
->GetIntegerv(GL_NUM_FRAGMENT_REGISTERS_ATI
, &i
);
772 mp_msg(MSGT_VO
, MSGL_ERR
,
773 "[gl] 3 registers needed for YUV combiner (ATI) support (found %i)\n", i
);
774 gl
->BeginFragmentShader();
775 gl
->SetFragmentShaderConstant(GL_CON_0_ATI
, c0
);
776 gl
->SetFragmentShaderConstant(GL_CON_1_ATI
, c1
);
777 gl
->SetFragmentShaderConstant(GL_CON_2_ATI
, c2
);
778 gl
->SetFragmentShaderConstant(GL_CON_3_ATI
, c3
);
779 gl
->SampleMap(GL_REG_0_ATI
, GL_TEXTURE0
, GL_SWIZZLE_STR_ATI
);
780 gl
->SampleMap(GL_REG_1_ATI
, GL_TEXTURE1
, GL_SWIZZLE_STR_ATI
);
781 gl
->SampleMap(GL_REG_2_ATI
, GL_TEXTURE2
, GL_SWIZZLE_STR_ATI
);
782 gl
->ColorFragmentOp2(GL_MUL_ATI
, GL_REG_1_ATI
, GL_NONE
, GL_NONE
,
783 GL_REG_1_ATI
, GL_NONE
, GL_BIAS_BIT_ATI
,
784 GL_CON_1_ATI
, GL_NONE
, GL_BIAS_BIT_ATI
);
785 gl
->ColorFragmentOp3(GL_MAD_ATI
, GL_REG_2_ATI
, GL_NONE
, GL_NONE
,
786 GL_REG_2_ATI
, GL_NONE
, GL_BIAS_BIT_ATI
,
787 GL_CON_2_ATI
, GL_NONE
, GL_BIAS_BIT_ATI
,
788 GL_REG_1_ATI
, GL_NONE
, GL_NONE
);
789 gl
->ColorFragmentOp3(GL_MAD_ATI
, GL_REG_0_ATI
, GL_NONE
, GL_NONE
,
790 GL_REG_0_ATI
, GL_NONE
, GL_NONE
,
791 GL_CON_0_ATI
, GL_NONE
, GL_BIAS_BIT_ATI
,
792 GL_REG_2_ATI
, GL_NONE
, GL_NONE
);
793 gl
->ColorFragmentOp2(GL_ADD_ATI
, GL_REG_0_ATI
, GL_NONE
, GL_8X_BIT_ATI
,
794 GL_REG_0_ATI
, GL_NONE
, GL_NONE
,
795 GL_CON_3_ATI
, GL_NONE
, GL_BIAS_BIT_ATI
);
796 gl
->EndFragmentShader();
798 static const char template[] =
801 " CONSTANT c0 = {%e, %e, %e};\n"
802 " CONSTANT c1 = {%e, %e, %e};\n"
803 " CONSTANT c2 = {%e, %e, %e};\n"
804 " CONSTANT c3 = {%e, %e, %e};\n"
807 " SampleMap r0, t0.str;\n"
808 " SampleMap r1, t1.str;\n"
809 " SampleMap r2, t2.str;\n"
810 " MUL r1.rgb, r1.bias, c1.bias;\n"
811 " MAD r2.rgb, r2.bias, c2.bias, r1;\n"
812 " MAD r0.rgb, r0, c0.bias, r2;\n"
813 " ADD r0.rgb.8x, r0, c3.bias;\n"
816 snprintf(buffer
, sizeof(buffer
), template,
817 yuv2rgb
[0][0], yuv2rgb
[1][0], yuv2rgb
[2][0],
818 yuv2rgb
[0][1], yuv2rgb
[1][1], yuv2rgb
[2][1],
819 yuv2rgb
[0][2], yuv2rgb
[1][2], yuv2rgb
[2][2],
820 yuv2rgb
[0][3], yuv2rgb
[1][3], yuv2rgb
[2][3]);
821 mp_msg(MSGT_VO
, MSGL_DBG2
, "[gl] generated fragment program:\n%s\n",
823 loadGPUProgram(gl
, GL_TEXT_FRAGMENT_SHADER_ATI
, buffer
);
828 * \brief helper function for gen_spline_lookup_tex
829 * \param x subpixel-position ((0,1) range) to calculate weights for
830 * \param dst where to store transformed weights, must provide space for 4 GLfloats
832 * calculates the weights and stores them after appropriate transformation
833 * for the scaler fragment program.
835 static void store_weights(float x
, GLfloat
*dst
)
837 float w0
= (((-1 * x
+ 3) * x
- 3) * x
+ 1) / 6;
838 float w1
= (((3 * x
- 6) * x
+ 0) * x
+ 4) / 6;
839 float w2
= (((-3 * x
+ 3) * x
+ 3) * x
+ 1) / 6;
840 float w3
= (((1 * x
+ 0) * x
+ 0) * x
+ 0) / 6;
841 *dst
++ = 1 + x
- w1
/ (w0
+ w1
);
842 *dst
++ = 1 - x
+ w3
/ (w2
+ w3
);
847 //! to avoid artefacts this should be rather large
848 #define LOOKUP_BSPLINE_RES (2 * 1024)
850 * \brief creates the 1D lookup texture needed for fast higher-order filtering
851 * \param unit texture unit to attach texture to
853 static void gen_spline_lookup_tex(GL
*gl
, GLenum unit
)
855 GLfloat
*tex
= calloc(4 * LOOKUP_BSPLINE_RES
, sizeof(*tex
));
858 for (i
= 0; i
< LOOKUP_BSPLINE_RES
; i
++) {
859 float x
= (float)(i
+ 0.5) / LOOKUP_BSPLINE_RES
;
860 store_weights(x
, tp
);
863 store_weights(0, tex
);
864 store_weights(1, &tex
[4 * (LOOKUP_BSPLINE_RES
- 1)]);
865 gl
->ActiveTexture(unit
);
866 gl
->TexImage1D(GL_TEXTURE_1D
, 0, GL_RGBA16
, LOOKUP_BSPLINE_RES
, 0, GL_RGBA
,
868 gl
->TexParameterf(GL_TEXTURE_1D
, GL_TEXTURE_PRIORITY
, 1.0);
869 gl
->TexParameteri(GL_TEXTURE_1D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
870 gl
->TexParameteri(GL_TEXTURE_1D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
871 gl
->TexParameteri(GL_TEXTURE_1D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
872 gl
->ActiveTexture(GL_TEXTURE0
);
876 static const char *bilin_filt_template
=
877 "TEX yuv.%c, fragment.texcoord[%c], texture[%c], %s;\n";
879 #define BICUB_FILT_MAIN(textype) \
880 /* first y-interpolation */ \
881 "ADD coord, fragment.texcoord[%c].xyxy, cdelta.xyxw;\n" \
882 "ADD coord2, fragment.texcoord[%c].xyxy, cdelta.zyzw;\n" \
883 "TEX a.r, coord.xyxy, texture[%c], "textype ";\n" \
884 "TEX a.g, coord.zwzw, texture[%c], "textype ";\n" \
885 /* second y-interpolation */ \
886 "TEX b.r, coord2.xyxy, texture[%c], "textype ";\n" \
887 "TEX b.g, coord2.zwzw, texture[%c], "textype ";\n" \
888 "LRP a.b, parmy.b, a.rrrr, a.gggg;\n" \
889 "LRP a.a, parmy.b, b.rrrr, b.gggg;\n" \
890 /* x-interpolation */ \
891 "LRP yuv.%c, parmx.b, a.bbbb, a.aaaa;\n"
893 static const char *bicub_filt_template_2D
=
894 "MAD coord.xy, fragment.texcoord[%c], {%e, %e}, {0.5, 0.5};\n"
895 "TEX parmx, coord.x, texture[%c], 1D;\n"
896 "MUL cdelta.xz, parmx.rrgg, {-%e, 0, %e, 0};\n"
897 "TEX parmy, coord.y, texture[%c], 1D;\n"
898 "MUL cdelta.yw, parmy.rrgg, {0, -%e, 0, %e};\n"
899 BICUB_FILT_MAIN("2D");
901 static const char *bicub_filt_template_RECT
=
902 "ADD coord, fragment.texcoord[%c], {0.5, 0.5};\n"
903 "TEX parmx, coord.x, texture[%c], 1D;\n"
904 "MUL cdelta.xz, parmx.rrgg, {-1, 0, 1, 0};\n"
905 "TEX parmy, coord.y, texture[%c], 1D;\n"
906 "MUL cdelta.yw, parmy.rrgg, {0, -1, 0, 1};\n"
907 BICUB_FILT_MAIN("RECT");
909 #define CALCWEIGHTS(t, s) \
910 "MAD "t ", {-0.5, 0.1666, 0.3333, -0.3333}, "s ", {1, 0, -0.5, 0.5};\n" \
911 "MAD "t ", "t ", "s ", {0, 0, -0.5, 0.5};\n" \
912 "MAD "t ", "t ", "s ", {-0.6666, 0, 0.8333, 0.1666};\n" \
913 "RCP a.x, "t ".z;\n" \
914 "RCP a.y, "t ".w;\n" \
915 "MAD "t ".xy, "t ".xyxy, a.xyxy, {1, 1, 0, 0};\n" \
916 "ADD "t ".x, "t ".xxxx, "s ";\n" \
917 "SUB "t ".y, "t ".yyyy, "s ";\n"
919 static const char *bicub_notex_filt_template_2D
=
920 "MAD coord.xy, fragment.texcoord[%c], {%e, %e}, {0.5, 0.5};\n"
921 "FRC coord.xy, coord.xyxy;\n"
922 CALCWEIGHTS("parmx", "coord.xxxx")
923 "MUL cdelta.xz, parmx.rrgg, {-%e, 0, %e, 0};\n"
924 CALCWEIGHTS("parmy", "coord.yyyy")
925 "MUL cdelta.yw, parmy.rrgg, {0, -%e, 0, %e};\n"
926 BICUB_FILT_MAIN("2D");
928 static const char *bicub_notex_filt_template_RECT
=
929 "ADD coord, fragment.texcoord[%c], {0.5, 0.5};\n"
930 "FRC coord.xy, coord.xyxy;\n"
931 CALCWEIGHTS("parmx", "coord.xxxx")
932 "MUL cdelta.xz, parmx.rrgg, {-1, 0, 1, 0};\n"
933 CALCWEIGHTS("parmy", "coord.yyyy")
934 "MUL cdelta.yw, parmy.rrgg, {0, -1, 0, 1};\n"
935 BICUB_FILT_MAIN("RECT");
937 #define BICUB_X_FILT_MAIN(textype) \
938 "ADD coord.xy, fragment.texcoord[%c].xyxy, cdelta.xyxy;\n" \
939 "ADD coord2.xy, fragment.texcoord[%c].xyxy, cdelta.zyzy;\n" \
940 "TEX a.r, coord, texture[%c], "textype ";\n" \
941 "TEX b.r, coord2, texture[%c], "textype ";\n" \
942 /* x-interpolation */ \
943 "LRP yuv.%c, parmx.b, a.rrrr, b.rrrr;\n"
945 static const char *bicub_x_filt_template_2D
=
946 "MAD coord.x, fragment.texcoord[%c], {%e}, {0.5};\n"
947 "TEX parmx, coord, texture[%c], 1D;\n"
948 "MUL cdelta.xyz, parmx.rrgg, {-%e, 0, %e};\n"
949 BICUB_X_FILT_MAIN("2D");
951 static const char *bicub_x_filt_template_RECT
=
952 "ADD coord.x, fragment.texcoord[%c], {0.5};\n"
953 "TEX parmx, coord, texture[%c], 1D;\n"
954 "MUL cdelta.xyz, parmx.rrgg, {-1, 0, 1};\n"
955 BICUB_X_FILT_MAIN("RECT");
957 static const char *unsharp_filt_template
=
958 "PARAM dcoord%c = {%e, %e, %e, %e};\n"
959 "ADD coord, fragment.texcoord[%c].xyxy, dcoord%c;\n"
960 "SUB coord2, fragment.texcoord[%c].xyxy, dcoord%c;\n"
961 "TEX a.r, fragment.texcoord[%c], texture[%c], %s;\n"
962 "TEX b.r, coord.xyxy, texture[%c], %s;\n"
963 "TEX b.g, coord.zwzw, texture[%c], %s;\n"
964 "ADD b.r, b.r, b.g;\n"
965 "TEX b.b, coord2.xyxy, texture[%c], %s;\n"
966 "TEX b.g, coord2.zwzw, texture[%c], %s;\n"
967 "DP3 b, b, {0.25, 0.25, 0.25};\n"
968 "SUB b.r, a.r, b.r;\n"
969 "MAD yuv.%c, b.r, {%e}, a.r;\n";
971 static const char *unsharp_filt_template2
=
972 "PARAM dcoord%c = {%e, %e, %e, %e};\n"
973 "PARAM dcoord2%c = {%e, 0, 0, %e};\n"
974 "ADD coord, fragment.texcoord[%c].xyxy, dcoord%c;\n"
975 "SUB coord2, fragment.texcoord[%c].xyxy, dcoord%c;\n"
976 "TEX a.r, fragment.texcoord[%c], texture[%c], %s;\n"
977 "TEX b.r, coord.xyxy, texture[%c], %s;\n"
978 "TEX b.g, coord.zwzw, texture[%c], %s;\n"
979 "ADD b.r, b.r, b.g;\n"
980 "TEX b.b, coord2.xyxy, texture[%c], %s;\n"
981 "TEX b.g, coord2.zwzw, texture[%c], %s;\n"
982 "ADD b.r, b.r, b.b;\n"
983 "ADD b.a, b.r, b.g;\n"
984 "ADD coord, fragment.texcoord[%c].xyxy, dcoord2%c;\n"
985 "SUB coord2, fragment.texcoord[%c].xyxy, dcoord2%c;\n"
986 "TEX b.r, coord.xyxy, texture[%c], %s;\n"
987 "TEX b.g, coord.zwzw, texture[%c], %s;\n"
988 "ADD b.r, b.r, b.g;\n"
989 "TEX b.b, coord2.xyxy, texture[%c], %s;\n"
990 "TEX b.g, coord2.zwzw, texture[%c], %s;\n"
991 "DP4 b.r, b, {-0.1171875, -0.1171875, -0.1171875, -0.09765625};\n"
992 "MAD b.r, a.r, {0.859375}, b.r;\n"
993 "MAD yuv.%c, b.r, {%e}, a.r;\n";
995 static const char *yuv_prog_template
=
996 "PARAM ycoef = {%e, %e, %e};\n"
997 "PARAM ucoef = {%e, %e, %e};\n"
998 "PARAM vcoef = {%e, %e, %e};\n"
999 "PARAM offsets = {%e, %e, %e};\n"
1001 "MAD res.rgb, yuv.rrrr, ycoef, offsets;\n"
1002 "MAD res.rgb, yuv.gggg, ucoef, res;\n"
1003 "MAD result.color.rgb, yuv.bbbb, vcoef, res;\n"
1006 static const char *yuv_pow_prog_template
=
1007 "PARAM ycoef = {%e, %e, %e};\n"
1008 "PARAM ucoef = {%e, %e, %e};\n"
1009 "PARAM vcoef = {%e, %e, %e};\n"
1010 "PARAM offsets = {%e, %e, %e};\n"
1011 "PARAM gamma = {%e, %e, %e};\n"
1013 "MAD res.rgb, yuv.rrrr, ycoef, offsets;\n"
1014 "MAD res.rgb, yuv.gggg, ucoef, res;\n"
1015 "MAD_SAT res.rgb, yuv.bbbb, vcoef, res;\n"
1016 "POW result.color.r, res.r, gamma.r;\n"
1017 "POW result.color.g, res.g, gamma.g;\n"
1018 "POW result.color.b, res.b, gamma.b;\n"
1021 static const char *yuv_lookup_prog_template
=
1022 "PARAM ycoef = {%e, %e, %e, 0};\n"
1023 "PARAM ucoef = {%e, %e, %e, 0};\n"
1024 "PARAM vcoef = {%e, %e, %e, 0};\n"
1025 "PARAM offsets = {%e, %e, %e, 0.125};\n"
1027 "MAD res, yuv.rrrr, ycoef, offsets;\n"
1028 "MAD res.rgb, yuv.gggg, ucoef, res;\n"
1029 "MAD res.rgb, yuv.bbbb, vcoef, res;\n"
1030 "TEX result.color.r, res.raaa, texture[%c], 2D;\n"
1031 "ADD res.a, res.a, 0.25;\n"
1032 "TEX result.color.g, res.gaaa, texture[%c], 2D;\n"
1033 "ADD res.a, res.a, 0.25;\n"
1034 "TEX result.color.b, res.baaa, texture[%c], 2D;\n"
1037 static const char *yuv_lookup3d_prog_template
=
1038 "TEX result.color, yuv, texture[%c], 3D;\n"
1042 * \brief creates and initializes helper textures needed for scaling texture read
1043 * \param scaler scaler type to create texture for
1044 * \param texu contains next free texture unit number
1045 * \param texs texture unit ids for the scaler are stored in this array
1047 static void create_scaler_textures(GL
*gl
, int scaler
, int *texu
, char *texs
)
1050 case YUV_SCALER_BILIN
:
1051 case YUV_SCALER_BICUB_NOTEX
:
1052 case YUV_SCALER_UNSHARP
:
1053 case YUV_SCALER_UNSHARP2
:
1055 case YUV_SCALER_BICUB
:
1056 case YUV_SCALER_BICUB_X
:
1057 texs
[0] = (*texu
)++;
1058 gen_spline_lookup_tex(gl
, GL_TEXTURE0
+ texs
[0]);
1062 mp_msg(MSGT_VO
, MSGL_ERR
, "[gl] unknown scaler type %i\n", scaler
);
1066 //! resolution of texture for gamma lookup table
1067 #define LOOKUP_RES 512
1068 //! resolution for 3D yuv->rgb conversion lookup table
1069 #define LOOKUP_3DRES 32
1071 * \brief creates and initializes helper textures needed for yuv conversion
1072 * \param params struct containing parameters like brightness, gamma, ...
1073 * \param texu contains next free texture unit number
1074 * \param texs texture unit ids for the conversion are stored in this array
1076 static void create_conv_textures(GL
*gl
, gl_conversion_params_t
*params
,
1077 int *texu
, char *texs
)
1079 unsigned char *lookup_data
= NULL
;
1080 int conv
= YUV_CONVERSION(params
->type
);
1082 case YUV_CONVERSION_FRAGMENT
:
1083 case YUV_CONVERSION_FRAGMENT_POW
:
1085 case YUV_CONVERSION_FRAGMENT_LOOKUP
:
1086 texs
[0] = (*texu
)++;
1087 gl
->ActiveTexture(GL_TEXTURE0
+ texs
[0]);
1088 lookup_data
= malloc(4 * LOOKUP_RES
);
1089 mp_gen_gamma_map(lookup_data
, LOOKUP_RES
, params
->csp_params
.rgamma
);
1090 mp_gen_gamma_map(&lookup_data
[LOOKUP_RES
], LOOKUP_RES
,
1091 params
->csp_params
.ggamma
);
1092 mp_gen_gamma_map(&lookup_data
[2 * LOOKUP_RES
], LOOKUP_RES
,
1093 params
->csp_params
.bgamma
);
1094 glCreateClearTex(gl
, GL_TEXTURE_2D
, GL_LUMINANCE8
, GL_LUMINANCE
,
1095 GL_UNSIGNED_BYTE
, GL_LINEAR
, LOOKUP_RES
, 4, 0);
1096 glUploadTex(gl
, GL_TEXTURE_2D
, GL_LUMINANCE
, GL_UNSIGNED_BYTE
,
1097 lookup_data
, LOOKUP_RES
, 0, 0, LOOKUP_RES
, 4, 0);
1098 gl
->ActiveTexture(GL_TEXTURE0
);
1101 case YUV_CONVERSION_FRAGMENT_LOOKUP3D
:
1103 int sz
= LOOKUP_3DRES
+ 2; // texture size including borders
1104 if (!gl
->TexImage3D
) {
1105 mp_msg(MSGT_VO
, MSGL_ERR
, "[gl] Missing 3D texture function!\n");
1108 texs
[0] = (*texu
)++;
1109 gl
->ActiveTexture(GL_TEXTURE0
+ texs
[0]);
1110 lookup_data
= malloc(3 * sz
* sz
* sz
);
1111 mp_gen_yuv2rgb_map(¶ms
->csp_params
, lookup_data
, LOOKUP_3DRES
);
1112 glAdjustAlignment(gl
, sz
);
1113 gl
->PixelStorei(GL_UNPACK_ROW_LENGTH
, 0);
1114 gl
->TexImage3D(GL_TEXTURE_3D
, 0, 3, sz
, sz
, sz
, 1,
1115 GL_RGB
, GL_UNSIGNED_BYTE
, lookup_data
);
1116 gl
->TexParameterf(GL_TEXTURE_3D
, GL_TEXTURE_PRIORITY
, 1.0);
1117 gl
->TexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
1118 gl
->TexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
1119 gl
->TexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
1120 gl
->TexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
1121 gl
->TexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_WRAP_R
, GL_CLAMP
);
1122 gl
->ActiveTexture(GL_TEXTURE0
);
1127 mp_msg(MSGT_VO
, MSGL_ERR
, "[gl] unknown conversion type %i\n", conv
);
1133 * \brief adds a scaling texture read at the current fragment program position
1134 * \param scaler type of scaler to insert
1135 * \param prog_pos current position in fragment program
1136 * \param remain how many bytes remain in the buffer given by prog_pos
1137 * \param texs array containing the texture unit identifiers for this scaler
1138 * \param in_tex texture unit the scaler should read from
1139 * \param out_comp component of the yuv variable the scaler stores the result in
1140 * \param rect if rectangular (pixel) adressing should be used for in_tex
1141 * \param texw width of the in_tex texture
1142 * \param texh height of the in_tex texture
1143 * \param strength strength of filter effect if the scaler does some kind of filtering
1145 static void add_scaler(int scaler
, char **prog_pos
, int *remain
, char *texs
,
1146 char in_tex
, char out_comp
, int rect
, int texw
, int texh
,
1149 const char *ttype
= rect
? "RECT" : "2D";
1150 const float ptw
= rect
? 1.0 : 1.0 / texw
;
1151 const float pth
= rect
? 1.0 : 1.0 / texh
;
1153 case YUV_SCALER_BILIN
:
1154 snprintf(*prog_pos
, *remain
, bilin_filt_template
, out_comp
, in_tex
,
1157 case YUV_SCALER_BICUB
:
1159 snprintf(*prog_pos
, *remain
, bicub_filt_template_RECT
,
1160 in_tex
, texs
[0], texs
[0],
1161 in_tex
, in_tex
, in_tex
, in_tex
, in_tex
, in_tex
, out_comp
);
1163 snprintf(*prog_pos
, *remain
, bicub_filt_template_2D
,
1164 in_tex
, (float)texw
, (float)texh
,
1165 texs
[0], ptw
, ptw
, texs
[0], pth
, pth
,
1166 in_tex
, in_tex
, in_tex
, in_tex
, in_tex
, in_tex
, out_comp
);
1168 case YUV_SCALER_BICUB_X
:
1170 snprintf(*prog_pos
, *remain
, bicub_x_filt_template_RECT
,
1172 in_tex
, in_tex
, in_tex
, in_tex
, out_comp
);
1174 snprintf(*prog_pos
, *remain
, bicub_x_filt_template_2D
,
1175 in_tex
, (float)texw
,
1177 in_tex
, in_tex
, in_tex
, in_tex
, out_comp
);
1179 case YUV_SCALER_BICUB_NOTEX
:
1181 snprintf(*prog_pos
, *remain
, bicub_notex_filt_template_RECT
,
1183 in_tex
, in_tex
, in_tex
, in_tex
, in_tex
, in_tex
, out_comp
);
1185 snprintf(*prog_pos
, *remain
, bicub_notex_filt_template_2D
,
1186 in_tex
, (float)texw
, (float)texh
, ptw
, ptw
, pth
, pth
,
1187 in_tex
, in_tex
, in_tex
, in_tex
, in_tex
, in_tex
, out_comp
);
1189 case YUV_SCALER_UNSHARP
:
1190 snprintf(*prog_pos
, *remain
, unsharp_filt_template
,
1191 out_comp
, 0.5 * ptw
, 0.5 * pth
, 0.5 * ptw
, -0.5 * pth
,
1192 in_tex
, out_comp
, in_tex
, out_comp
, in_tex
,
1193 in_tex
, ttype
, in_tex
, ttype
, in_tex
, ttype
, in_tex
, ttype
,
1194 in_tex
, ttype
, out_comp
, strength
);
1196 case YUV_SCALER_UNSHARP2
:
1197 snprintf(*prog_pos
, *remain
, unsharp_filt_template2
,
1198 out_comp
, 1.2 * ptw
, 1.2 * pth
, 1.2 * ptw
, -1.2 * pth
,
1199 out_comp
, 1.5 * ptw
, 1.5 * pth
,
1200 in_tex
, out_comp
, in_tex
, out_comp
, in_tex
,
1201 in_tex
, ttype
, in_tex
, ttype
, in_tex
, ttype
, in_tex
, ttype
,
1202 in_tex
, ttype
, in_tex
, out_comp
, in_tex
, out_comp
,
1203 in_tex
, ttype
, in_tex
, ttype
, in_tex
, ttype
,
1204 in_tex
, ttype
, out_comp
, strength
);
1207 *remain
-= strlen(*prog_pos
);
1208 *prog_pos
+= strlen(*prog_pos
);
1211 static const struct {
1216 {"instructions", 0x88A0, 0x88A1},
1217 {"native instructions", 0x88A2, 0x88A3},
1218 {"temporaries", 0x88A4, 0x88A5},
1219 {"native temporaries", 0x88A6, 0x88A7},
1220 {"parameters", 0x88A8, 0x88A9},
1221 {"native parameters", 0x88AA, 0x88AB},
1222 {"attribs", 0x88AC, 0x88AD},
1223 {"native attribs", 0x88AE, 0x88AF},
1224 {"ALU instructions", 0x8805, 0x880B},
1225 {"TEX instructions", 0x8806, 0x880C},
1226 {"TEX indirections", 0x8807, 0x880D},
1227 {"native ALU instructions", 0x8808, 0x880E},
1228 {"native TEX instructions", 0x8809, 0x880F},
1229 {"native TEX indirections", 0x880A, 0x8810},
1234 * \brief load the specified GPU Program
1235 * \param target program target to load into, only GL_FRAGMENT_PROGRAM is tested
1236 * \param prog program string
1237 * \return 1 on success, 0 otherwise
1239 int loadGPUProgram(GL
*gl
, GLenum target
, char *prog
)
1242 GLint cur
= 0, max
= 0, err
= 0;
1243 if (!gl
->ProgramString
) {
1244 mp_msg(MSGT_VO
, MSGL_ERR
, "[gl] Missing GPU program function\n");
1247 gl
->ProgramString(target
, GL_PROGRAM_FORMAT_ASCII
, strlen(prog
), prog
);
1248 gl
->GetIntegerv(GL_PROGRAM_ERROR_POSITION
, &err
);
1250 mp_msg(MSGT_VO
, MSGL_ERR
,
1251 "[gl] Error compiling fragment program, make sure your card supports\n"
1252 "[gl] GL_ARB_fragment_program (use glxinfo to check).\n"
1253 "[gl] Error message:\n %s at %.10s\n",
1254 gl
->GetString(GL_PROGRAM_ERROR_STRING
), &prog
[err
]);
1257 if (!gl
->GetProgramiv
|| !mp_msg_test(MSGT_VO
, MSGL_DBG2
))
1259 mp_msg(MSGT_VO
, MSGL_V
, "[gl] Program statistics:\n");
1260 for (i
= 0; progstats
[i
].name
; i
++) {
1261 gl
->GetProgramiv(target
, progstats
[i
].cur
, &cur
);
1262 gl
->GetProgramiv(target
, progstats
[i
].max
, &max
);
1263 mp_msg(MSGT_VO
, MSGL_V
, "[gl] %s: %i/%i\n", progstats
[i
].name
, cur
,
1269 #define MAX_PROGSZ (1024 * 1024)
1272 * \brief setup a fragment program that will do YUV->RGB conversion
1273 * \param parms struct containing parameters like conversion and scaler type,
1276 static void glSetupYUVFragprog(GL
*gl
, gl_conversion_params_t
*params
)
1278 int type
= params
->type
;
1279 int texw
= params
->texw
;
1280 int texh
= params
->texh
;
1281 int rect
= params
->target
== GL_TEXTURE_RECTANGLE
;
1282 static const char prog_hdr
[] =
1284 "OPTION ARB_precision_hint_fastest;\n"
1285 // all scaler variables must go here so they aren't defined
1286 // multiple times when the same scaler is used more than once
1287 "TEMP coord, coord2, cdelta, parmx, parmy, a, b, yuv;\n";
1289 char *yuv_prog
, *prog_pos
;
1291 char lum_scale_texs
[1];
1292 char chrom_scale_texs
[1];
1295 // this is the conversion matrix, with y, u, v factors
1296 // for red, green, blue and the constant offsets
1297 float yuv2rgb
[3][4];
1298 create_conv_textures(gl
, params
, &cur_texu
, conv_texs
);
1299 create_scaler_textures(gl
, YUV_LUM_SCALER(type
), &cur_texu
, lum_scale_texs
);
1300 if (YUV_CHROM_SCALER(type
) == YUV_LUM_SCALER(type
))
1301 memcpy(chrom_scale_texs
, lum_scale_texs
, sizeof(chrom_scale_texs
));
1303 create_scaler_textures(gl
, YUV_CHROM_SCALER(type
), &cur_texu
,
1305 gl
->GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &i
);
1307 mp_msg(MSGT_VO
, MSGL_ERR
,
1308 "[gl] %i texture units needed for this type of YUV fragment support (found %i)\n",
1310 if (!gl
->ProgramString
) {
1311 mp_msg(MSGT_VO
, MSGL_FATAL
, "[gl] ProgramString function missing!\n");
1314 yuv_prog
= malloc(MAX_PROGSZ
);
1315 strcpy(yuv_prog
, prog_hdr
);
1316 prog_pos
= yuv_prog
+ sizeof(prog_hdr
) - 1;
1317 prog_remain
= MAX_PROGSZ
- sizeof(prog_hdr
);
1318 add_scaler(YUV_LUM_SCALER(type
), &prog_pos
, &prog_remain
, lum_scale_texs
,
1319 '0', 'r', rect
, texw
, texh
, params
->filter_strength
);
1320 add_scaler(YUV_CHROM_SCALER(type
), &prog_pos
, &prog_remain
,
1321 chrom_scale_texs
, '1', 'g', rect
, params
->chrom_texw
,
1322 params
->chrom_texh
, params
->filter_strength
);
1323 add_scaler(YUV_CHROM_SCALER(type
), &prog_pos
, &prog_remain
,
1324 chrom_scale_texs
, '2', 'b', rect
, params
->chrom_texw
,
1325 params
->chrom_texh
, params
->filter_strength
);
1326 mp_get_yuv2rgb_coeffs(¶ms
->csp_params
, yuv2rgb
);
1327 switch (YUV_CONVERSION(type
)) {
1328 case YUV_CONVERSION_FRAGMENT
:
1329 snprintf(prog_pos
, prog_remain
, yuv_prog_template
,
1330 yuv2rgb
[ROW_R
][COL_Y
], yuv2rgb
[ROW_G
][COL_Y
], yuv2rgb
[ROW_B
][COL_Y
],
1331 yuv2rgb
[ROW_R
][COL_U
], yuv2rgb
[ROW_G
][COL_U
], yuv2rgb
[ROW_B
][COL_U
],
1332 yuv2rgb
[ROW_R
][COL_V
], yuv2rgb
[ROW_G
][COL_V
], yuv2rgb
[ROW_B
][COL_V
],
1333 yuv2rgb
[ROW_R
][COL_C
], yuv2rgb
[ROW_G
][COL_C
], yuv2rgb
[ROW_B
][COL_C
]);
1335 case YUV_CONVERSION_FRAGMENT_POW
:
1336 snprintf(prog_pos
, prog_remain
, yuv_pow_prog_template
,
1337 yuv2rgb
[ROW_R
][COL_Y
], yuv2rgb
[ROW_G
][COL_Y
], yuv2rgb
[ROW_B
][COL_Y
],
1338 yuv2rgb
[ROW_R
][COL_U
], yuv2rgb
[ROW_G
][COL_U
], yuv2rgb
[ROW_B
][COL_U
],
1339 yuv2rgb
[ROW_R
][COL_V
], yuv2rgb
[ROW_G
][COL_V
], yuv2rgb
[ROW_B
][COL_V
],
1340 yuv2rgb
[ROW_R
][COL_C
], yuv2rgb
[ROW_G
][COL_C
], yuv2rgb
[ROW_B
][COL_C
],
1341 (float)1.0 / params
->csp_params
.rgamma
,
1342 (float)1.0 / params
->csp_params
.bgamma
,
1343 (float)1.0 / params
->csp_params
.bgamma
);
1345 case YUV_CONVERSION_FRAGMENT_LOOKUP
:
1346 snprintf(prog_pos
, prog_remain
, yuv_lookup_prog_template
,
1347 yuv2rgb
[ROW_R
][COL_Y
], yuv2rgb
[ROW_G
][COL_Y
], yuv2rgb
[ROW_B
][COL_Y
],
1348 yuv2rgb
[ROW_R
][COL_U
], yuv2rgb
[ROW_G
][COL_U
], yuv2rgb
[ROW_B
][COL_U
],
1349 yuv2rgb
[ROW_R
][COL_V
], yuv2rgb
[ROW_G
][COL_V
], yuv2rgb
[ROW_B
][COL_V
],
1350 yuv2rgb
[ROW_R
][COL_C
], yuv2rgb
[ROW_G
][COL_C
], yuv2rgb
[ROW_B
][COL_C
],
1351 conv_texs
[0], conv_texs
[0], conv_texs
[0]);
1353 case YUV_CONVERSION_FRAGMENT_LOOKUP3D
:
1354 snprintf(prog_pos
, prog_remain
, yuv_lookup3d_prog_template
,
1358 mp_msg(MSGT_VO
, MSGL_ERR
, "[gl] unknown conversion type %i\n",
1359 YUV_CONVERSION(type
));
1362 mp_msg(MSGT_VO
, MSGL_DBG2
, "[gl] generated fragment program:\n%s\n",
1364 loadGPUProgram(gl
, GL_FRAGMENT_PROGRAM
, yuv_prog
);
1369 * \brief detect the best YUV->RGB conversion method available
1371 int glAutodetectYUVConversion(GL
*gl
)
1373 const char *extensions
= gl
->GetString(GL_EXTENSIONS
);
1374 if (!extensions
|| !gl
->MultiTexCoord2f
)
1375 return YUV_CONVERSION_NONE
;
1376 if (strstr(extensions
, "GL_ARB_fragment_program"))
1377 return YUV_CONVERSION_FRAGMENT
;
1378 if (strstr(extensions
, "GL_ATI_text_fragment_shader"))
1379 return YUV_CONVERSION_TEXT_FRAGMENT
;
1380 if (strstr(extensions
, "GL_ATI_fragment_shader"))
1381 return YUV_CONVERSION_COMBINERS_ATI
;
1382 return YUV_CONVERSION_NONE
;
1386 * \brief setup YUV->RGB conversion
1387 * \param parms struct containing parameters like conversion and scaler type,
1389 * \ingroup glconversion
1391 void glSetupYUVConversion(GL
*gl
, gl_conversion_params_t
*params
)
1393 float uvcos
= params
->csp_params
.saturation
* cos(params
->csp_params
.hue
);
1394 float uvsin
= params
->csp_params
.saturation
* sin(params
->csp_params
.hue
);
1395 if (params
->chrom_texw
== 0)
1396 params
->chrom_texw
= 1;
1397 if (params
->chrom_texh
== 0)
1398 params
->chrom_texh
= 1;
1399 switch (YUV_CONVERSION(params
->type
)) {
1400 case YUV_CONVERSION_COMBINERS
:
1401 glSetupYUVCombiners(gl
, uvcos
, uvsin
);
1403 case YUV_CONVERSION_COMBINERS_ATI
:
1404 glSetupYUVFragmentATI(gl
, ¶ms
->csp_params
, 0);
1406 case YUV_CONVERSION_TEXT_FRAGMENT
:
1407 glSetupYUVFragmentATI(gl
, ¶ms
->csp_params
, 1);
1409 case YUV_CONVERSION_FRAGMENT_LOOKUP
:
1410 case YUV_CONVERSION_FRAGMENT_LOOKUP3D
:
1411 case YUV_CONVERSION_FRAGMENT
:
1412 case YUV_CONVERSION_FRAGMENT_POW
:
1413 glSetupYUVFragprog(gl
, params
);
1415 case YUV_CONVERSION_NONE
:
1418 mp_msg(MSGT_VO
, MSGL_ERR
, "[gl] unknown conversion type %i\n",
1419 YUV_CONVERSION(params
->type
));
1424 * \brief enable the specified YUV conversion
1425 * \param target texture target for Y, U and V textures (e.g. GL_TEXTURE_2D)
1426 * \param type type of YUV conversion
1427 * \ingroup glconversion
1429 void glEnableYUVConversion(GL
*gl
, GLenum target
, int type
)
1431 switch (YUV_CONVERSION(type
)) {
1432 case YUV_CONVERSION_COMBINERS
:
1433 gl
->ActiveTexture(GL_TEXTURE1
);
1435 gl
->ActiveTexture(GL_TEXTURE2
);
1437 gl
->ActiveTexture(GL_TEXTURE0
);
1438 gl
->Enable(GL_REGISTER_COMBINERS_NV
);
1440 case YUV_CONVERSION_COMBINERS_ATI
:
1441 gl
->ActiveTexture(GL_TEXTURE1
);
1443 gl
->ActiveTexture(GL_TEXTURE2
);
1445 gl
->ActiveTexture(GL_TEXTURE0
);
1446 gl
->Enable(GL_FRAGMENT_SHADER_ATI
);
1448 case YUV_CONVERSION_TEXT_FRAGMENT
:
1449 gl
->ActiveTexture(GL_TEXTURE1
);
1451 gl
->ActiveTexture(GL_TEXTURE2
);
1453 gl
->ActiveTexture(GL_TEXTURE0
);
1454 gl
->Enable(GL_TEXT_FRAGMENT_SHADER_ATI
);
1456 case YUV_CONVERSION_FRAGMENT_LOOKUP3D
:
1457 case YUV_CONVERSION_FRAGMENT_LOOKUP
:
1458 case YUV_CONVERSION_FRAGMENT_POW
:
1459 case YUV_CONVERSION_FRAGMENT
:
1460 case YUV_CONVERSION_NONE
:
1461 gl
->Enable(GL_FRAGMENT_PROGRAM
);
1467 * \brief disable the specified YUV conversion
1468 * \param target texture target for Y, U and V textures (e.g. GL_TEXTURE_2D)
1469 * \param type type of YUV conversion
1470 * \ingroup glconversion
1472 void glDisableYUVConversion(GL
*gl
, GLenum target
, int type
)
1474 switch (YUV_CONVERSION(type
)) {
1475 case YUV_CONVERSION_COMBINERS
:
1476 gl
->ActiveTexture(GL_TEXTURE1
);
1477 gl
->Disable(target
);
1478 gl
->ActiveTexture(GL_TEXTURE2
);
1479 gl
->Disable(target
);
1480 gl
->ActiveTexture(GL_TEXTURE0
);
1481 gl
->Disable(GL_REGISTER_COMBINERS_NV
);
1483 case YUV_CONVERSION_COMBINERS_ATI
:
1484 gl
->ActiveTexture(GL_TEXTURE1
);
1485 gl
->Disable(target
);
1486 gl
->ActiveTexture(GL_TEXTURE2
);
1487 gl
->Disable(target
);
1488 gl
->ActiveTexture(GL_TEXTURE0
);
1489 gl
->Disable(GL_FRAGMENT_SHADER_ATI
);
1491 case YUV_CONVERSION_TEXT_FRAGMENT
:
1492 gl
->Disable(GL_TEXT_FRAGMENT_SHADER_ATI
);
1493 // HACK: at least the Mac OS X 10.5 PPC Radeon drivers are broken and
1494 // without this disable the texture units while the program is still
1495 // running (10.4 PPC seems to work without this though).
1497 gl
->ActiveTexture(GL_TEXTURE1
);
1498 gl
->Disable(target
);
1499 gl
->ActiveTexture(GL_TEXTURE2
);
1500 gl
->Disable(target
);
1501 gl
->ActiveTexture(GL_TEXTURE0
);
1503 case YUV_CONVERSION_FRAGMENT_LOOKUP3D
:
1504 case YUV_CONVERSION_FRAGMENT_LOOKUP
:
1505 case YUV_CONVERSION_FRAGMENT_POW
:
1506 case YUV_CONVERSION_FRAGMENT
:
1507 case YUV_CONVERSION_NONE
:
1508 gl
->Disable(GL_FRAGMENT_PROGRAM
);
1513 void glEnable3DLeft(GL
*gl
, int type
)
1517 case GL_3D_RED_CYAN
:
1518 gl
->ColorMask(GL_TRUE
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
1520 case GL_3D_GREEN_MAGENTA
:
1521 gl
->ColorMask(GL_FALSE
, GL_TRUE
, GL_FALSE
, GL_FALSE
);
1523 case GL_3D_QUADBUFFER
:
1524 gl
->GetIntegerv(GL_DRAW_BUFFER
, &buffer
);
1528 case GL_FRONT_RIGHT
:
1529 buffer
= GL_FRONT_LEFT
;
1534 buffer
= GL_BACK_LEFT
;
1537 gl
->DrawBuffer(buffer
);
1542 void glEnable3DRight(GL
*gl
, int type
)
1546 case GL_3D_RED_CYAN
:
1547 gl
->ColorMask(GL_FALSE
, GL_TRUE
, GL_TRUE
, GL_FALSE
);
1549 case GL_3D_GREEN_MAGENTA
:
1550 gl
->ColorMask(GL_TRUE
, GL_FALSE
, GL_TRUE
, GL_FALSE
);
1552 case GL_3D_QUADBUFFER
:
1553 gl
->GetIntegerv(GL_DRAW_BUFFER
, &buffer
);
1557 case GL_FRONT_RIGHT
:
1558 buffer
= GL_FRONT_RIGHT
;
1563 buffer
= GL_BACK_RIGHT
;
1566 gl
->DrawBuffer(buffer
);
1571 void glDisable3D(GL
*gl
, int type
)
1575 case GL_3D_RED_CYAN
:
1576 case GL_3D_GREEN_MAGENTA
:
1577 gl
->ColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
1579 case GL_3D_QUADBUFFER
:
1580 gl
->DrawBuffer(vo_doublebuffering
? GL_BACK
: GL_FRONT
);
1581 gl
->GetIntegerv(GL_DRAW_BUFFER
, &buffer
);
1585 case GL_FRONT_RIGHT
:
1594 gl
->DrawBuffer(buffer
);
1600 * \brief draw a texture part at given 2D coordinates
1601 * \param x screen top coordinate
1602 * \param y screen left coordinate
1603 * \param w screen width coordinate
1604 * \param h screen height coordinate
1605 * \param tx texture top coordinate in pixels
1606 * \param ty texture left coordinate in pixels
1607 * \param tw texture part width in pixels
1608 * \param th texture part height in pixels
1609 * \param sx width of texture in pixels
1610 * \param sy height of texture in pixels
1611 * \param rect_tex whether this texture uses texture_rectangle extension
1612 * \param is_yv12 if != 0, also draw the textures from units 1 and 2,
1613 * bits 8 - 15 and 16 - 23 specify the x and y scaling of those textures
1614 * \param flip flip the texture upside down
1615 * \ingroup gltexture
1617 void glDrawTex(GL
*gl
, GLfloat x
, GLfloat y
, GLfloat w
, GLfloat h
,
1618 GLfloat tx
, GLfloat ty
, GLfloat tw
, GLfloat th
,
1619 int sx
, int sy
, int rect_tex
, int is_yv12
, int flip
)
1621 int chroma_x_shift
= (is_yv12
>> 8) & 31;
1622 int chroma_y_shift
= (is_yv12
>> 16) & 31;
1623 GLfloat xscale
= 1 << chroma_x_shift
;
1624 GLfloat yscale
= 1 << chroma_y_shift
;
1625 GLfloat tx2
= tx
/ xscale
, ty2
= ty
/ yscale
, tw2
= tw
/ xscale
, th2
= th
/ yscale
;
1631 tx2
= tx
, ty2
= ty
, tw2
= tw
, th2
= th
;
1637 gl
->Begin(GL_QUADS
);
1638 gl
->TexCoord2f(tx
, ty
);
1640 gl
->MultiTexCoord2f(GL_TEXTURE1
, tx2
, ty2
);
1641 gl
->MultiTexCoord2f(GL_TEXTURE2
, tx2
, ty2
);
1644 gl
->TexCoord2f(tx
, ty
+ th
);
1646 gl
->MultiTexCoord2f(GL_TEXTURE1
, tx2
, ty2
+ th2
);
1647 gl
->MultiTexCoord2f(GL_TEXTURE2
, tx2
, ty2
+ th2
);
1649 gl
->Vertex2f(x
, y
+ h
);
1650 gl
->TexCoord2f(tx
+ tw
, ty
+ th
);
1652 gl
->MultiTexCoord2f(GL_TEXTURE1
, tx2
+ tw2
, ty2
+ th2
);
1653 gl
->MultiTexCoord2f(GL_TEXTURE2
, tx2
+ tw2
, ty2
+ th2
);
1655 gl
->Vertex2f(x
+ w
, y
+ h
);
1656 gl
->TexCoord2f(tx
+ tw
, ty
);
1658 gl
->MultiTexCoord2f(GL_TEXTURE1
, tx2
+ tw2
, ty2
);
1659 gl
->MultiTexCoord2f(GL_TEXTURE2
, tx2
+ tw2
, ty2
);
1661 gl
->Vertex2f(x
+ w
, y
);
1665 #ifdef CONFIG_GL_WIN32
1666 #include "w32_common.h"
1668 static int create_window_w32(struct MPGLContext
*ctx
, uint32_t d_width
,
1669 uint32_t d_height
, uint32_t flags
,
1672 if (!vo_w32_config(d_width
, d_height
, flags
))
1678 * \brief little helper since wglGetProcAddress definition does not fit our
1680 * \param procName name of function to look up
1681 * \return function pointer returned by wglGetProcAddress
1683 static void *w32gpa(const GLubyte
*procName
)
1686 void *res
= wglGetProcAddress(procName
);
1689 oglmod
= GetModuleHandle("opengl32.dll");
1690 return GetProcAddress(oglmod
, procName
);
1693 static int setGlWindow_w32(MPGLContext
*ctx
)
1695 HWND win
= vo_w32_window
;
1696 int *vinfo
= &ctx
->vinfo
.w32
;
1697 HGLRC
*context
= &ctx
->context
.w32
;
1699 HDC windc
= vo_w32_get_dc(win
);
1700 HGLRC new_context
= 0;
1701 int keep_context
= 0;
1702 int res
= SET_WINDOW_FAILED
;
1705 // should only be needed when keeping context, but not doing glFinish
1706 // can cause flickering even when we do not keep it.
1709 new_vinfo
= GetPixelFormat(windc
);
1710 if (*context
&& *vinfo
&& new_vinfo
&& *vinfo
== new_vinfo
) {
1711 // we can keep the wglContext
1712 new_context
= *context
;
1716 new_context
= wglCreateContext(windc
);
1718 mp_msg(MSGT_VO
, MSGL_FATAL
, "[gl] Could not create GL context!\n");
1724 if (!wglMakeCurrent(windc
, new_context
)) {
1725 mp_msg(MSGT_VO
, MSGL_FATAL
, "[gl] Could not set GL context!\n");
1727 wglDeleteContext(new_context
);
1732 vo_w32_window
= win
;
1735 GetClientRect(win
, &rect
);
1736 ctx
->vo
->dwidth
= rect
.right
;
1737 ctx
->vo
->dheight
= rect
.bottom
;
1739 if (!keep_context
) {
1741 wglDeleteContext(*context
);
1742 *context
= new_context
;
1744 getFunctions(gl
, w32gpa
, NULL
);
1746 // and inform that reinit is neccessary
1747 res
= SET_WINDOW_REINIT
;
1749 res
= SET_WINDOW_OK
;
1752 vo_w32_release_dc(win
, windc
);
1756 static void releaseGlContext_w32(MPGLContext
*ctx
)
1758 int *vinfo
= &ctx
->vinfo
.w32
;
1759 HGLRC
*context
= &ctx
->context
.w32
;
1762 wglMakeCurrent(0, 0);
1763 wglDeleteContext(*context
);
1768 static void swapGlBuffers_w32(MPGLContext
*ctx
)
1770 HDC vo_hdc
= vo_w32_get_dc(vo_w32_window
);
1771 SwapBuffers(vo_hdc
);
1772 vo_w32_release_dc(vo_w32_window
, vo_hdc
);
1775 //trivial wrappers (w32 code uses old vo API)
1776 static void new_vo_w32_ontop(struct vo
*vo
) { vo_w32_ontop(); }
1777 static void new_vo_w32_border(struct vo
*vo
) { vo_w32_border(); }
1778 static void new_vo_w32_fullscreen(struct vo
*vo
) { vo_w32_fullscreen(); }
1779 static int new_vo_w32_check_events(struct vo
*vo
) { return vo_w32_check_events(); }
1780 static void new_w32_update_xinerama_info(struct vo
*vo
) { w32_update_xinerama_info(); }
1782 #ifdef CONFIG_GL_X11
1783 #include "x11_common.h"
1785 static int create_window_x11(struct MPGLContext
*ctx
, uint32_t d_width
,
1786 uint32_t d_height
, uint32_t flags
,
1789 struct vo
*vo
= ctx
->vo
;
1791 static int default_glx_attribs
[] = {
1792 GLX_RGBA
, GLX_RED_SIZE
, 1, GLX_GREEN_SIZE
, 1, GLX_BLUE_SIZE
, 1,
1793 GLX_DOUBLEBUFFER
, None
1795 static int stereo_glx_attribs
[] = {
1796 GLX_RGBA
, GLX_RED_SIZE
, 1, GLX_GREEN_SIZE
, 1, GLX_BLUE_SIZE
, 1,
1797 GLX_DOUBLEBUFFER
, GLX_STEREO
, None
1799 XVisualInfo
*vinfo
= NULL
;
1800 if (flags
& VOFLAG_STEREO
) {
1801 vinfo
= glXChooseVisual(vo
->x11
->display
, vo
->x11
->screen
,
1802 stereo_glx_attribs
);
1804 mp_msg(MSGT_VO
, MSGL_ERR
, "[gl] Could not find a stereo visual,"
1805 " 3D will probably not work!\n");
1808 vinfo
= glXChooseVisual(vo
->x11
->display
, vo
->x11
->screen
,
1809 default_glx_attribs
);
1811 mp_msg(MSGT_VO
, MSGL_ERR
, "[gl] no GLX support present\n");
1814 mp_msg(MSGT_VO
, MSGL_V
, "[gl] GLX chose visual with ID 0x%x\n",
1815 (int)vinfo
->visualid
);
1817 Colormap colormap
= XCreateColormap(vo
->x11
->display
, vo
->x11
->rootwin
,
1818 vinfo
->visual
, AllocNone
);
1819 vo_x11_create_vo_window(vo
, vinfo
, vo
->dx
, vo
->dy
, d_width
, d_height
,
1820 flags
, colormap
, "gl", title
);
1826 * \brief Returns the XVisualInfo associated with Window win.
1827 * \param win Window whose XVisualInfo is returne.
1828 * \return XVisualInfo of the window. Caller must use XFree to free it.
1830 static XVisualInfo
*getWindowVisualInfo(MPGLContext
*ctx
, Window win
)
1832 XWindowAttributes xw_attr
;
1833 XVisualInfo vinfo_template
;
1835 XGetWindowAttributes(ctx
->vo
->x11
->display
, win
, &xw_attr
);
1836 vinfo_template
.visualid
= XVisualIDFromVisual(xw_attr
.visual
);
1837 return XGetVisualInfo(ctx
->vo
->x11
->display
, VisualIDMask
, &vinfo_template
, &tmp
);
1840 static void appendstr(char **dst
, const char *str
)
1846 newsize
= strlen(*dst
) + 1 + strlen(str
) + 1;
1847 newstr
= realloc(*dst
, newsize
);
1856 * \brief Changes the window in which video is displayed.
1857 * If possible only transfers the context to the new window, otherwise
1858 * creates a new one, which must be initialized by the caller.
1859 * \param vinfo Currently used visual.
1860 * \param context Currently used context.
1861 * \param win window that should be used for drawing.
1862 * \return one of SET_WINDOW_FAILED, SET_WINDOW_OK or SET_WINDOW_REINIT.
1863 * In case of SET_WINDOW_REINIT the context could not be transfered
1864 * and the caller must initialize it correctly.
1865 * \ingroup glcontext
1867 static int setGlWindow_x11(MPGLContext
*ctx
)
1869 XVisualInfo
**vinfo
= &ctx
->vinfo
.x11
;
1870 GLXContext
*context
= &ctx
->context
.x11
;
1871 Display
*display
= ctx
->vo
->x11
->display
;
1872 Window win
= ctx
->vo
->x11
->window
;
1873 XVisualInfo
*new_vinfo
;
1874 GLXContext new_context
= NULL
;
1875 int keep_context
= 0;
1878 // should only be needed when keeping context, but not doing glFinish
1879 // can cause flickering even when we do not keep it.
1882 new_vinfo
= getWindowVisualInfo(ctx
, win
);
1883 if (*context
&& *vinfo
&& new_vinfo
&&
1884 (*vinfo
)->visualid
== new_vinfo
->visualid
) {
1885 // we can keep the GLXContext
1886 new_context
= *context
;
1892 new_context
= glXCreateContext(display
, new_vinfo
, NULL
, True
);
1894 mp_msg(MSGT_VO
, MSGL_FATAL
, "[gl] Could not create GLX context!\n");
1896 return SET_WINDOW_FAILED
;
1901 if (!glXMakeCurrent(display
, ctx
->vo
->x11
->window
, new_context
)) {
1902 mp_msg(MSGT_VO
, MSGL_FATAL
, "[gl] Could not set GLX context!\n");
1903 if (!keep_context
) {
1904 glXDestroyContext(display
, new_context
);
1907 return SET_WINDOW_FAILED
;
1911 ctx
->vo
->x11
->window
= win
;
1912 vo_x11_update_geometry(ctx
->vo
, 1);
1913 if (!keep_context
) {
1914 void *(*getProcAddress
)(const GLubyte
*);
1915 const char *(*glXExtStr
)(Display
*, int);
1916 char *glxstr
= strdup("");
1918 glXDestroyContext(display
, *context
);
1919 *context
= new_context
;
1923 getProcAddress
= getdladdr("glXGetProcAddress");
1924 if (!getProcAddress
)
1925 getProcAddress
= getdladdr("glXGetProcAddressARB");
1926 glXExtStr
= getdladdr("glXQueryExtensionsString");
1928 appendstr(&glxstr
, glXExtStr(display
, DefaultScreen(display
)));
1929 glXExtStr
= getdladdr("glXGetClientString");
1931 appendstr(&glxstr
, glXExtStr(display
, GLX_EXTENSIONS
));
1932 glXExtStr
= getdladdr("glXGetServerString");
1934 appendstr(&glxstr
, glXExtStr(display
, GLX_EXTENSIONS
));
1936 getFunctions(gl
, getProcAddress
, glxstr
);
1937 if (!gl
->GenPrograms
&& gl
->GetString
&&
1939 strstr(gl
->GetString(GL_EXTENSIONS
), "GL_ARB_vertex_program")) {
1940 mp_msg(MSGT_VO
, MSGL_WARN
,
1941 "Broken glXGetProcAddress detected, trying workaround\n");
1942 getFunctions(gl
, NULL
, glxstr
);
1946 // and inform that reinit is neccessary
1947 return SET_WINDOW_REINIT
;
1949 return SET_WINDOW_OK
;
1953 * \brief free the VisualInfo and GLXContext of an OpenGL context.
1954 * \ingroup glcontext
1956 static void releaseGlContext_x11(MPGLContext
*ctx
)
1958 XVisualInfo
**vinfo
= &ctx
->vinfo
.x11
;
1959 GLXContext
*context
= &ctx
->context
.x11
;
1960 Display
*display
= ctx
->vo
->x11
->display
;
1967 glXMakeCurrent(display
, None
, NULL
);
1968 glXDestroyContext(display
, *context
);
1973 static void swapGlBuffers_x11(MPGLContext
*ctx
)
1975 glXSwapBuffers(ctx
->vo
->x11
->display
, ctx
->vo
->x11
->window
);
1979 #ifdef CONFIG_GL_SDL
1980 #include "sdl_common.h"
1982 static int create_window_sdl(struct MPGLContext
*ctx
, uint32_t d_width
,
1983 uint32_t d_height
, uint32_t flags
,
1986 SDL_WM_SetCaption(title
, NULL
);
1987 ctx
->vo
->dwidth
= d_width
;
1988 ctx
->vo
->dheight
= d_height
;
1992 static void swapGlBuffers_sdl(MPGLContext
*ctx
)
1994 SDL_GL_SwapBuffers();
1997 static void *sdlgpa(const GLubyte
*name
)
1999 return SDL_GL_GetProcAddress(name
);
2002 static int setGlWindow_sdl(MPGLContext
*ctx
)
2004 if (sdl_set_mode(0, SDL_OPENGL
| SDL_RESIZABLE
) < 0)
2005 return SET_WINDOW_FAILED
;
2006 SDL_GL_LoadLibrary(NULL
);
2007 getFunctions(ctx
->gl
, sdlgpa
, NULL
);
2008 return SET_WINDOW_OK
;
2011 static void releaseGlContext_sdl(MPGLContext
*ctx
)
2015 static int sdl_check_events(struct vo
*vo
)
2019 while (SDL_PollEvent(&event
))
2020 res
|= sdl_default_handle_event(&event
);
2021 // poll "events" from within MPlayer code
2022 res
|= sdl_default_handle_event(NULL
);
2023 if (res
& VO_EVENT_RESIZE
)
2024 sdl_set_mode(0, SDL_OPENGL
| SDL_RESIZABLE
);
2028 static void new_sdl_update_xinerama_info(struct vo
*vo
) { sdl_update_xinerama_info(); }
2029 static void new_vo_sdl_fullscreen(struct vo
*vo
) { vo_sdl_fullscreen(); }
2033 MPGLContext
*init_mpglcontext(enum MPGLType type
, struct vo
*vo
)
2036 if (type
== GLTYPE_AUTO
) {
2037 ctx
= init_mpglcontext(GLTYPE_W32
, vo
);
2040 ctx
= init_mpglcontext(GLTYPE_X11
, vo
);
2043 return init_mpglcontext(GLTYPE_SDL
, vo
);
2045 ctx
= talloc_zero(NULL
, MPGLContext
);
2046 ctx
->gl
= talloc_zero(ctx
, GL
);
2049 switch (ctx
->type
) {
2050 #ifdef CONFIG_GL_WIN32
2052 ctx
->create_window
= create_window_w32
;
2053 ctx
->setGlWindow
= setGlWindow_w32
;
2054 ctx
->releaseGlContext
= releaseGlContext_w32
;
2055 ctx
->swapGlBuffers
= swapGlBuffers_w32
;
2056 ctx
->update_xinerama_info
= new_w32_update_xinerama_info
;
2057 ctx
->border
= new_vo_w32_border
;
2058 ctx
->check_events
= new_vo_w32_check_events
;
2059 ctx
->fullscreen
= new_vo_w32_fullscreen
;
2060 ctx
->ontop
= new_vo_w32_ontop
;
2061 //the win32 code is hardcoded to use the deprecated vo API
2067 #ifdef CONFIG_GL_X11
2069 ctx
->create_window
= create_window_x11
;
2070 ctx
->setGlWindow
= setGlWindow_x11
;
2071 ctx
->releaseGlContext
= releaseGlContext_x11
;
2072 ctx
->swapGlBuffers
= swapGlBuffers_x11
;
2073 ctx
->update_xinerama_info
= update_xinerama_info
;
2074 ctx
->border
= vo_x11_border
;
2075 ctx
->check_events
= vo_x11_check_events
;
2076 ctx
->fullscreen
= vo_x11_fullscreen
;
2077 ctx
->ontop
= vo_x11_ontop
;
2082 #ifdef CONFIG_GL_SDL
2084 ctx
->create_window
= create_window_sdl
;
2085 ctx
->setGlWindow
= setGlWindow_sdl
;
2086 ctx
->releaseGlContext
= releaseGlContext_sdl
;
2087 ctx
->swapGlBuffers
= swapGlBuffers_sdl
;
2088 ctx
->update_xinerama_info
= new_sdl_update_xinerama_info
;
2089 ctx
->check_events
= sdl_check_events
;
2090 ctx
->fullscreen
= new_vo_sdl_fullscreen
;
2091 //the SDL code is hardcoded to use the deprecated vo API
2102 void uninit_mpglcontext(MPGLContext
*ctx
)
2106 ctx
->releaseGlContext(ctx
);
2107 switch (ctx
->type
) {
2108 #ifdef CONFIG_GL_WIN32
2113 #ifdef CONFIG_GL_X11
2115 vo_x11_uninit(ctx
->vo
);
2118 #ifdef CONFIG_GL_SDL