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 ENABLE(GRAPHICS_CONTEXT_3D)
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 target = getProcAddress(reinterpret_cast<const char*>(makeString(functionName, "ARB").characters8()));
74 if (target)
75 return target;
76
77 // FIXME: <https://webkit.org/b/143964> OpenGLShims appears to have a dead store if GLES2
78 target = getProcAddress(reinterpret_cast<const char*>(makeString(functionName, "EXT").characters8()));
79
80#if defined(GL_ES_VERSION_2_0)
81 target = getProcAddress(reinterpret_cast<const char*>(makeString(functionName, "ANGLE").characters8()));
82 if (target)
83 return target;
84
85 target = getProcAddress(reinterpret_cast<const char*>(makeString(functionName, "APPLE").characters8()));
86#endif
87
88 // A null address is still a failure case.
89 if (!target && success)
90 *success = false;
91
92 return target;
93}
94
95#define ASSIGN_FUNCTION_TABLE_ENTRY(FunctionName, success) \
96 openGLFunctionTable()->FunctionName = reinterpret_cast<FunctionName##Type>(lookupOpenGLFunctionAddress(#FunctionName, &success))
97
98#define ASSIGN_FUNCTION_TABLE_ENTRY_EXT(FunctionName) \
99 openGLFunctionTable()->FunctionName = reinterpret_cast<FunctionName##Type>(lookupOpenGLFunctionAddress(#FunctionName))
100
101bool initializeOpenGLShims()
102{
103 static bool success = true;
104 static bool initialized = false;
105 if (initialized)
106 return success;
107
108 initialized = true;
109 ASSIGN_FUNCTION_TABLE_ENTRY(glActiveTexture, success);
110 ASSIGN_FUNCTION_TABLE_ENTRY(glAttachShader, success);
111 ASSIGN_FUNCTION_TABLE_ENTRY(glBindAttribLocation, success);
112 ASSIGN_FUNCTION_TABLE_ENTRY(glBindBuffer, success);
113 ASSIGN_FUNCTION_TABLE_ENTRY(glBindFramebuffer, success);
114 ASSIGN_FUNCTION_TABLE_ENTRY(glBindRenderbuffer, success);
115 ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glBindVertexArray);
116 ASSIGN_FUNCTION_TABLE_ENTRY(glBlendColor, success);
117 ASSIGN_FUNCTION_TABLE_ENTRY(glBlendEquation, success);
118 ASSIGN_FUNCTION_TABLE_ENTRY(glBlendEquationSeparate, success);
119 ASSIGN_FUNCTION_TABLE_ENTRY(glBlendFuncSeparate, success);
120 // In GLES2 there is optional an ANGLE extension for glBlitFramebuffer
121#if defined(GL_ES_VERSION_2_0)
122 ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glBlitFramebuffer);
123#else
124 ASSIGN_FUNCTION_TABLE_ENTRY(glBlitFramebuffer, success);
125#endif
126 ASSIGN_FUNCTION_TABLE_ENTRY(glBufferData, success);
127 ASSIGN_FUNCTION_TABLE_ENTRY(glBufferSubData, success);
128 ASSIGN_FUNCTION_TABLE_ENTRY(glCheckFramebufferStatus, success);
129 ASSIGN_FUNCTION_TABLE_ENTRY(glCompileShader, success);
130 ASSIGN_FUNCTION_TABLE_ENTRY(glCompressedTexImage2D, success);
131 ASSIGN_FUNCTION_TABLE_ENTRY(glCompressedTexSubImage2D, success);
132 ASSIGN_FUNCTION_TABLE_ENTRY(glCreateProgram, success);
133 ASSIGN_FUNCTION_TABLE_ENTRY(glCreateShader, success);
134 ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteBuffers, success);
135 ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteFramebuffers, success);
136 ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteProgram, success);
137 ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteRenderbuffers, success);
138 ASSIGN_FUNCTION_TABLE_ENTRY(glDeleteShader, success);
139 ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glDeleteVertexArrays);
140 ASSIGN_FUNCTION_TABLE_ENTRY(glDetachShader, success);
141 ASSIGN_FUNCTION_TABLE_ENTRY(glDisableVertexAttribArray, success);
142 ASSIGN_FUNCTION_TABLE_ENTRY(glDrawArraysInstanced, success);
143 ASSIGN_FUNCTION_TABLE_ENTRY(glDrawBuffers, success);
144 ASSIGN_FUNCTION_TABLE_ENTRY(glDrawElementsInstanced, success);
145 ASSIGN_FUNCTION_TABLE_ENTRY(glEnableVertexAttribArray, success);
146 ASSIGN_FUNCTION_TABLE_ENTRY(glFramebufferRenderbuffer, success);
147 ASSIGN_FUNCTION_TABLE_ENTRY(glFramebufferTexture2D, success);
148 ASSIGN_FUNCTION_TABLE_ENTRY(glGenBuffers, success);
149 ASSIGN_FUNCTION_TABLE_ENTRY(glGenerateMipmap, success);
150 ASSIGN_FUNCTION_TABLE_ENTRY(glGenFramebuffers, success);
151 ASSIGN_FUNCTION_TABLE_ENTRY(glGenRenderbuffers, success);
152 ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glGenVertexArrays);
153 ASSIGN_FUNCTION_TABLE_ENTRY(glGetActiveAttrib, success);
154 ASSIGN_FUNCTION_TABLE_ENTRY(glGetActiveUniform, success);
155 ASSIGN_FUNCTION_TABLE_ENTRY(glGetAttachedShaders, success);
156 ASSIGN_FUNCTION_TABLE_ENTRY(glGetAttribLocation, success);
157 ASSIGN_FUNCTION_TABLE_ENTRY(glGetBufferParameteriv, success);
158 ASSIGN_FUNCTION_TABLE_ENTRY(glGetFramebufferAttachmentParameteriv, success);
159 ASSIGN_FUNCTION_TABLE_ENTRY(glGetProgramInfoLog, success);
160 ASSIGN_FUNCTION_TABLE_ENTRY(glGetProgramiv, success);
161 ASSIGN_FUNCTION_TABLE_ENTRY(glGetRenderbufferParameteriv, success);
162 ASSIGN_FUNCTION_TABLE_ENTRY(glGetShaderInfoLog, success);
163 ASSIGN_FUNCTION_TABLE_ENTRY(glGetShaderiv, success);
164 ASSIGN_FUNCTION_TABLE_ENTRY(glGetShaderSource, success);
165 // glGetStringi is only available on OpenGL or GLES versions >= 3.0.
166 // Add it with _EXT so it doesn't cause an initialization failure on lower versions.
167 ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glGetStringi);
168 ASSIGN_FUNCTION_TABLE_ENTRY(glGetUniformfv, success);
169 ASSIGN_FUNCTION_TABLE_ENTRY(glGetUniformiv, success);
170 ASSIGN_FUNCTION_TABLE_ENTRY(glGetUniformLocation, success);
171 ASSIGN_FUNCTION_TABLE_ENTRY(glGetVertexAttribfv, success);
172 ASSIGN_FUNCTION_TABLE_ENTRY(glGetVertexAttribiv, success);
173 ASSIGN_FUNCTION_TABLE_ENTRY(glGetVertexAttribPointerv, success);
174 ASSIGN_FUNCTION_TABLE_ENTRY(glIsBuffer, success);
175 ASSIGN_FUNCTION_TABLE_ENTRY(glIsFramebuffer, success);
176 ASSIGN_FUNCTION_TABLE_ENTRY(glIsProgram, success);
177 ASSIGN_FUNCTION_TABLE_ENTRY(glIsRenderbuffer, success);
178 ASSIGN_FUNCTION_TABLE_ENTRY(glIsShader, success);
179 ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glIsVertexArray);
180 ASSIGN_FUNCTION_TABLE_ENTRY(glLinkProgram, success);
181 ASSIGN_FUNCTION_TABLE_ENTRY(glRenderbufferStorage, success);
182 // In GLES2 there are optional ANGLE and APPLE extensions for glRenderbufferStorageMultisample.
183#if defined(GL_ES_VERSION_2_0)
184 ASSIGN_FUNCTION_TABLE_ENTRY_EXT(glRenderbufferStorageMultisample);
185#else
186 ASSIGN_FUNCTION_TABLE_ENTRY(glRenderbufferStorageMultisample, success);
187#endif
188 ASSIGN_FUNCTION_TABLE_ENTRY(glSampleCoverage, success);
189 ASSIGN_FUNCTION_TABLE_ENTRY(glShaderSource, success);
190 ASSIGN_FUNCTION_TABLE_ENTRY(glStencilFuncSeparate, success);
191 ASSIGN_FUNCTION_TABLE_ENTRY(glStencilMaskSeparate, success);
192 ASSIGN_FUNCTION_TABLE_ENTRY(glStencilOpSeparate, success);
193 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform1f, success);
194 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform1fv, success);
195 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform1i, success);
196 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform1iv, success);
197 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform2f, success);
198 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform2fv, success);
199 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform2i, success);
200 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform2iv, success);
201 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform3f, success);
202 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform3fv, success);
203 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform3i, success);
204 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform3iv, success);
205 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform4f, success);
206 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform4fv, success);
207 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform4i, success);
208 ASSIGN_FUNCTION_TABLE_ENTRY(glUniform4iv, success);
209 ASSIGN_FUNCTION_TABLE_ENTRY(glUniformMatrix2fv, success);
210 ASSIGN_FUNCTION_TABLE_ENTRY(glUniformMatrix3fv, success);
211 ASSIGN_FUNCTION_TABLE_ENTRY(glUniformMatrix4fv, success);
212 ASSIGN_FUNCTION_TABLE_ENTRY(glUseProgram, success);
213 ASSIGN_FUNCTION_TABLE_ENTRY(glValidateProgram, success);
214 ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib1f, success);
215 ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib1fv, success);
216 ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib2f, success);
217 ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib2fv, success);
218 ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib3f, success);
219 ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib3fv, success);
220 ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib4f, success);
221 ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttrib4fv, success);
222 ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttribDivisor, success);
223 ASSIGN_FUNCTION_TABLE_ENTRY(glVertexAttribPointer, success);
224
225 if (!success)
226 LOG_ERROR("Could not initialize OpenGL shims");
227 return success;
228}
229
230} // namespace WebCore
231
232#endif // ENABLE(GRAPHICS_CONTEXT_3D)
233