diff options
Diffstat (limited to 'src/graphics/OGLHelper.cpp')
-rw-r--r-- | src/graphics/OGLHelper.cpp | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/src/graphics/OGLHelper.cpp b/src/graphics/OGLHelper.cpp new file mode 100644 index 0000000..3f8b537 --- /dev/null +++ b/src/graphics/OGLHelper.cpp @@ -0,0 +1,440 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "OGLHelper.h" + +#include "../base/Logger.h" +#include "../base/Exception.h" + +#include "GLContext.h" + +#ifndef _WIN32 +#include <dlfcn.h> +#endif + +#include <cstdio> +#include <iostream> +#include <sstream> +#include <cstring> +#include <cstdlib> +#include <assert.h> + +#if defined(__APPLE__) +#include <OpenGL/OpenGL.h> +#endif + +using namespace std; + +namespace avg { + +namespace glproc { +#ifndef AVG_ENABLE_EGL + PFNGLBUFFERSUBDATAPROC BufferSubData; + PFNGLGETBUFFERSUBDATAPROC GetBufferSubData; + PFNGLBLITFRAMEBUFFERPROC BlitFramebuffer; + PFNGLDRAWBUFFERSPROC DrawBuffers; + PFNGLDRAWRANGEELEMENTSPROC DrawRangeElements; + PFNGLGETOBJECTPARAMETERIVARBPROC GetObjectParameteriv; +#endif + PFNGLGENBUFFERSPROC GenBuffers; + PFNGLBUFFERDATAPROC BufferData; + PFNGLDEBUGMESSAGECALLBACKPROC DebugMessageCallback; + PFNGLDELETEBUFFERSPROC DeleteBuffers; + PFNGLBINDBUFFERPROC BindBuffer; + PFNGLMAPBUFFERPROC MapBuffer; + PFNGLUNMAPBUFFERPROC UnmapBuffer; + + PFNGLCREATESHADERPROC CreateShader; + PFNGLSHADERSOURCEPROC ShaderSource; + PFNGLCOMPILESHADERPROC CompileShader; + PFNGLCREATEPROGRAMPROC CreateProgram; + PFNGLATTACHSHADERPROC AttachShader; + PFNGLLINKPROGRAMPROC LinkProgram; + PFNGLGETSHADERIVPROC GetShaderiv; + PFNGLGETPROGRAMIVPROC GetProgramiv; + PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog; + PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog; + PFNGLUSEPROGRAMPROC UseProgram; + PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation; + PFNGLUNIFORM1IPROC Uniform1i; + PFNGLUNIFORM1FPROC Uniform1f; + PFNGLUNIFORM2FPROC Uniform2f; + PFNGLUNIFORM3FPROC Uniform3f; + PFNGLUNIFORM4FPROC Uniform4f; + PFNGLUNIFORM1FVPROC Uniform1fv; + PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv; + + PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate; + PFNGLBLENDEQUATIONPROC BlendEquation; + PFNGLBLENDCOLORPROC BlendColor; + PFNGLACTIVETEXTUREPROC ActiveTexture; + PFNGLGENERATEMIPMAPPROC GenerateMipmap; + + PFNGLCHECKFRAMEBUFFERSTATUSPROC CheckFramebufferStatus; + PFNGLGENFRAMEBUFFERSPROC GenFramebuffers; + PFNGLBINDFRAMEBUFFERPROC BindFramebuffer; + PFNGLFRAMEBUFFERTEXTURE2DPROC FramebufferTexture2D; + PFNGLDELETEFRAMEBUFFERSPROC DeleteFramebuffers; + PFNGLGENRENDERBUFFERSPROC GenRenderbuffers; + PFNGLBINDRENDERBUFFERPROC BindRenderbuffer; + PFNGLRENDERBUFFERSTORAGEPROC RenderbufferStorage; + PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC RenderbufferStorageMultisample; + PFNGLFRAMEBUFFERRENDERBUFFERPROC FramebufferRenderbuffer; + PFNGLDELETERENDERBUFFERSPROC DeleteRenderbuffers; + PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer; + PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray; + PFNGLBINDATTRIBLOCATIONPROC BindAttribLocation; +#if defined(linux) && !defined(AVG_ENABLE_EGL) + PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; +#endif +#ifdef _WIN32 + PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB; + PFNWGLGETSWAPINTERVALEXTPROC GetSwapIntervalEXT; + PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT; +#endif + + void * s_hGLLib = 0; +} + +bool queryOGLExtension(const char *extName) +{ + char *p; + size_t extNameLen = strlen(extName); + + p = (char *)glGetString(GL_EXTENSIONS); + AVG_ASSERT(p != 0); + char * end = p + strlen(p); + while (p < end) { + size_t n = strcspn(p, " "); + if ((extNameLen == n) && (strncmp(extName, p, n) == 0)) { + return true; + } + p += (n + 1); + } + return false; +} + +bool queryGLXExtension(const char *extName) +{ +#if (defined __APPLE__) || (defined _WIN32) || (defined AVG_ENABLE_EGL) + return false; +#else + int extNameLen = strlen(extName); + + Display * display = XOpenDisplay(0); + char * p = (char *)glXQueryExtensionsString(display, DefaultScreen(display)); + if (NULL == p) { + throw Exception(AVG_ERR_VIDEO_GENERAL, "Couldn't get GLX extension string."); + } + + char * end = p + strlen(p); + + while (p < end) { + int n = strcspn(p, " "); + if ((extNameLen == n) && (strncmp(extName, p, n) == 0)) { +// If we close the display connection on some drivers (at least fglrx/Ubuntu 11.04), +// libavg crashes soon afterwards. +// XCloseDisplay(display); + return true; + } + p += (n + 1); + } +// XCloseDisplay(display); + return false; +#endif +} + +string AVG_API oglModeToString(int mode) +{ + switch (mode) { + case GL_ALPHA: + return "GL_ALPHA"; + case GL_RGB: + return "GL_RGB"; + case GL_RGBA: + return "GL_RGBA"; +#ifdef AVG_ENABLE_EGL + case GL_BGRA_EXT: + return "GL_BGRA_EXT"; +#else + case GL_BGR: + return "GL_BGR"; + case GL_BGRA: + return "GL_BGRA"; +#endif + default: + return "UNKNOWN"; + } +} + +#ifdef _WIN32 +#define GL_ALL_CLIENT_ATTRIB_BITS GL_CLIENT_ALL_ATTRIB_BITS +#endif + +string oglMemoryMode2String(OGLMemoryMode mode) +{ + switch (mode) { + case MM_PBO: + return "PBO"; + case MM_OGL: + return "OGL"; + default: + return "invalid gl mem mode"; + } +} + +void AVG_API clearGLBuffers(GLbitfield mask, bool bOpaque) +{ + float alpha; + if (bOpaque) { + alpha = 1.0; + } else { + alpha = 0.0; + } + glClearColor(0.0, 0.0, 0.0, alpha); + if (mask & GL_STENCIL_BUFFER_BIT) { + glStencilMask(~0); + glClearStencil(0); + } + glClear(mask); + GLContext::checkError("clearGLBuffers()"); + if (mask & GL_STENCIL_BUFFER_BIT) { + glStencilMask(0); + } +} + +void invalidGLCall() +{ + assert(false); +} + +void loadGLLibrary() +{ +#ifdef _WIN32 + const char * pszFName = "OPENGL32.DLL"; + char szErr[512]; + + glproc::s_hGLLib = (void *)LoadLibrary(pszFName); + + if (glproc::s_hGLLib == 0) { + FormatMessage((FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM), + 0, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + szErr, 512, 0); + throw Exception(AVG_ERR_VIDEO_GENERAL, string("Loading ") + pszFName + "failed: " + + szErr); + } +#else +#ifdef __APPLE__ + const char * pszFName = "/System/Library/Frameworks/OpenGL.framework/OpenGL"; +#else +#ifdef AVG_ENABLE_EGL + const char * pszFName = "libGLESv2.so"; +#else + const char * pszFName = "libGL.so.1"; +#endif +#endif + glproc::s_hGLLib = dlopen(pszFName, RTLD_NOW); + if (glproc::s_hGLLib == 0) { + const char * pszErr = (char *)dlerror(); + throw Exception(AVG_ERR_VIDEO_GENERAL, string("Loading ") + pszFName + "failed: " + + pszErr); + } +#endif +} + +GLfunction getProcAddress(const string& sName) +{ + AVG_ASSERT(glproc::s_hGLLib); +#ifdef _WIN32 + GLfunction pProc = (GLfunction)wglGetProcAddress(sName.c_str()); +/* + if (!pProc) { + char szErr[512]; + FormatMessage((FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM), + 0, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + szErr, 512, 0); + throw Exception(AVG_ERR_VIDEO_GENERAL, + string("wglGetProcAddress("+sName+") failed: ") + szErr); + } +*/ +#else + GLfunction pProc = (GLfunction)dlsym(glproc::s_hGLLib, sName.c_str()); + if (!pProc) { + // If the name didn't work, try using an underscore :-). + string sName_ = string("_")+sName; + pProc = (GLfunction)dlsym(glproc::s_hGLLib, sName_.c_str()); + } +#endif + return(pProc); +} + +GLfunction getFuzzyProcAddress(const char * psz) +{ + GLfunction pProc = getProcAddress(psz); + if (!pProc) { + string s = string(psz)+"EXT"; + pProc = getProcAddress(s); + } + if (!pProc) { + string s = string(psz)+"ARB"; + pProc = getProcAddress(s); + } + if (!pProc) { + string s = string(psz)+"OES"; + pProc = getProcAddress(s); + } + if (!pProc) { + pProc = invalidGLCall; + } + return pProc; +} + +#if defined(linux) && !defined(AVG_ENABLE_EGL) +GLfunction getglXProcAddress(const char * psz) +{ + GLfunction pProc = (GLfunction)glXGetProcAddress((const GLubyte *)psz); + if (!pProc) { + pProc = invalidGLCall; + } + return pProc; +} +#endif + +#ifdef _WIN32 +GLfunction getwglProcAddress(const char * psz) +{ + GLfunction pProc = (GLfunction)wglGetProcAddress((LPCSTR)psz); + if (!pProc) { + pProc = invalidGLCall; + } + return pProc; +} +#endif + +namespace glproc { + + void init() { + static bool s_bInitialized = false; + if (s_bInitialized) { + return; + } + s_bInitialized = true; + loadGLLibrary(); + + GenBuffers = (PFNGLGENBUFFERSPROC)getFuzzyProcAddress("glGenBuffers"); + BufferData = (PFNGLBUFFERDATAPROC)getFuzzyProcAddress("glBufferData"); + DeleteBuffers = (PFNGLDELETEBUFFERSPROC)getFuzzyProcAddress("glDeleteBuffers"); + BindBuffer = (PFNGLBINDBUFFERPROC)getFuzzyProcAddress("glBindBuffer"); + MapBuffer = (PFNGLMAPBUFFERPROC)getFuzzyProcAddress("glMapBuffer"); + UnmapBuffer = (PFNGLUNMAPBUFFERPROC)getFuzzyProcAddress("glUnmapBuffer"); + + CreateShader = (PFNGLCREATESHADERPROC)getFuzzyProcAddress("glCreateShader"); + ShaderSource = (PFNGLSHADERSOURCEPROC)getFuzzyProcAddress("glShaderSource"); + CompileShader = (PFNGLCOMPILESHADERPROC)getFuzzyProcAddress("glCompileShader"); + CreateProgram= (PFNGLCREATEPROGRAMPROC)getFuzzyProcAddress("glCreateProgram"); + AttachShader = (PFNGLATTACHSHADERPROC)getFuzzyProcAddress("glAttachShader"); + LinkProgram = (PFNGLLINKPROGRAMPROC)getFuzzyProcAddress("glLinkProgram"); + GetShaderiv = (PFNGLGETSHADERIVPROC)getFuzzyProcAddress("glGetShaderiv"); + GetProgramiv = (PFNGLGETPROGRAMIVPROC)getFuzzyProcAddress("glGetProgramiv"); + GetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) + getFuzzyProcAddress("glGetShaderInfoLog"); + GetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) + getFuzzyProcAddress("glGetProgramInfoLog"); + UseProgram =(PFNGLUSEPROGRAMPROC) getFuzzyProcAddress("glUseProgram"); + GetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) + getFuzzyProcAddress("glGetUniformLocation"); + Uniform1i = (PFNGLUNIFORM1IPROC)getFuzzyProcAddress("glUniform1i"); + Uniform1f = (PFNGLUNIFORM1FPROC)getFuzzyProcAddress("glUniform1f"); + Uniform2f = (PFNGLUNIFORM2FPROC)getFuzzyProcAddress("glUniform2f"); + Uniform3f = (PFNGLUNIFORM3FPROC)getFuzzyProcAddress("glUniform3f"); + Uniform4f = (PFNGLUNIFORM4FPROC)getFuzzyProcAddress("glUniform4f"); + Uniform1fv = (PFNGLUNIFORM1FVPROC)getFuzzyProcAddress("glUniform1fv"); + UniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) + getFuzzyProcAddress("glUniformMatrix4fv"); + + BlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) + getFuzzyProcAddress("glBlendFuncSeparate"); + BlendEquation = (PFNGLBLENDEQUATIONPROC)getFuzzyProcAddress("glBlendEquation"); + BlendColor = (PFNGLBLENDCOLORPROC)getFuzzyProcAddress("glBlendColor"); + ActiveTexture = (PFNGLACTIVETEXTUREPROC)getFuzzyProcAddress("glActiveTexture"); + GenerateMipmap = (PFNGLGENERATEMIPMAPPROC)getFuzzyProcAddress + ("glGenerateMipmap"); + + CheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) + getFuzzyProcAddress("glCheckFramebufferStatus"); + GenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) + getFuzzyProcAddress("glGenFramebuffers"); + BindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) + getFuzzyProcAddress("glBindFramebuffer"); + FramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) + getFuzzyProcAddress("glFramebufferTexture2D"); + DeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) + getFuzzyProcAddress("glDeleteFramebuffers"); + GenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) + getFuzzyProcAddress("glGenRenderbuffers"); + BindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) + getFuzzyProcAddress("glBindRenderbuffer"); + RenderbufferStorage= (PFNGLRENDERBUFFERSTORAGEPROC) + getFuzzyProcAddress("glRenderbufferStorage"); + RenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) + getFuzzyProcAddress("glRenderbufferStorageMultisample"); + FramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) + getFuzzyProcAddress("glFramebufferRenderbuffer"); + + DeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) + getFuzzyProcAddress("glDeleteRenderbuffers"); +#ifndef AVG_ENABLE_EGL + BufferSubData = (PFNGLBUFFERSUBDATAPROC)getFuzzyProcAddress("glBufferSubData"); + GetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC)getFuzzyProcAddress + ("glGetBufferSubData"); + GetObjectParameteriv = (PFNGLGETOBJECTPARAMETERIVARBPROC) + getFuzzyProcAddress("glGetObjectParameteriv"); + + BlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) + getFuzzyProcAddress("glBlitFramebuffer"); + DrawBuffers = (PFNGLDRAWBUFFERSPROC)getFuzzyProcAddress("glDrawBuffers"); + DrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) + getFuzzyProcAddress("glDrawRangeElements"); + DebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKARBPROC) + getFuzzyProcAddress("glDebugMessageCallback"); +#endif + VertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) + getFuzzyProcAddress("glVertexAttribPointer"); + EnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) + getFuzzyProcAddress("glEnableVertexAttribArray"); + BindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) + getFuzzyProcAddress("glBindAttribLocation"); +#if defined(linux) && !defined(AVG_ENABLE_EGL) + SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) + getglXProcAddress("glXSwapIntervalEXT"); +#endif +#ifdef _WIN32 + GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) + getwglProcAddress("wglGetExtensionsStringARB"); + GetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC) + getwglProcAddress("wglGetSwapIntervalEXT"); + SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) + getwglProcAddress("wglSwapIntervalEXT"); +#endif + } +} + +} |