diff options
author | wm4 <wm4@nowhere> | 2012-11-05 17:02:04 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2012-11-12 20:06:14 +0100 |
commit | d4bdd0473d6f43132257c9fb3848d829755167a3 (patch) | |
tree | 8021c2f7da1841393c8c832105e20cd527826d6c /libvo/gl_common.c | |
parent | bd48deba77bd5582c5829d6fe73a7d2571088aba (diff) | |
download | mpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.bz2 mpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.xz |
Rename directories, move files (step 1 of 2) (does not compile)
Tis drops the silly lib prefixes, and attempts to organize the tree in
a more logical way. Make the top-level directory less cluttered as
well.
Renames the following directories:
libaf -> audio/filter
libao2 -> audio/out
libvo -> video/out
libmpdemux -> demux
Split libmpcodecs:
vf* -> video/filter
vd*, dec_video.* -> video/decode
mp_image*, img_format*, ... -> video/
ad*, dec_audio.* -> audio/decode
libaf/format.* is moved to audio/ - this is similar to how mp_image.*
is located in video/.
Move most top-level .c/.h files to core. (talloc.c/.h is left on top-
level, because it's external.) Park some of the more annoying files
in compat/. Some of these are relicts from the time mplayer used
ffmpeg internals.
sub/ is not split, because it's too much of a mess (subtitle code is
mixed with OSD display and rendering).
Maybe the organization of core is not ideal: it mixes playback core
(like mplayer.c) and utility helpers (like bstr.c/h). Should the need
arise, the playback core will be moved somewhere else, while core
contains all helper and common code.
Diffstat (limited to 'libvo/gl_common.c')
-rw-r--r-- | libvo/gl_common.c | 2654 |
1 files changed, 0 insertions, 2654 deletions
diff --git a/libvo/gl_common.c b/libvo/gl_common.c deleted file mode 100644 index 80db2eacc4..0000000000 --- a/libvo/gl_common.c +++ /dev/null @@ -1,2654 +0,0 @@ -/* - * common OpenGL routines - * - * copyleft (C) 2005-2010 Reimar Döffinger <Reimar.Doeffinger@gmx.de> - * Special thanks go to the xine team and Matthias Hopf, whose video_out_opengl.c - * gave me lots of good ideas. - * - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * You can alternatively redistribute this file and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - */ - -/** - * \file gl_common.c - * \brief OpenGL helper functions used by vo_gl.c and vo_gl2.c - */ - -#include <stddef.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <stdbool.h> -#include <math.h> -#include <assert.h> -#include "talloc.h" -#include "gl_common.h" -#include "csputils.h" -#include "aspect.h" -#include "pnm_loader.h" -#include "options.h" -#include "sub/sub.h" -#include "bitmap_packer.h" - -//! \defgroup glgeneral OpenGL general helper functions - -// GLU has this as gluErrorString (we don't use GLU, as it is legacy-OpenGL) -static const char *gl_error_to_string(GLenum error) -{ - switch (error) { - case GL_INVALID_ENUM: return "INVALID_ENUM"; - case GL_INVALID_VALUE: return "INVALID_VALUE"; - case GL_INVALID_OPERATION: return "INVALID_OPERATION"; - case GL_INVALID_FRAMEBUFFER_OPERATION: - return "INVALID_FRAMEBUFFER_OPERATION"; - case GL_OUT_OF_MEMORY: return "OUT_OF_MEMORY"; - default: return "unknown"; - } -} - -void glCheckError(GL *gl, const char *info) -{ - for (;;) { - GLenum error = gl->GetError(); - if (error == GL_NO_ERROR) - break; - mp_msg(MSGT_VO, MSGL_ERR, "[gl] %s: OpenGL error %s.\n", info, - gl_error_to_string(error)); - } -} - -//! \defgroup glcontext OpenGL context management helper functions - -//! \defgroup gltexture OpenGL texture handling helper functions - -//! \defgroup glconversion OpenGL conversion helper functions - -/** - * \brief adjusts the GL_UNPACK_ALIGNMENT to fit the stride. - * \param stride number of bytes per line for which alignment should fit. - * \ingroup glgeneral - */ -void glAdjustAlignment(GL *gl, int stride) -{ - GLint gl_alignment; - if (stride % 8 == 0) - gl_alignment = 8; - else if (stride % 4 == 0) - gl_alignment = 4; - else if (stride % 2 == 0) - gl_alignment = 2; - else - gl_alignment = 1; - gl->PixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment); - gl->PixelStorei(GL_PACK_ALIGNMENT, gl_alignment); -} - -//! always return this format as internal texture format in glFindFormat -#define TEXTUREFORMAT_ALWAYS GL_RGB8 -#undef TEXTUREFORMAT_ALWAYS - -/** - * \brief find the OpenGL settings coresponding to format. - * - * All parameters may be NULL. - * \param fmt MPlayer format to analyze. - * \param bpp [OUT] bits per pixel of that format. - * \param gl_texfmt [OUT] internal texture format that fits the - * image format, not necessarily the best for performance. - * \param gl_format [OUT] OpenGL format for this image format. - * \param gl_type [OUT] OpenGL type for this image format. - * \return 1 if format is supported by OpenGL, 0 if not. - * \ingroup gltexture - */ -int glFindFormat(uint32_t fmt, int have_texture_rg, int *bpp, GLint *gl_texfmt, - GLenum *gl_format, GLenum *gl_type) -{ - int supported = 1; - int dummy1; - GLenum dummy2; - GLint dummy3; - if (!bpp) - bpp = &dummy1; - if (!gl_texfmt) - gl_texfmt = &dummy3; - if (!gl_format) - gl_format = &dummy2; - if (!gl_type) - gl_type = &dummy2; - - if (mp_get_chroma_shift(fmt, NULL, NULL, NULL)) { - // reduce the possible cases a bit - if (IMGFMT_IS_YUVP16_LE(fmt)) - fmt = IMGFMT_420P16_LE; - else if (IMGFMT_IS_YUVP16_BE(fmt)) - fmt = IMGFMT_420P16_BE; - else - fmt = IMGFMT_YV12; - } - - *bpp = IMGFMT_IS_BGR(fmt) ? IMGFMT_BGR_DEPTH(fmt) : IMGFMT_RGB_DEPTH(fmt); - *gl_texfmt = 3; - switch (fmt) { - case IMGFMT_RGB48NE: - *gl_format = GL_RGB; - *gl_type = GL_UNSIGNED_SHORT; - break; - case IMGFMT_RGB24: - *gl_format = GL_RGB; - *gl_type = GL_UNSIGNED_BYTE; - break; - case IMGFMT_RGBA: - *gl_texfmt = 4; - *gl_format = GL_RGBA; - *gl_type = GL_UNSIGNED_BYTE; - break; - case IMGFMT_420P16: - supported = 0; // no native YUV support - *gl_texfmt = have_texture_rg ? GL_R16 : GL_LUMINANCE16; - *bpp = 16; - *gl_format = have_texture_rg ? GL_RED : GL_LUMINANCE; - *gl_type = GL_UNSIGNED_SHORT; - break; - case IMGFMT_YV12: - supported = 0; // no native YV12 support - case IMGFMT_Y800: - case IMGFMT_Y8: - *gl_texfmt = 1; - *bpp = 8; - *gl_format = GL_LUMINANCE; - *gl_type = GL_UNSIGNED_BYTE; - break; - case IMGFMT_UYVY: - // IMGFMT_YUY2 would be more logical for the _REV format, - // but gives clearly swapped colors. - case IMGFMT_YVYU: - *gl_texfmt = GL_YCBCR_MESA; - *bpp = 16; - *gl_format = GL_YCBCR_MESA; - *gl_type = fmt == IMGFMT_UYVY ? GL_UNSIGNED_SHORT_8_8 : GL_UNSIGNED_SHORT_8_8_REV; - break; -#if 0 - // we do not support palettized formats, although the format the - // swscale produces works - case IMGFMT_RGB8: - *gl_format = GL_RGB; - *gl_type = GL_UNSIGNED_BYTE_2_3_3_REV; - break; -#endif - case IMGFMT_RGB15: - *gl_format = GL_RGBA; - *gl_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - break; - case IMGFMT_RGB16: - *gl_format = GL_RGB; - *gl_type = GL_UNSIGNED_SHORT_5_6_5_REV; - break; -#if 0 - case IMGFMT_BGR8: - // special case as red and blue have a different number of bits. - // GL_BGR and GL_UNSIGNED_BYTE_3_3_2 isn't supported at least - // by nVidia drivers, and in addition would give more bits to - // blue than to red, which isn't wanted - *gl_format = GL_RGB; - *gl_type = GL_UNSIGNED_BYTE_3_3_2; - break; -#endif - case IMGFMT_BGR15: - *gl_format = GL_BGRA; - *gl_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - break; - case IMGFMT_BGR16: - *gl_format = GL_RGB; - *gl_type = GL_UNSIGNED_SHORT_5_6_5; - break; - case IMGFMT_BGR24: - *gl_format = GL_BGR; - *gl_type = GL_UNSIGNED_BYTE; - break; - case IMGFMT_BGRA: - *gl_texfmt = 4; - *gl_format = GL_BGRA; - *gl_type = GL_UNSIGNED_BYTE; - break; - default: - *gl_texfmt = 4; - *gl_format = GL_RGBA; - *gl_type = GL_UNSIGNED_BYTE; - supported = 0; - } -#ifdef TEXTUREFORMAT_ALWAYS - *gl_texfmt = TEXTUREFORMAT_ALWAYS; -#endif - return supported; -} - -struct feature { - int id; - const char *name; -}; - -static const struct feature features[] = { - {MPGL_CAP_GL, "Basic OpenGL"}, - {MPGL_CAP_GL_LEGACY, "Legacy OpenGL"}, - {MPGL_CAP_GL2, "OpenGL 2.0"}, - {MPGL_CAP_GL21, "OpenGL 2.1"}, - {MPGL_CAP_GL3, "OpenGL 3.0"}, - {MPGL_CAP_FB, "Framebuffers"}, - {MPGL_CAP_VAO, "VAOs"}, - {MPGL_CAP_SRGB_TEX, "sRGB textures"}, - {MPGL_CAP_SRGB_FB, "sRGB framebuffers"}, - {MPGL_CAP_FLOAT_TEX, "Float textures"}, - {MPGL_CAP_TEX_RG, "RG textures"}, - {MPGL_CAP_NO_SW, "NO_SW"}, - {0}, -}; - -static void list_features(int set, int msgl, bool invert) -{ - for (const struct feature *f = &features[0]; f->id; f++) { - if (invert == !(f->id & set)) - mp_msg(MSGT_VO, msgl, " [%s]", f->name); - } - mp_msg(MSGT_VO, msgl, "\n"); -} - -// This guesses if the current GL context is a suspected software renderer. -static bool is_software_gl(GL *gl) -{ - const char *renderer = gl->GetString(GL_RENDERER); - const char *vendor = gl->GetString(GL_VENDOR); - return !(renderer && vendor) || - strcmp(renderer, "Software Rasterizer") == 0 || - strstr(renderer, "llvmpipe") || - strcmp(vendor, "Microsoft Corporation") == 0 || - strcmp(renderer, "Mesa X11") == 0; -} - -#ifdef HAVE_LIBDL -#include <dlfcn.h> -#endif -/** - * \brief find address of a linked function - * \param s name of function to find - * \return address of function or NULL if not found - */ -static void *getdladdr(const char *s) -{ - void *ret = NULL; -#ifdef HAVE_LIBDL - void *handle = dlopen(NULL, RTLD_LAZY); - if (!handle) - return NULL; - ret = dlsym(handle, s); - dlclose(handle); -#endif - return ret; -} - -#define FN_OFFS(name) offsetof(GL, name) - -// Define the function with a "hard" reference to the function as fallback. -// (This requires linking with a compatible OpenGL library.) -#define DEF_FN_HARD(name) {FN_OFFS(name), {"gl" # name}, gl ## name} - -#define DEF_FN(name) {FN_OFFS(name), {"gl" # name}} -#define DEF_FN_NAMES(name, ...) {FN_OFFS(name), {__VA_ARGS__}} - -struct gl_function { - ptrdiff_t offset; - char *funcnames[7]; - void *fallback; -}; - -struct gl_functions { - const char *extension; // introduced with this extension in any version - int provides; // bitfield of MPGL_CAP_* constants - int ver_core; // introduced as required function - int ver_removed; // removed as required function (no replacement) - bool partial_ok; // loading only some functions is ok - struct gl_function *functions; -}; - -#define MAX_FN_COUNT 50 // max functions per gl_functions section - -struct gl_functions gl_functions[] = { - // GL functions which are always available anywhere at least since 1.1 - { - .ver_core = MPGL_VER(1, 1), - .provides = MPGL_CAP_GL, - .functions = (struct gl_function[]) { - DEF_FN_HARD(Viewport), - DEF_FN_HARD(Clear), - DEF_FN_HARD(GenTextures), - DEF_FN_HARD(DeleteTextures), - DEF_FN_HARD(TexEnvi), - DEF_FN_HARD(ClearColor), - DEF_FN_HARD(Enable), - DEF_FN_HARD(Disable), - DEF_FN_HARD(DrawBuffer), - DEF_FN_HARD(DepthMask), - DEF_FN_HARD(BlendFunc), - DEF_FN_HARD(Flush), - DEF_FN_HARD(Finish), - DEF_FN_HARD(PixelStorei), - DEF_FN_HARD(TexImage1D), - DEF_FN_HARD(TexImage2D), - DEF_FN_HARD(TexSubImage2D), - DEF_FN_HARD(GetTexImage), - DEF_FN_HARD(TexParameteri), - DEF_FN_HARD(TexParameterf), - DEF_FN_HARD(TexParameterfv), - DEF_FN_HARD(GetIntegerv), - DEF_FN_HARD(GetBooleanv), - DEF_FN_HARD(ColorMask), - DEF_FN_HARD(ReadPixels), - DEF_FN_HARD(ReadBuffer), - DEF_FN_HARD(DrawArrays), - DEF_FN_HARD(GetString), - DEF_FN_HARD(GetError), - {0} - }, - }, - // GL 2.0-3.x functions - { - .ver_core = MPGL_VER(2, 0), - .provides = MPGL_CAP_GL2, - .functions = (struct gl_function[]) { - DEF_FN(GenBuffers), - DEF_FN(DeleteBuffers), - DEF_FN(BindBuffer), - DEF_FN(MapBuffer), - DEF_FN(UnmapBuffer), - DEF_FN(BufferData), - DEF_FN(ActiveTexture), - DEF_FN(BindTexture), - DEF_FN(GetAttribLocation), - DEF_FN(EnableVertexAttribArray), - DEF_FN(DisableVertexAttribArray), - DEF_FN(VertexAttribPointer), - DEF_FN(UseProgram), - DEF_FN(GetUniformLocation), - DEF_FN(CompileShader), - DEF_FN(CreateProgram), - DEF_FN(CreateShader), - DEF_FN(ShaderSource), - DEF_FN(LinkProgram), - DEF_FN(AttachShader), - DEF_FN(DeleteShader), - DEF_FN(DeleteProgram), - DEF_FN(GetShaderInfoLog), - DEF_FN(GetShaderiv), - DEF_FN(GetProgramInfoLog), - DEF_FN(GetProgramiv), - DEF_FN(BindAttribLocation), - DEF_FN(Uniform1f), - DEF_FN(Uniform2f), - DEF_FN(Uniform3f), - DEF_FN(Uniform1i), - DEF_FN(UniformMatrix3fv), - DEF_FN(TexImage3D), - {0}, - }, - }, - // GL 2.1-3.x functions (also: GLSL 120 shaders) - { - .ver_core = MPGL_VER(2, 1), - .provides = MPGL_CAP_GL21, - .functions = (struct gl_function[]) { - DEF_FN(UniformMatrix4x3fv), - {0} - }, - }, - // GL 3.x core only functions. - { - .ver_core = MPGL_VER(3, 0), - .provides = MPGL_CAP_GL3 | MPGL_CAP_SRGB_TEX | MPGL_CAP_SRGB_FB, - .functions = (struct gl_function[]) { - DEF_FN(GetStringi), - {0} - }, - }, - // Framebuffers, extension in GL 2.x, core in GL 3.x core. - { - .ver_core = MPGL_VER(3, 0), - .extension = "GL_ARB_framebuffer_object", - .provides = MPGL_CAP_FB, - .functions = (struct gl_function[]) { - DEF_FN(BindFramebuffer), - DEF_FN(GenFramebuffers), - DEF_FN(DeleteFramebuffers), - DEF_FN(CheckFramebufferStatus), - DEF_FN(FramebufferTexture2D), - {0} - }, - }, - // Framebuffers, alternative extension name. - { - .ver_removed = MPGL_VER(3, 0), // don't touch these fn names in 3.x - .extension = "GL_EXT_framebuffer_object", - .provides = MPGL_CAP_FB, - .functions = (struct gl_function[]) { - DEF_FN_NAMES(BindFramebuffer, "glBindFramebufferEXT"), - DEF_FN_NAMES(GenFramebuffers, "glGenFramebuffersEXT"), - DEF_FN_NAMES(DeleteFramebuffers, "glDeleteFramebuffersEXT"), - DEF_FN_NAMES(CheckFramebufferStatus, "glCheckFramebufferStatusEXT"), - DEF_FN_NAMES(FramebufferTexture2D, "glFramebufferTexture2DEXT"), - {0} - }, - }, - // VAOs, extension in GL 2.x, core in GL 3.x core. - { - .ver_core = MPGL_VER(3, 0), - .extension = "GL_ARB_vertex_array_object", - .provides = MPGL_CAP_VAO, - .functions = (struct gl_function[]) { - DEF_FN(GenVertexArrays), - DEF_FN(BindVertexArray), - DEF_FN(DeleteVertexArrays), - {0} - } - }, - // sRGB textures, extension in GL 2.x, core in GL 3.x core. - { - .ver_core = MPGL_VER(3, 0), - .extension = "GL_EXT_texture_sRGB", - .provides = MPGL_CAP_SRGB_TEX, - .functions = (struct gl_function[]) {{0}}, - }, - // sRGB framebuffers, extension in GL 2.x, core in GL 3.x core. - { - .ver_core = MPGL_VER(3, 0), - .extension = "GL_EXT_framebuffer_sRGB", - .provides = MPGL_CAP_SRGB_FB, - .functions = (struct gl_function[]) {{0}}, - }, - // Float textures, extension in GL 2.x, core in GL 3.x core. - { - .ver_core = MPGL_VER(3, 0), - .extension = "GL_ARB_texture_float", - .provides = MPGL_CAP_FLOAT_TEX, - .functions = (struct gl_function[]) {{0}}, - }, - // GL_RED / GL_RG textures, extension in GL 2.x, core in GL 3.x core. - { - .ver_core = MPGL_VER(3, 0), - .extension = "GL_ARB_texture_rg", - .provides = MPGL_CAP_TEX_RG, - .functions = (struct gl_function[]) {{0}}, - }, - // Swap control, always an OS specific extension - { - .extension = "_swap_control", - .functions = (struct gl_function[]) { - DEF_FN_NAMES(SwapInterval, "glXSwapIntervalSGI", "glXSwapInterval", - "wglSwapIntervalSGI", "wglSwapInterval", - "wglSwapIntervalEXT"), - {0} - }, - }, - // GL legacy functions in GL 1.x - 2.x, removed from GL 3.x - { - .ver_core = MPGL_VER(1, 1), - .ver_removed = MPGL_VER(3, 0), - .provides = MPGL_CAP_GL_LEGACY, - .functions = (struct gl_function[]) { - DEF_FN_HARD(Begin), - DEF_FN_HARD(End), - DEF_FN_HARD(MatrixMode), - DEF_FN_HARD(LoadIdentity), - DEF_FN_HARD(Translated), - DEF_FN_HARD(Scaled), - DEF_FN_HARD(Ortho), - DEF_FN_HARD(PushMatrix), - DEF_FN_HARD(PopMatrix), - DEF_FN_HARD(GenLists), - DEF_FN_HARD(DeleteLists), - DEF_FN_HARD(NewList), - DEF_FN_HARD(EndList), - DEF_FN_HARD(CallList), - DEF_FN_HARD(CallLists), - DEF_FN_HARD(Color4ub), - DEF_FN_HARD(Color4f), - DEF_FN_HARD(TexCoord2f), - DEF_FN_HARD(TexCoord2fv), - DEF_FN_HARD(Vertex2f), - DEF_FN_HARD(VertexPointer), - DEF_FN_HARD(ColorPointer), - DEF_FN_HARD(TexCoordPointer), - DEF_FN_HARD(EnableClientState), - DEF_FN_HARD(DisableClientState), - {0} - }, - }, - // Loading of old extensions, which are later added to GL 2.0. - // NOTE: actually we should be checking the extension strings: the OpenGL - // library could provide an entry point, but not implement it. - // But the previous code didn't do that, and nobody ever complained. - { - .ver_removed = MPGL_VER(2, 1), - .partial_ok = true, - .functions = (struct gl_function[]) { - DEF_FN_NAMES(GenBuffers, "glGenBuffers", "glGenBuffersARB"), - DEF_FN_NAMES(DeleteBuffers, "glDeleteBuffers", "glDeleteBuffersARB"), - DEF_FN_NAMES(BindBuffer, "glBindBuffer", "glBindBufferARB"), - DEF_FN_NAMES(MapBuffer, "glMapBuffer", "glMapBufferARB"), - DEF_FN_NAMES(UnmapBuffer, "glUnmapBuffer", "glUnmapBufferARB"), - DEF_FN_NAMES(BufferData, "glBufferData", "glBufferDataARB"), - DEF_FN_NAMES(ActiveTexture, "glActiveTexture", "glActiveTextureARB"), - DEF_FN_NAMES(BindTexture, "glBindTexture", "glBindTextureARB", "glBindTextureEXT"), - DEF_FN_NAMES(MultiTexCoord2f, "glMultiTexCoord2f", "glMultiTexCoord2fARB"), - DEF_FN_NAMES(TexImage3D, "glTexImage3D"), - {0} - }, - }, - // Ancient ARB shaders. - { - .extension = "_program", - .ver_removed = MPGL_VER(3, 0), - .functions = (struct gl_function[]) { - DEF_FN_NAMES(GenPrograms, "glGenProgramsARB"), - DEF_FN_NAMES(DeletePrograms, "glDeleteProgramsARB"), - DEF_FN_NAMES(BindProgram, "glBindProgramARB"), - DEF_FN_NAMES(ProgramString, "glProgramStringARB"), - DEF_FN_NAMES(GetProgramivARB, "glGetProgramivARB"), - DEF_FN_NAMES(ProgramEnvParameter4f, "glProgramEnvParameter4fARB"), - {0} - }, - }, - // Ancient ATI extensions. - { - .extension = "ATI_fragment_shader", - .ver_removed = MPGL_VER(3, 0), - .functions = (struct gl_function[]) { - DEF_FN_NAMES(BeginFragmentShader, "glBeginFragmentShaderATI"), - DEF_FN_NAMES(EndFragmentShader, "glEndFragmentShaderATI"), - DEF_FN_NAMES(SampleMap, "glSampleMapATI"), - DEF_FN_NAMES(ColorFragmentOp2, "glColorFragmentOp2ATI"), - DEF_FN_NAMES(ColorFragmentOp3, "glColorFragmentOp3ATI"), - DEF_FN_NAMES(SetFragmentShaderConstant, "glSetFragmentShaderConstantATI"), - {0} - }, - }, -}; - -#undef FN_OFFS -#undef DEF_FN_HARD -#undef DEF_FN -#undef DEF_FN_NAMES - - -/** - * \brief find the function pointers of some useful OpenGL extensions - * \param getProcAddress function to resolve function names, may be NULL - * \param ext2 an extra extension string - */ -static void getFunctions(GL *gl, void *(*getProcAddress)(const GLubyte *), - const char *ext2, bool gl3) -{ - talloc_free_children(gl); - *gl = (GL) { - .extensions = talloc_strdup(gl, ext2 ? ext2 : ""), - }; - - if (!getProcAddress) - getProcAddress = (void *)getdladdr; - - GLint major = 0, minor = 0; - if (gl3) { - gl->GetStringi = getProcAddress("glGetStringi"); - gl->GetIntegerv = getProcAddress("glGetIntegerv"); - - if (!(gl->GetStringi && gl->GetIntegerv)) - return; - - gl->GetIntegerv(GL_MAJOR_VERSION, &major); - gl->GetIntegerv(GL_MINOR_VERSION, &minor); - - GLint exts; - gl->GetIntegerv(GL_NUM_EXTENSIONS, &exts); - for (int n = 0; n < exts; n++) { - gl->extensions - = talloc_asprintf_append(gl->extensions, " %s", - gl->GetStringi(GL_EXTENSIONS, n)); - } - } else { - gl->GetString = getProcAddress("glGetString"); - if (!gl->GetString) - gl->GetString = glGetString; - - const char *ext = (char*)gl->GetString(GL_EXTENSIONS); - gl->extensions = talloc_asprintf_append(gl->extensions, " %s", ext); - - const char *version = gl->GetString(GL_VERSION); - sscanf(version, "%d.%d", &major, &minor); - } - gl->version = MPGL_VER(major, minor); - - mp_msg(MSGT_VO, MSGL_V, "[gl] Detected OpenGL %d.%d.\n", major, minor); - mp_msg(MSGT_VO, MSGL_DBG2, "[gl] Combined OpenGL extensions string:\n%s\n", - gl->extensions); - - for (int n = 0; n < sizeof(gl_functions) / sizeof(gl_functions[0]); n++) { - struct gl_functions *section = &gl_functions[n]; - - // With gl3=false, we could have a legacy context, where functionality - // is never removed. (E.g. the context could be at version >= 3.0, but - // legacy functions like glBegin still exist and work.) - if (gl3 && section->ver_removed && gl->version >= section->ver_removed) - continue; - - bool must_exist = section->ver_core && gl->version >= section->ver_core - && !section->partial_ok; - - if (!must_exist && section->extension && - !strstr(gl->extensions, section->extension)) - continue; - - void *loaded[MAX_FN_COUNT] = {0}; - bool all_loaded = true; - - for (int i = 0; section->functions[i].funcnames[0]; i++) { - struct gl_function *fn = §ion->functions[i]; - void *ptr = NULL; - for (int x = 0; fn->funcnames[x]; x++) { - ptr = getProcAddress((const GLubyte *)fn->funcnames[x]); - if (ptr) - break; - } - if (!ptr) - ptr = fn->fallback; - if (!ptr) { - all_loaded = false; - if (must_exist) { - // Either we or the driver are not conforming to OpenGL. - mp_msg(MSGT_VO, MSGL_ERR, "[gl] Required function '%s' not " - "found.\n", fn->funcnames[0]); - talloc_free_children(gl); - *gl = (GL) {0}; - return; - } - } - assert(i < MAX_FN_COUNT); - loaded[i] = ptr; - } - - if (all_loaded || section->partial_ok) { - gl->mpgl_caps |= section->provides; - for (int i = 0; section->functions[i].funcnames[0]; i++) { - struct gl_function *fn = §ion->functions[i]; - void **funcptr = (void**)(((char*)gl) + fn->offset); - if (loaded[i]) - *funcptr = loaded[i]; - } - } - } - - gl->glsl_version = 0; - if (gl->version >= MPGL_VER(2, 0)) - gl->glsl_version = 110; - if (gl->version >= MPGL_VER(2, 1)) - gl->glsl_version = 120; - if (gl->version >= MPGL_VER(3, 0)) - gl->glsl_version = 130; - // Specifically needed for OSX (normally we request 3.0 contexts only, but - // OSX always creates 3.2 contexts when requesting a core context). - if (gl->version >= MPGL_VER(3, 2)) - gl->glsl_version = 150; - - if (!is_software_gl(gl)) - gl->mpgl_caps |= MPGL_CAP_NO_SW; - - mp_msg(MSGT_VO, MSGL_V, "[gl] Detected OpenGL features:"); - list_features(gl->mpgl_caps, MSGL_V, false); -} - -/** - * \brief create a texture and set some defaults - * \param target texture taget, usually GL_TEXTURE_2D - * \param fmt internal texture format - * \param format texture host data format - * \param type texture host data type - * \param filter filter used for scaling, e.g. GL_LINEAR - * \param w texture width - * \param h texture height - * \param val luminance value to fill texture with - * \ingroup gltexture - */ -void glCreateClearTex(GL *gl, GLenum target, GLenum fmt, GLenum format, - GLenum type, GLint filter, int w, int h, - unsigned char val) -{ - GLfloat fval = (GLfloat)val / 255.0; - GLfloat border[4] = { - fval, fval, fval, fval - }; - int stride; - char *init; - if (w == 0) - w = 1; - if (h == 0) - h = 1; - stride = w * glFmt2bpp(format, type); - if (!stride) - return; - init = malloc(stride * h); - memset(init, val, stride * h); - glAdjustAlignment(gl, stride); - gl->PixelStorei(GL_UNPACK_ROW_LENGTH, w); - gl->TexImage2D(target, 0, fmt, w, h, 0, format, type, init); - gl->TexParameterf(target, GL_TEXTURE_PRIORITY, 1.0); - gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, filter); - gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter); - gl->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // Border texels should not be used with CLAMP_TO_EDGE - // We set a sane default anyway. - gl->TexParameterfv(target, GL_TEXTURE_BORDER_COLOR, border); - free(init); -} - -static GLint detect_hqtexfmt(GL *gl) -{ - const char *extensions = (const char *)gl->GetString(GL_EXTENSIONS); - if (strstr(extensions, "_texture_float")) - return GL_RGB32F; - else if (strstr(extensions, "NV_float_buffer")) - return GL_FLOAT_RGB32_NV; - return GL_RGB16; -} - -/** - * \brief creates a texture from a PPM file - * \param target texture taget, usually GL_TEXTURE_2D - * \param fmt internal texture format, 0 for default - * \param filter filter used for scaling, e.g. GL_LINEAR - * \param f file to read PPM from - * \param width [out] width of texture - * \param height [out] height of texture - * \param maxval [out] maxval value from PPM file - * \return 0 on error, 1 otherwise - * \ingroup gltexture - */ -int glCreatePPMTex(GL *gl, GLenum target, GLenum fmt, GLint filter, - FILE *f, int *width, int *height, int *maxval) -{ - int w, h, m, bpp; - GLenum type; - uint8_t *data = read_pnm(f, &w, &h, &bpp, &m); - GLint hqtexfmt = detect_hqtexfmt(gl); - if (!data || (bpp != 3 && bpp != 6)) { - free(data); - return 0; - } - if (!fmt) { - fmt = bpp == 6 ? hqtexfmt : 3; - if (fmt == GL_FLOAT_RGB32_NV && target != GL_TEXTURE_RECTANGLE) - fmt = GL_RGB16; - } - type = bpp == 6 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE; - glCreateClearTex(gl, target, fmt, GL_RGB, type, filter, w, h, 0); - glUploadTex(gl, target, GL_RGB, type, - data, w * bpp, 0, 0, w, h, 0); - free(data); - if (width) - *width = w; - if (height) - *height = h; - if (maxval) - *maxval = m; - return 1; -} - -/** - * \brief return the number of bytes per pixel for the given format - * \param format OpenGL format - * \param type OpenGL type - * \return bytes per pixel - * \ingroup glgeneral - * - * Does not handle all possible variants, just those used by MPlayer - */ -int glFmt2bpp(GLenum format, GLenum type) -{ - int component_size = 0; - switch (type) { - case GL_UNSIGNED_BYTE_3_3_2: - case GL_UNSIGNED_BYTE_2_3_3_REV: - return 1; - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_UNSIGNED_SHORT_1_5_5_5_REV: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_5_6_5_REV: - return 2; - case GL_UNSIGNED_BYTE: - component_size = 1; - break; - case GL_UNSIGNED_SHORT: - component_size = 2; - break; - } - switch (format) { - case GL_LUMINANCE: - case GL_ALPHA: - return component_size; - case GL_YCBCR_MESA: - return 2; - case GL_RGB: - case GL_BGR: - return 3 * component_size; - case GL_RGBA: - case GL_BGRA: - return 4 * component_size; - case GL_RED: - return component_size; - case GL_RG: - case GL_LUMINANCE_ALPHA: - return 2 * component_size; - } - abort(); // unknown -} - -/** - * \brief upload a texture, handling things like stride and slices - * \param target texture target, usually GL_TEXTURE_2D - * \param format OpenGL format of data - * \param type OpenGL type of data - * \param dataptr data to upload - * \param stride data stride - * \param x x offset in texture - * \param y y offset in texture - * \param w width of the texture part to upload - * \param h height of the texture part to upload - * \param slice height of an upload slice, 0 for all at once - * \ingroup gltexture - */ -void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type, - const void *dataptr, int stride, - int x, int y, int w, int h, int slice) -{ - const uint8_t *data = dataptr; - int y_max = y + h; - if (w <= 0 || h <= 0) - return; - if (slice <= 0) - slice = h; - if (stride < 0) { - data += (h - 1) * stride; - stride = -stride; - } - // this is not always correct, but should work for MPlayer - glAdjustAlignment(gl, stride); - gl->PixelStorei(GL_UNPACK_ROW_LENGTH, stride / glFmt2bpp(format, type)); - for (; y + slice <= y_max; y += slice) { - gl->TexSubImage2D(target, 0, x, y, w, slice, format, type, data); - data += stride * slice; - } - if (y < y_max) - gl->TexSubImage2D(target, 0, x, y, w, y_max - y, format, type, data); -} - -// Like glUploadTex, but upload a byte array with all elements set to val. -// If scratch is not NULL, points to a resizeable talloc memory block than can -// be freely used by the function (for avoiding temporary memory allocations). -void glClearTex(GL *gl, GLenum target, GLenum format, GLenum type, - int x, int y, int w, int h, uint8_t val, void **scratch) -{ - int bpp = glFmt2bpp(format, type); - int stride = w * bpp; - int size = h * stride; - if (size < 1) - return; - void *data = scratch ? *scratch : NULL; - if (talloc_get_size(data) < size) - data = talloc_realloc(NULL, data, char *, size); - memset(data, val, size); - glAdjustAlignment(gl, stride); - gl->PixelStorei(GL_UNPACK_ROW_LENGTH, w); - gl->TexSubImage2D(target, 0, x, y, w, h, format, type, data); - if (scratch) { - *scratch = data; - } else { - talloc_free(data); - } -} - -/** - * \brief download a texture, handling things like stride and slices - * \param target texture target, usually GL_TEXTURE_2D - * \param format OpenGL format of data - * \param type OpenGL type of data - * \param dataptr destination memory for download - * \param stride data stride (must be positive) - * \ingroup gltexture - */ -void glDownloadTex(GL *gl, GLenum target, GLenum format, GLenum type, - void *dataptr, int stride) -{ - // this is not always correct, but should work for MPlayer - glAdjustAlignment(gl, stride); - gl->PixelStorei(GL_PACK_ROW_LENGTH, stride / glFmt2bpp(format, type)); - gl->GetTexImage(target, 0, format, type, dataptr); -} - -/** - * \brief Setup ATI version of register combiners for YUV to RGB conversion. - * \param csp_params parameters used for colorspace conversion - * \param text if set use the GL_ATI_text_fragment_shader API as - * used on OS X. - */ -static void glSetupYUVFragmentATI(GL *gl, struct mp_csp_params *csp_params, - int text) -{ - GLint i; - float yuv2rgb[3][4]; - - gl->GetIntegerv(GL_MAX_TEXTURE_UNITS, &i); - if (i < 3) - mp_msg(MSGT_VO, MSGL_ERR, - "[gl] 3 texture units needed for YUV combiner (ATI) support (found %i)\n", i); - - mp_get_yuv2rgb_coeffs(csp_params, yuv2rgb); - for (i = 0; i < 3; i++) { - int j; - yuv2rgb[i][3] -= -0.5 * (yuv2rgb[i][1] + yuv2rgb[i][2]); - for (j = 0; j < 4; j++) { - yuv2rgb[i][j] *= 0.125; - yuv2rgb[i][j] += 0.5; - if (yuv2rgb[i][j] > 1) - yuv2rgb[i][j] = 1 |