blob: fa6aa92f1113689bcbea3719440c56e148a90530 [file] [log] [blame]
twiz@google.com59a190b2011-03-14 21:23:01 +00001/*
2 Copyright 2011 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "GrGLInterface.h"
19#include "GrTypes.h"
20
21#include <stdio.h>
22
23#if defined(GR_GL_PROC_ADDRESS_HEADER)
24 #include GR_GL_PROC_ADDRESS_HEADER
25#endif
26
27#if !defined(GR_GL_PROC_ADDRESS)
28 #error "Must define GR_GL_PROC_ADDRESS"
29#endif
30
31#define GR_GL_GET_PROC(PROC_NAME) \
32 glBindings->f##PROC_NAME = \
33 reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>( \
34 GR_GL_PROC_ADDRESS(gl##PROC_NAME)); \
35 GrAssert(NULL != glBindings->f##PROC_NAME && \
36 "Missing GL binding: " #PROC_NAME);
37
38#define GR_GL_GET_PROC_SUFFIX(PROC_NAME, SUFFIX) \
39 glBindings->f##PROC_NAME = \
40 reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>( \
41 GR_GL_PROC_ADDRESS(gl##PROC_NAME##SUFFIX)); \
42 GrAssert(NULL != glBindings->f##PROC_NAME && \
43 "Missing GL binding: " #PROC_NAME);
44
45#define GR_GL_GET_PROC_SYMBOL(PROC_NAME) \
46 glBindings->f##PROC_NAME = reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>(gl##PROC_NAME);
47
48namespace {
49
50void gl_version_from_string(int* major, int* minor,
51 const char* versionString) {
52 if (NULL == versionString) {
53 GrAssert(0);
54 *major = 0;
55 *minor = 0;
56 return;
57 }
58#if GR_SUPPORT_GLDESKTOP
59 int n = sscanf(versionString, "%d.%d", major, minor);
60 if (n != 2) {
61 GrAssert(0);
62 *major = 0;
63 *minor = 0;
64 return;
65 }
66#else
67 char profile[2];
68 int n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
69 major, minor);
70 bool ok = 4 == n;
71 if (!ok) {
72 int n = sscanf(versionString, "OpenGL ES %d.%d", major, minor);
73 ok = 2 == n;
74 }
75 if (!ok) {
76 GrAssert(0);
77 *major = 0;
78 *minor = 0;
79 return;
80 }
81#endif
82}
83
84bool has_gl_extension_from_string(const char* ext,
85 const char* extensionString) {
86 int extLength = strlen(ext);
87
88 while (true) {
89 int n = strcspn(extensionString, " ");
90 if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
91 return true;
92 }
93 if (0 == extensionString[n]) {
94 return false;
95 }
96 extensionString += n+1;
97 }
98
99 return false;
100}
101
102GrGLInterface* gGLInterface = NULL;
103
104void InitializeGLInterfaceExtensions(GrGLInterface* glBindings) {
105 int major, minor;
106 const char* versionString = reinterpret_cast<const char*>(
107 glBindings->fGetString(GL_VERSION));
108 const char* extensionString = reinterpret_cast<const char*>(
109 glBindings->fGetString(GL_EXTENSIONS));
110 gl_version_from_string(&major, &minor, versionString);
111
112 bool fboFound = false;
113#if GR_SUPPORT_GLDESKTOP
114 if (major >= 3 || has_gl_extension_from_string("GL_ARB_framebuffer_object",
115 extensionString)) {
116 // GL_ARB_framebuffer_object doesn't use ARB suffix.
117 GR_GL_GET_PROC(GenFramebuffers);
118 GR_GL_GET_PROC(BindFramebuffer);
119 GR_GL_GET_PROC(FramebufferTexture2D);
120 GR_GL_GET_PROC(CheckFramebufferStatus);
121 GR_GL_GET_PROC(DeleteFramebuffers);
122 GR_GL_GET_PROC(RenderbufferStorage);
123 GR_GL_GET_PROC(GenRenderbuffers);
124 GR_GL_GET_PROC(DeleteRenderbuffers);
125 GR_GL_GET_PROC(FramebufferRenderbuffer);
126 GR_GL_GET_PROC(BindRenderbuffer);
127 GR_GL_GET_PROC(RenderbufferStorageMultisample);
128 GR_GL_GET_PROC(BlitFramebuffer);
129 fboFound = true;
130 }
131
132 #if GL_EXT_framebuffer_object && !GR_MAC_BUILD
133 if (!fboFound &&
134 has_gl_extension_from_string("GL_EXT_framebuffer_object",
135 extensionString)) {
136 GR_GL_GET_PROC_SUFFIX(GenFramebuffers, EXT);
137 GR_GL_GET_PROC_SUFFIX(BindFramebuffer, EXT);
138 GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, EXT);
139 GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, EXT);
140 GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, EXT);
141 GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, EXT);
142 GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, EXT);
143 GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, EXT);
144 GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT);
145 GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, EXT);
146 fboFound = true;
147
148 if (has_gl_extension_from_string("GL_EXT_framebuffer_multisample",
149 extensionString)) {
150 GR_GL_GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT);
151 }
152 if (has_gl_extension_from_string("GL_EXT_framebuffer_blit",
153 extensionString)) {
154 GR_GL_GET_PROC_SUFFIX(BlitFramebuffer, EXT);
155 }
156 }
157 #endif
158
159 // we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5)
160 GrAssert((major == 1 && minor >= 5) || major >=2);
161 GR_GL_GET_PROC(MapBuffer);
162 GR_GL_GET_PROC(UnmapBuffer);
163#else // !GR_SUPPORT_GLDESKTOP
164 #if GR_SUPPORT_GLES2
165 if (!fboFound && major >= 2) {// ES 2.0 supports FBO
166 GR_GL_GET_PROC(GenFramebuffers);
167 GR_GL_GET_PROC(BindFramebuffer);
168 GR_GL_GET_PROC(FramebufferTexture2D);
169 GR_GL_GET_PROC(CheckFramebufferStatus);
170 GR_GL_GET_PROC(DeleteFramebuffers);
171 GR_GL_GET_PROC(RenderbufferStorage);
172 GR_GL_GET_PROC(GenRenderbuffers);
173 GR_GL_GET_PROC(DeleteRenderbuffers);
174 GR_GL_GET_PROC(FramebufferRenderbuffer);
175 GR_GL_GET_PROC(BindRenderbuffer);
176 fboFound = true;
177 }
178 #endif
179
180 #if GL_OES_mapbuffer
181 if (!fboFound &&
182 has_gl_extension_from_string("GL_OES_framebuffer_object",
183 extensionString)) {
184 GR_GL_GET_PROC_SUFFIX(GenFramebuffers, OES);
185 GR_GL_GET_PROC_SUFFIX(BindFramebuffer, OES);
186 GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, OES);
187 GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, OES);
188 GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, OES);
189 GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, OES);
190 GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, OES);
191 GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, OES);
192 GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, OES);
193 GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, OES);
194 fboFound = true;
195 }
196 #endif
197
198 #if GL_APPLE_framebuffer_multisample
199 if (has_gl_extension_from_string("GL_APPLE_framebuffer_multisample",
200 extensionString)) {
201 GR_GL_GET_PROC_SUFFIX(ResolveMultisampleFramebuffer, APPLE);
202 }
203 #endif
204
205 #if GL_IMG_multisampled_render_to_texture
206 if (has_gl_extension_from_string(
207 "GL_IMG_multisampled_render_to_texture", extensionString)) {
208 GR_GL_GET_PROC_SUFFIX(FramebufferTexture2DMultisample, IMG);
209 }
210 #endif
211
212 #if GL_OES_mapbuffer
213 if (has_gl_extension_from_string("GL_OES_mapbuffer", extensionString)) {
214 GR_GL_GET_PROC_SUFFIX(MapBuffer, OES);
215 GR_GL_GET_PROC_SUFFIX(UnmapBuffer, OES);
216 }
217 #endif
218#endif // !GR_SUPPORT_GLDESKTOP
219
220 if (!fboFound) {
221 // we require some form of FBO
222 GrAssert(!"No FBOs supported?");
223 }
224}
225
226void GrGLInitializeGLInterface(GrGLInterface* glBindings) {
227 Gr_bzero(glBindings, sizeof(GrGLInterface));
228
twiz@google.comdc008e12011-03-15 16:12:21 +0000229#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES1
twiz@google.com59a190b2011-03-14 21:23:01 +0000230 // These entry points only exist on desktop GL implementations.
231 GR_GL_GET_PROC_SYMBOL(Color4ub);
232 GR_GL_GET_PROC_SYMBOL(ColorPointer);
233 GR_GL_GET_PROC_SYMBOL(DisableClientState);
234 GR_GL_GET_PROC_SYMBOL(EnableClientState);
235 GR_GL_GET_PROC_SYMBOL(LoadMatrixf);
236 GR_GL_GET_PROC_SYMBOL(MatrixMode);
237 GR_GL_GET_PROC_SYMBOL(PointSize);
238 GR_GL_GET_PROC_SYMBOL(ShadeModel);
239 GR_GL_GET_PROC_SYMBOL(TexCoordPointer);
240 GR_GL_GET_PROC_SYMBOL(TexEnvi);
241 GR_GL_GET_PROC_SYMBOL(VertexPointer);
242 GR_GL_GET_PROC(ClientActiveTexture);
243#endif
244
245 // The following gl entry points are part of GL 1.1, and will always be
246 // exported as symbols.
247 // Note that on windows, the wglGetProcAddress call will fail to retrieve
248 // these entry points.
249 GR_GL_GET_PROC_SYMBOL(BlendFunc);
250 GR_GL_GET_PROC_SYMBOL(Clear);
251 GR_GL_GET_PROC_SYMBOL(ClearColor);
252 GR_GL_GET_PROC_SYMBOL(ClearStencil);
253 GR_GL_GET_PROC_SYMBOL(ColorMask);
254 GR_GL_GET_PROC_SYMBOL(CullFace);
255 GR_GL_GET_PROC_SYMBOL(DeleteTextures);
256 GR_GL_GET_PROC_SYMBOL(DepthMask);
257 GR_GL_GET_PROC_SYMBOL(Disable);
258 GR_GL_GET_PROC_SYMBOL(DrawArrays);
259 GR_GL_GET_PROC_SYMBOL(DrawElements);
260 GR_GL_GET_PROC_SYMBOL(Enable);
261 GR_GL_GET_PROC_SYMBOL(FrontFace);
262 GR_GL_GET_PROC_SYMBOL(GenTextures);
263 GR_GL_GET_PROC_SYMBOL(GetError);
264 GR_GL_GET_PROC_SYMBOL(GetIntegerv);
265 GR_GL_GET_PROC_SYMBOL(GetString);
266 GR_GL_GET_PROC_SYMBOL(LineWidth);
267 GR_GL_GET_PROC_SYMBOL(PixelStorei);
268 GR_GL_GET_PROC_SYMBOL(ReadPixels);
269 GR_GL_GET_PROC_SYMBOL(Scissor);
270 GR_GL_GET_PROC_SYMBOL(StencilFunc);
271 GR_GL_GET_PROC_SYMBOL(StencilMask);
272 GR_GL_GET_PROC_SYMBOL(StencilOp);
273 GR_GL_GET_PROC_SYMBOL(TexImage2D);
274 GR_GL_GET_PROC_SYMBOL(TexParameteri);
275 GR_GL_GET_PROC_SYMBOL(TexSubImage2D);
276 GR_GL_GET_PROC_SYMBOL(Viewport);
277
278 // Capture the remaining entry points as gl extensions.
279 GR_GL_GET_PROC(ActiveTexture);
280 GR_GL_GET_PROC(AttachShader);
281 GR_GL_GET_PROC(BindAttribLocation);
282 GR_GL_GET_PROC(BindBuffer);
283 GR_GL_GET_PROC(BindTexture);
bsalomon@google.com080773c2011-03-15 19:09:25 +0000284 GR_GL_GET_PROC(BlendColor);
twiz@google.com59a190b2011-03-14 21:23:01 +0000285 GR_GL_GET_PROC(BufferData);
286 GR_GL_GET_PROC(BufferSubData);
287 GR_GL_GET_PROC(CompileShader);
288 GR_GL_GET_PROC(CompressedTexImage2D);
289 GR_GL_GET_PROC(CreateProgram);
290 GR_GL_GET_PROC(CreateShader);
291 GR_GL_GET_PROC(DeleteBuffers);
292 GR_GL_GET_PROC(DeleteProgram);
293 GR_GL_GET_PROC(DeleteShader);
294 GR_GL_GET_PROC(DisableVertexAttribArray);
295 GR_GL_GET_PROC(EnableVertexAttribArray);
296 GR_GL_GET_PROC(GenBuffers);
297 GR_GL_GET_PROC(GetBufferParameteriv);
298 GR_GL_GET_PROC(GetProgramInfoLog);
299 GR_GL_GET_PROC(GetProgramiv);
300 GR_GL_GET_PROC(GetShaderInfoLog);
301 GR_GL_GET_PROC(GetShaderiv);
302 GR_GL_GET_PROC(GetUniformLocation);
303 GR_GL_GET_PROC(LinkProgram);
304 GR_GL_GET_PROC(ShaderSource);
305 GR_GL_GET_PROC(StencilFuncSeparate);
306 GR_GL_GET_PROC(StencilMaskSeparate);
307 GR_GL_GET_PROC(StencilOpSeparate);
308 GR_GL_GET_PROC(Uniform1fv);
309 GR_GL_GET_PROC(Uniform1i);
310 GR_GL_GET_PROC(Uniform4fv);
311 GR_GL_GET_PROC(UniformMatrix3fv);
312 GR_GL_GET_PROC(UseProgram);
313 GR_GL_GET_PROC(VertexAttrib4fv);
314 GR_GL_GET_PROC(VertexAttribPointer);
315
316 InitializeGLInterfaceExtensions(glBindings);
317}
318
319} // unnamed namespace
320
321void GrGLSetGLInterface(GrGLInterface* gl_interface) {
322 gGLInterface = gl_interface;
323}
324
325GrGLInterface* GrGLGetGLInterface() {
326 return gGLInterface;
327}
328
329void GrGLSetDefaultGLInterface() {
330 static GrGLInterface gDefaultInterface;
331 static bool gDefaultInitialized = false;
332 GrAssert(!gDefaultInitialized);
333
334 if (!gDefaultInitialized) {
335 GrGLInitializeGLInterface(&gDefaultInterface);
336 GrGLSetGLInterface(&gDefaultInterface);
337 }
338}
339
340bool has_gl_extension(const char* ext) {
341 const char* glstr = reinterpret_cast<const char*>(
342 GrGLGetGLInterface()->fGetString(GL_EXTENSIONS));
343
344 return has_gl_extension_from_string(ext, glstr);
345}
346
347void gl_version(int* major, int* minor) {
348 const char* v = reinterpret_cast<const char*>(
349 GrGLGetGLInterface()->fGetString(GL_VERSION));
350 gl_version_from_string(major, minor, v);
351}