summaryrefslogtreecommitdiffstats
path: root/libvo/gl_common.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-11-05 17:02:04 +0100
committerwm4 <wm4@nowhere>2012-11-12 20:06:14 +0100
commitd4bdd0473d6f43132257c9fb3848d829755167a3 (patch)
tree8021c2f7da1841393c8c832105e20cd527826d6c /libvo/gl_common.c
parentbd48deba77bd5582c5829d6fe73a7d2571088aba (diff)
downloadmpv-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.c2654
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 = &section->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 = &section->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