1/*
2 *  Copyright (C) 2011 Igalia S.L.
3 *
4 *  This library is free software; you can redistribute it and/or
5 *  modify it under the terms of the GNU Lesser General Public
6 *  License as published by the Free Software Foundation; either
7 *  version 2.1 of the License, or (at your option) any later version.
8 *
9 *  This library is distributed in the hope that it will be useful,
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 *  Lesser General Public License for more details.
13 *
14 *  You should have received a copy of the GNU Lesser General Public
15 *  License along with this library; if not, write to the Free Software
16 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19#include "config.h"
20#if USE(3D_GRAPHICS) || defined(QT_OPENGL_SHIMS)
21
22#define DISABLE_SHIMS
23#include "OpenGLShims.h"
24
25#if !PLATFORM(WIN)
26#include <dlfcn.h>
27#endif
28
29#include <wtf/text/CString.h>
30#include <wtf/text/WTFString.h>
31
32namespace WebCore {
33
34OpenGLFunctionTable* openGLFunctionTable()
35{
36    static OpenGLFunctionTable table;
37    return &table;
38}
39
40#if PLATFORM(WIN)
41static void* getProcAddress(const char* procName)
42{
43    return GetProcAddress(GetModuleHandleA("libGLESv2"), procName);
44}
45#else
46typedef void* (*glGetProcAddressType) (const char* procName);
47static void* getProcAddress(const char* procName)
48{
49    static bool initialized = false;
50    static glGetProcAddressType getProcAddressFunction = 0;
51
52    if (!initialized) {
53        getProcAddressFunction = reinterpret_cast<glGetProcAddressType>(dlsym(RTLD_DEFAULT, "glXGetProcAddress"));
54        if (!getProcAddressFunction)
55            getProcAddressFunction = reinterpret_cast<glGetProcAddressType>(dlsym(RTLD_DEFAULT, "glXGetProcAddressARB"));
56    }
57
58    if (!getProcAddressFunction)
59        return dlsym(RTLD_DEFAULT, procName);
60    return getProcAddressFunction(procName);
61}
62#endif
63
64static void* lookupOpenGLFunctionAddress(const char* functionName, bool* success = 0)
65{
66    if (success && !*success)
67        return 0;
68
69    void* target = getProcAddress(functionName);
70    if (target)
71        return target;
72
73    String fullFunctionName(functionName);
74    fullFunctionName.append("ARB");
75    target = getProcAddress(fullFunctionName.utf8().data());
76    if (target)
77        return target;
78
79    fullFunctionName = functionName;
80    fullFunctionName.append("EXT");
81    target = getProcAddress(fullFunctionName.utf8().data());
82
83#if defined(GL_ES_VERSION_2_0)
84    fullFunctionName = functionName;
85    fullFunctionName.append("ANGLE");
86    target = getProcAddress(fullFunctionName.utf8().data());
87    if (target)
88        return target;
89
90    fullFunctionName = functionName;
91    fullFunctionName.append("APPLE");
92    target = getProcAddress(fullFunctionName.utf8().data());
93#endif
94
95    // A null address is still a failure case.
96    if (!target && success)
97        *success = false;
98
99    return target;
100}
101
102#define ASSIGN_FUNCTION_TABLE_ENTRY(FunctionName, success) \
103    openGLFunctionTable()->FunctionName = reinterpret_cast<FunctionName##Type>(lookupOpenGLFunctionAddress(#FunctionName, &success))
104
105#define ASSIGN_FUNCTION_TABLE_ENTRY_EXT(FunctionName) \
106    openGLFunctionTable()->FunctionName = reinterpret_cast<FunctionName##Type>(lookupOpenGLFunctionAddress(#FunctionName))
107
108bool initializeOpenGLShims()
109{
110    static bool success = true;
111    static bool initialized = false;
112    if (initialized)
113        return success;
114
115    initialized = true;
116    ASSIGN_FUNCTION_TABLE_ENTRY(glActiveTexture, success);
117    ASSIGN_FUNCTION_TABLE_ENTRY(glAttachShader, success);
118    ASSIGN_FUNCTION_TABLE_ENTRY(glBindAttribLocation, success);
119    ASSIGN_FUNCTION_TABLE_ENTRY(glBindBuffer, success);
120    ASSIGN_FUNCTION_TABLE_ENTRY(glBindFramebuffer, success);
121    ASSIGN_FUNCTION_TABLE_ENTRY(glBindRenderbuffer, success);
122    ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glBindVertexArray);
123    ASSIGN_FUNCTION_TABLE_ENTRY(glBlendColor, success);
124    ASSIGN_FUNCTION_TABLE_ENTRY(glBlendEquation, success);
125    ASSIGN_FUNCTION_TABLE_ENTRY(glBlendEquationSeparate, success);
126    ASSIGN_FUNCTION_TABLE_ENTRY(glBlendFuncSeparate, success);
127    // In GLES2 there is optional an ANGLE extension for glBlitFramebuffer
128#if defined(GL_ES_VERSION_2_0)
129    ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glBlitFramebuffer);
130#else
131    ASSIGN_FUNCTION_TABLE_ENTRY(glBlitFramebuffer, success);
132#endif
133    ASSIGN_FUNCTION_TABLE_ENTRY(glBufferData, success);
134    ASSIGN_FUNCTION_TABLE_ENTRY(glBufferSubData, success);
135    ASSIGN_FUNCTION_TABLE_ENTRY(glCheckFramebufferStatus, success);
136    ASSIGN_FUNCTION_TABLE_ENTRY(glCompileShader, success);
137    ASSIGN_FUNCTION_TABLE_ENTRY(glCompressedTexImage2D, success);
138    ASSIGN_FUNCTION_TABLE_ENTRY(glCompressedTexSubImage2D, success);
139    ASSIGN_FUNCTION_TABLE_ENTRY(glCreateProgram, success);
140    ASSIGN_FUNCTION_TABLE_ENTRY(glCreateShader, success);
141    ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteBuffers, success);
142    ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteFramebuffers, success);
143    ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteProgram, success);
144    ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteRenderbuffers, success);
145    ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteShader, success);
146    ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glDeleteVertexArrays);
147    ASSIGN_FUNCTION_TABLE_ENTRY(glDetachShader, success);
148    ASSIGN_FUNCTION_TABLE_ENTRY(glDisableVertexAttribArray, success);
149    ASSIGN_FUNCTION_TABLE_ENTRY(glDrawArraysInstanced, success);
150    ASSIGN_FUNCTION_TABLE_ENTRY(glDrawBuffers, success);
151    ASSIGN_FUNCTION_TABLE_ENTRY(glDrawElementsInstanced, success);
152    ASSIGN_FUNCTION_TABLE_ENTRY(glEnableVertexAttribArray, success);
153    ASSIGN_FUNCTION_TABLE_ENTRY(glFramebufferRenderbuffer, success);
154    ASSIGN_FUNCTION_TABLE_ENTRY(glFramebufferTexture2D, success);
155    ASSIGN_FUNCTION_TABLE_ENTRY(glGenBuffers, success);
156    ASSIGN_FUNCTION_TABLE_ENTRY(glGenerateMipmap, success);
157    ASSIGN_FUNCTION_TABLE_ENTRY(glGenFramebuffers, success);
158    ASSIGN_FUNCTION_TABLE_ENTRY(glGenRenderbuffers, success);
159    ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glGenVertexArrays);
160    ASSIGN_FUNCTION_TABLE_ENTRY(glGetActiveAttrib, success);
161    ASSIGN_FUNCTION_TABLE_ENTRY(glGetActiveUniform, success);
162    ASSIGN_FUNCTION_TABLE_ENTRY(glGetAttachedShaders, success);
163    ASSIGN_FUNCTION_TABLE_ENTRY(glGetAttribLocation, success);
164    ASSIGN_FUNCTION_TABLE_ENTRY(glGetBufferParameteriv, success);
165    ASSIGN_FUNCTION_TABLE_ENTRY(glGetFramebufferAttachmentParameteriv, success);
166    ASSIGN_FUNCTION_TABLE_ENTRY(glGetProgramInfoLog, success);
167    ASSIGN_FUNCTION_TABLE_ENTRY(glGetProgramiv, success);
168    ASSIGN_FUNCTION_TABLE_ENTRY(glGetRenderbufferParameteriv, success);
169    ASSIGN_FUNCTION_TABLE_ENTRY(glGetShaderInfoLog, success);
170    ASSIGN_FUNCTION_TABLE_ENTRY(glGetShaderiv, success);
171    ASSIGN_FUNCTION_TABLE_ENTRY(glGetShaderSource, success);
172    ASSIGN_FUNCTION_TABLE_ENTRY(glGetUniformfv, success);
173    ASSIGN_FUNCTION_TABLE_ENTRY(glGetUniformiv, success);
174    ASSIGN_FUNCTION_TABLE_ENTRY(glGetUniformLocation, success);
175    ASSIGN_FUNCTION_TABLE_ENTRY(glGetVertexAttribfv, success);
176    ASSIGN_FUNCTION_TABLE_ENTRY(glGetVertexAttribiv, success);
177    ASSIGN_FUNCTION_TABLE_ENTRY(glGetVertexAttribPointerv, success);
178    ASSIGN_FUNCTION_TABLE_ENTRY(glIsBuffer, success);
179    ASSIGN_FUNCTION_TABLE_ENTRY(glIsFramebuffer, success);
180    ASSIGN_FUNCTION_TABLE_ENTRY(glIsProgram, success);
181    ASSIGN_FUNCTION_TABLE_ENTRY(glIsRenderbuffer, success);
182    ASSIGN_FUNCTION_TABLE_ENTRY(glIsShader, success);
183    ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glIsVertexArray);
184    ASSIGN_FUNCTION_TABLE_ENTRY(glLinkProgram, success);
185    ASSIGN_FUNCTION_TABLE_ENTRY(glRenderbufferStorage, success);
186    // In GLES2 there are optional ANGLE and APPLE extensions for glRenderbufferStorageMultisample.
187#if defined(GL_ES_VERSION_2_0)
188    ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glRenderbufferStorageMultisample);
189#else
190    ASSIGN_FUNCTION_TABLE_ENTRY(glRenderbufferStorageMultisample, success);
191#endif
192    ASSIGN_FUNCTION_TABLE_ENTRY(glSampleCoverage, success);
193    ASSIGN_FUNCTION_TABLE_ENTRY(glShaderSource, success);
194    ASSIGN_FUNCTION_TABLE_ENTRY(glStencilFuncSeparate, success);
195    ASSIGN_FUNCTION_TABLE_ENTRY(glStencilMaskSeparate, success);
196    ASSIGN_FUNCTION_TABLE_ENTRY(glStencilOpSeparate, success);
197    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform1f, success);
198    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform1fv, success);
199    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform1i, success);
200    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform1iv, success);
201    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform2f, success);
202    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform2fv, success);
203    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform2i, success);
204    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform2iv, success);
205    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform3f, success);
206    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform3fv, success);
207    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform3i, success);
208    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform3iv, success);
209    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform4f, success);
210    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform4fv, success);
211    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform4i, success);
212    ASSIGN_FUNCTION_TABLE_ENTRY(glUniform4iv, success);
213    ASSIGN_FUNCTION_TABLE_ENTRY(glUniformMatrix2fv, success);
214    ASSIGN_FUNCTION_TABLE_ENTRY(glUniformMatrix3fv, success);
215    ASSIGN_FUNCTION_TABLE_ENTRY(glUniformMatrix4fv, success);
216    ASSIGN_FUNCTION_TABLE_ENTRY(glUseProgram, success);
217    ASSIGN_FUNCTION_TABLE_ENTRY(glValidateProgram, success);
218    ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib1f, success);
219    ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib1fv, success);
220    ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib2f, success);
221    ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib2fv, success);
222    ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib3f, success);
223    ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib3fv, success);
224    ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib4f, success);
225    ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib4fv, success);
226    ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttribDivisor, success);
227    ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttribPointer, success);
228
229    if (!success)
230        LOG_ERROR("Could not initialize OpenGL shims");
231    return success;
232}
233
234} // namespace WebCore
235
236#endif // USE(3D_GRAPHICS)
237