blob: 0bddd98a753f388d69b2be982c1e02dd9e2693ff [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
twiz@google.com0f31ca72011-03-18 17:38:11 +000021#include "GrGLPlatformIncludes.h"
twiz@google.com59a190b2011-03-14 21:23:01 +000022#include <stdio.h>
23
twiz@google.com0f31ca72011-03-18 17:38:11 +000024#if defined(GR_GL_PLATFORM_HEADER_SUPPORT)
25 #include GR_GL_PLATFORM_HEADER_SUPPORT
26#endif
27
28#if defined(GR_GL_PLATFORM_HEADER)
29 #include GR_GL_PLATFORM_HEADER
30#endif
31
32#if defined(GR_GL_PLATFORM_HEADER_EXT)
33 #include GR_GL_PLATFORM_HEADER_EXT
34#endif
35
36#if defined(GR_GL_PLATFORM_HEADER2)
37 #include GR_GL_PLATFORM_HEADER2
38#endif
39
40#if defined(GR_GL_PLATFORM_HEADER_EXT2)
41 #include GR_GL_PLATFORM_HEADER_EXT2
42#endif
43
twiz@google.com59a190b2011-03-14 21:23:01 +000044#if defined(GR_GL_PROC_ADDRESS_HEADER)
45 #include GR_GL_PROC_ADDRESS_HEADER
46#endif
47
48#if !defined(GR_GL_PROC_ADDRESS)
49 #error "Must define GR_GL_PROC_ADDRESS"
50#endif
51
52#define GR_GL_GET_PROC(PROC_NAME) \
53 glBindings->f##PROC_NAME = \
54 reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>( \
55 GR_GL_PROC_ADDRESS(gl##PROC_NAME)); \
56 GrAssert(NULL != glBindings->f##PROC_NAME && \
57 "Missing GL binding: " #PROC_NAME);
58
59#define GR_GL_GET_PROC_SUFFIX(PROC_NAME, SUFFIX) \
60 glBindings->f##PROC_NAME = \
61 reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>( \
62 GR_GL_PROC_ADDRESS(gl##PROC_NAME##SUFFIX)); \
63 GrAssert(NULL != glBindings->f##PROC_NAME && \
64 "Missing GL binding: " #PROC_NAME);
65
66#define GR_GL_GET_PROC_SYMBOL(PROC_NAME) \
67 glBindings->f##PROC_NAME = reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>(gl##PROC_NAME);
68
69namespace {
70
71void gl_version_from_string(int* major, int* minor,
72 const char* versionString) {
73 if (NULL == versionString) {
74 GrAssert(0);
75 *major = 0;
76 *minor = 0;
77 return;
78 }
twiz@google.com0f31ca72011-03-18 17:38:11 +000079
twiz@google.com59a190b2011-03-14 21:23:01 +000080 int n = sscanf(versionString, "%d.%d", major, minor);
twiz@google.com0f31ca72011-03-18 17:38:11 +000081 if (2 == n) {
82 return;
twiz@google.com59a190b2011-03-14 21:23:01 +000083 }
twiz@google.com0f31ca72011-03-18 17:38:11 +000084
twiz@google.com59a190b2011-03-14 21:23:01 +000085 char profile[2];
twiz@google.com0f31ca72011-03-18 17:38:11 +000086 n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
87 major, minor);
twiz@google.com59a190b2011-03-14 21:23:01 +000088 bool ok = 4 == n;
89 if (!ok) {
twiz@google.com0f31ca72011-03-18 17:38:11 +000090 n = sscanf(versionString, "OpenGL ES %d.%d", major, minor);
twiz@google.com59a190b2011-03-14 21:23:01 +000091 ok = 2 == n;
92 }
twiz@google.com0f31ca72011-03-18 17:38:11 +000093
twiz@google.com59a190b2011-03-14 21:23:01 +000094 if (!ok) {
95 GrAssert(0);
96 *major = 0;
97 *minor = 0;
98 return;
99 }
twiz@google.com59a190b2011-03-14 21:23:01 +0000100}
101
102bool has_gl_extension_from_string(const char* ext,
103 const char* extensionString) {
104 int extLength = strlen(ext);
105
106 while (true) {
107 int n = strcspn(extensionString, " ");
108 if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
109 return true;
110 }
111 if (0 == extensionString[n]) {
112 return false;
113 }
114 extensionString += n+1;
115 }
116
117 return false;
118}
119
120GrGLInterface* gGLInterface = NULL;
121
122void InitializeGLInterfaceExtensions(GrGLInterface* glBindings) {
123 int major, minor;
124 const char* versionString = reinterpret_cast<const char*>(
125 glBindings->fGetString(GL_VERSION));
126 const char* extensionString = reinterpret_cast<const char*>(
127 glBindings->fGetString(GL_EXTENSIONS));
128 gl_version_from_string(&major, &minor, versionString);
129
130 bool fboFound = false;
131#if GR_SUPPORT_GLDESKTOP
132 if (major >= 3 || has_gl_extension_from_string("GL_ARB_framebuffer_object",
133 extensionString)) {
134 // GL_ARB_framebuffer_object doesn't use ARB suffix.
135 GR_GL_GET_PROC(GenFramebuffers);
136 GR_GL_GET_PROC(BindFramebuffer);
137 GR_GL_GET_PROC(FramebufferTexture2D);
138 GR_GL_GET_PROC(CheckFramebufferStatus);
139 GR_GL_GET_PROC(DeleteFramebuffers);
140 GR_GL_GET_PROC(RenderbufferStorage);
141 GR_GL_GET_PROC(GenRenderbuffers);
142 GR_GL_GET_PROC(DeleteRenderbuffers);
143 GR_GL_GET_PROC(FramebufferRenderbuffer);
144 GR_GL_GET_PROC(BindRenderbuffer);
145 GR_GL_GET_PROC(RenderbufferStorageMultisample);
146 GR_GL_GET_PROC(BlitFramebuffer);
147 fboFound = true;
148 }
149
150 #if GL_EXT_framebuffer_object && !GR_MAC_BUILD
151 if (!fboFound &&
152 has_gl_extension_from_string("GL_EXT_framebuffer_object",
153 extensionString)) {
154 GR_GL_GET_PROC_SUFFIX(GenFramebuffers, EXT);
155 GR_GL_GET_PROC_SUFFIX(BindFramebuffer, EXT);
156 GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, EXT);
157 GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, EXT);
158 GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, EXT);
159 GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, EXT);
160 GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, EXT);
161 GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, EXT);
162 GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT);
163 GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, EXT);
164 fboFound = true;
165
166 if (has_gl_extension_from_string("GL_EXT_framebuffer_multisample",
167 extensionString)) {
168 GR_GL_GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT);
169 }
170 if (has_gl_extension_from_string("GL_EXT_framebuffer_blit",
171 extensionString)) {
172 GR_GL_GET_PROC_SUFFIX(BlitFramebuffer, EXT);
173 }
174 }
175 #endif
176
177 // we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5)
178 GrAssert((major == 1 && minor >= 5) || major >=2);
179 GR_GL_GET_PROC(MapBuffer);
180 GR_GL_GET_PROC(UnmapBuffer);
181#else // !GR_SUPPORT_GLDESKTOP
182 #if GR_SUPPORT_GLES2
183 if (!fboFound && major >= 2) {// ES 2.0 supports FBO
184 GR_GL_GET_PROC(GenFramebuffers);
185 GR_GL_GET_PROC(BindFramebuffer);
186 GR_GL_GET_PROC(FramebufferTexture2D);
187 GR_GL_GET_PROC(CheckFramebufferStatus);
188 GR_GL_GET_PROC(DeleteFramebuffers);
189 GR_GL_GET_PROC(RenderbufferStorage);
190 GR_GL_GET_PROC(GenRenderbuffers);
191 GR_GL_GET_PROC(DeleteRenderbuffers);
192 GR_GL_GET_PROC(FramebufferRenderbuffer);
193 GR_GL_GET_PROC(BindRenderbuffer);
194 fboFound = true;
195 }
196 #endif
197
twiz@google.com0f31ca72011-03-18 17:38:11 +0000198 #if GL_OES_framebuffer_object
twiz@google.com59a190b2011-03-14 21:23:01 +0000199 if (!fboFound &&
200 has_gl_extension_from_string("GL_OES_framebuffer_object",
201 extensionString)) {
202 GR_GL_GET_PROC_SUFFIX(GenFramebuffers, OES);
203 GR_GL_GET_PROC_SUFFIX(BindFramebuffer, OES);
204 GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, OES);
205 GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, OES);
206 GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, OES);
207 GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, OES);
208 GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, OES);
209 GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, OES);
210 GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, OES);
211 GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, OES);
212 fboFound = true;
213 }
214 #endif
215
216 #if GL_APPLE_framebuffer_multisample
217 if (has_gl_extension_from_string("GL_APPLE_framebuffer_multisample",
218 extensionString)) {
219 GR_GL_GET_PROC_SUFFIX(ResolveMultisampleFramebuffer, APPLE);
220 }
221 #endif
222
223 #if GL_IMG_multisampled_render_to_texture
224 if (has_gl_extension_from_string(
225 "GL_IMG_multisampled_render_to_texture", extensionString)) {
226 GR_GL_GET_PROC_SUFFIX(FramebufferTexture2DMultisample, IMG);
227 }
228 #endif
229
230 #if GL_OES_mapbuffer
231 if (has_gl_extension_from_string("GL_OES_mapbuffer", extensionString)) {
232 GR_GL_GET_PROC_SUFFIX(MapBuffer, OES);
233 GR_GL_GET_PROC_SUFFIX(UnmapBuffer, OES);
234 }
235 #endif
236#endif // !GR_SUPPORT_GLDESKTOP
237
238 if (!fboFound) {
239 // we require some form of FBO
240 GrAssert(!"No FBOs supported?");
241 }
242}
243
244void GrGLInitializeGLInterface(GrGLInterface* glBindings) {
245 Gr_bzero(glBindings, sizeof(GrGLInterface));
246
twiz@google.comb65e0cb2011-03-18 20:41:44 +0000247 // Indicate the type of the exported GL functions based on macros
248 // pulled in from the platform includes.
249#if GR_SUPPORT_GLDESKTOP
250 glBindings->fBindingsExported = kDesktop_GrGLBinding;
251#endif
252
253#if GR_SUPPORT_GLES1 && !GR_SUPPORT_GLES2
254 glBindings->fBindingsExported = kES1_GrGLBinding;
255#endif
256
257#if GR_SUPPORT_GLES2
258 glBindings->fBindingsExported = kES2_GrGLBinding;
259#endif
260
twiz@google.comdc008e12011-03-15 16:12:21 +0000261#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES1
twiz@google.com59a190b2011-03-14 21:23:01 +0000262 // These entry points only exist on desktop GL implementations.
263 GR_GL_GET_PROC_SYMBOL(Color4ub);
264 GR_GL_GET_PROC_SYMBOL(ColorPointer);
265 GR_GL_GET_PROC_SYMBOL(DisableClientState);
266 GR_GL_GET_PROC_SYMBOL(EnableClientState);
267 GR_GL_GET_PROC_SYMBOL(LoadMatrixf);
268 GR_GL_GET_PROC_SYMBOL(MatrixMode);
269 GR_GL_GET_PROC_SYMBOL(PointSize);
270 GR_GL_GET_PROC_SYMBOL(ShadeModel);
271 GR_GL_GET_PROC_SYMBOL(TexCoordPointer);
272 GR_GL_GET_PROC_SYMBOL(TexEnvi);
273 GR_GL_GET_PROC_SYMBOL(VertexPointer);
274 GR_GL_GET_PROC(ClientActiveTexture);
275#endif
276
277 // The following gl entry points are part of GL 1.1, and will always be
278 // exported as symbols.
279 // Note that on windows, the wglGetProcAddress call will fail to retrieve
280 // these entry points.
281 GR_GL_GET_PROC_SYMBOL(BlendFunc);
282 GR_GL_GET_PROC_SYMBOL(Clear);
283 GR_GL_GET_PROC_SYMBOL(ClearColor);
284 GR_GL_GET_PROC_SYMBOL(ClearStencil);
285 GR_GL_GET_PROC_SYMBOL(ColorMask);
286 GR_GL_GET_PROC_SYMBOL(CullFace);
287 GR_GL_GET_PROC_SYMBOL(DeleteTextures);
288 GR_GL_GET_PROC_SYMBOL(DepthMask);
289 GR_GL_GET_PROC_SYMBOL(Disable);
290 GR_GL_GET_PROC_SYMBOL(DrawArrays);
291 GR_GL_GET_PROC_SYMBOL(DrawElements);
292 GR_GL_GET_PROC_SYMBOL(Enable);
293 GR_GL_GET_PROC_SYMBOL(FrontFace);
294 GR_GL_GET_PROC_SYMBOL(GenTextures);
295 GR_GL_GET_PROC_SYMBOL(GetError);
296 GR_GL_GET_PROC_SYMBOL(GetIntegerv);
297 GR_GL_GET_PROC_SYMBOL(GetString);
298 GR_GL_GET_PROC_SYMBOL(LineWidth);
299 GR_GL_GET_PROC_SYMBOL(PixelStorei);
300 GR_GL_GET_PROC_SYMBOL(ReadPixels);
301 GR_GL_GET_PROC_SYMBOL(Scissor);
302 GR_GL_GET_PROC_SYMBOL(StencilFunc);
303 GR_GL_GET_PROC_SYMBOL(StencilMask);
304 GR_GL_GET_PROC_SYMBOL(StencilOp);
305 GR_GL_GET_PROC_SYMBOL(TexImage2D);
306 GR_GL_GET_PROC_SYMBOL(TexParameteri);
307 GR_GL_GET_PROC_SYMBOL(TexSubImage2D);
308 GR_GL_GET_PROC_SYMBOL(Viewport);
309
310 // Capture the remaining entry points as gl extensions.
311 GR_GL_GET_PROC(ActiveTexture);
312 GR_GL_GET_PROC(AttachShader);
313 GR_GL_GET_PROC(BindAttribLocation);
314 GR_GL_GET_PROC(BindBuffer);
315 GR_GL_GET_PROC(BindTexture);
bsalomon@google.com080773c2011-03-15 19:09:25 +0000316 GR_GL_GET_PROC(BlendColor);
twiz@google.com59a190b2011-03-14 21:23:01 +0000317 GR_GL_GET_PROC(BufferData);
318 GR_GL_GET_PROC(BufferSubData);
319 GR_GL_GET_PROC(CompileShader);
320 GR_GL_GET_PROC(CompressedTexImage2D);
321 GR_GL_GET_PROC(CreateProgram);
322 GR_GL_GET_PROC(CreateShader);
323 GR_GL_GET_PROC(DeleteBuffers);
324 GR_GL_GET_PROC(DeleteProgram);
325 GR_GL_GET_PROC(DeleteShader);
326 GR_GL_GET_PROC(DisableVertexAttribArray);
327 GR_GL_GET_PROC(EnableVertexAttribArray);
328 GR_GL_GET_PROC(GenBuffers);
329 GR_GL_GET_PROC(GetBufferParameteriv);
330 GR_GL_GET_PROC(GetProgramInfoLog);
331 GR_GL_GET_PROC(GetProgramiv);
332 GR_GL_GET_PROC(GetShaderInfoLog);
333 GR_GL_GET_PROC(GetShaderiv);
334 GR_GL_GET_PROC(GetUniformLocation);
335 GR_GL_GET_PROC(LinkProgram);
336 GR_GL_GET_PROC(ShaderSource);
337 GR_GL_GET_PROC(StencilFuncSeparate);
338 GR_GL_GET_PROC(StencilMaskSeparate);
339 GR_GL_GET_PROC(StencilOpSeparate);
340 GR_GL_GET_PROC(Uniform1fv);
341 GR_GL_GET_PROC(Uniform1i);
342 GR_GL_GET_PROC(Uniform4fv);
343 GR_GL_GET_PROC(UniformMatrix3fv);
344 GR_GL_GET_PROC(UseProgram);
345 GR_GL_GET_PROC(VertexAttrib4fv);
346 GR_GL_GET_PROC(VertexAttribPointer);
347
348 InitializeGLInterfaceExtensions(glBindings);
349}
350
351} // unnamed namespace
352
353void GrGLSetGLInterface(GrGLInterface* gl_interface) {
354 gGLInterface = gl_interface;
355}
356
357GrGLInterface* GrGLGetGLInterface() {
358 return gGLInterface;
359}
360
361void GrGLSetDefaultGLInterface() {
362 static GrGLInterface gDefaultInterface;
363 static bool gDefaultInitialized = false;
364 GrAssert(!gDefaultInitialized);
365
366 if (!gDefaultInitialized) {
367 GrGLInitializeGLInterface(&gDefaultInterface);
368 GrGLSetGLInterface(&gDefaultInterface);
369 }
370}
371
372bool has_gl_extension(const char* ext) {
373 const char* glstr = reinterpret_cast<const char*>(
374 GrGLGetGLInterface()->fGetString(GL_EXTENSIONS));
375
376 return has_gl_extension_from_string(ext, glstr);
377}
378
379void gl_version(int* major, int* minor) {
380 const char* v = reinterpret_cast<const char*>(
381 GrGLGetGLInterface()->fGetString(GL_VERSION));
382 gl_version_from_string(major, minor, v);
383}