blob: 4d726047bbf1c45cb61a7368e266ae46f4726bcd [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.comdc008e12011-03-15 16:12:21 +0000247#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES1
twiz@google.com59a190b2011-03-14 21:23:01 +0000248 // These entry points only exist on desktop GL implementations.
249 GR_GL_GET_PROC_SYMBOL(Color4ub);
250 GR_GL_GET_PROC_SYMBOL(ColorPointer);
251 GR_GL_GET_PROC_SYMBOL(DisableClientState);
252 GR_GL_GET_PROC_SYMBOL(EnableClientState);
253 GR_GL_GET_PROC_SYMBOL(LoadMatrixf);
254 GR_GL_GET_PROC_SYMBOL(MatrixMode);
255 GR_GL_GET_PROC_SYMBOL(PointSize);
256 GR_GL_GET_PROC_SYMBOL(ShadeModel);
257 GR_GL_GET_PROC_SYMBOL(TexCoordPointer);
258 GR_GL_GET_PROC_SYMBOL(TexEnvi);
259 GR_GL_GET_PROC_SYMBOL(VertexPointer);
260 GR_GL_GET_PROC(ClientActiveTexture);
261#endif
262
263 // The following gl entry points are part of GL 1.1, and will always be
264 // exported as symbols.
265 // Note that on windows, the wglGetProcAddress call will fail to retrieve
266 // these entry points.
267 GR_GL_GET_PROC_SYMBOL(BlendFunc);
268 GR_GL_GET_PROC_SYMBOL(Clear);
269 GR_GL_GET_PROC_SYMBOL(ClearColor);
270 GR_GL_GET_PROC_SYMBOL(ClearStencil);
271 GR_GL_GET_PROC_SYMBOL(ColorMask);
272 GR_GL_GET_PROC_SYMBOL(CullFace);
273 GR_GL_GET_PROC_SYMBOL(DeleteTextures);
274 GR_GL_GET_PROC_SYMBOL(DepthMask);
275 GR_GL_GET_PROC_SYMBOL(Disable);
276 GR_GL_GET_PROC_SYMBOL(DrawArrays);
277 GR_GL_GET_PROC_SYMBOL(DrawElements);
278 GR_GL_GET_PROC_SYMBOL(Enable);
279 GR_GL_GET_PROC_SYMBOL(FrontFace);
280 GR_GL_GET_PROC_SYMBOL(GenTextures);
281 GR_GL_GET_PROC_SYMBOL(GetError);
282 GR_GL_GET_PROC_SYMBOL(GetIntegerv);
283 GR_GL_GET_PROC_SYMBOL(GetString);
284 GR_GL_GET_PROC_SYMBOL(LineWidth);
285 GR_GL_GET_PROC_SYMBOL(PixelStorei);
286 GR_GL_GET_PROC_SYMBOL(ReadPixels);
287 GR_GL_GET_PROC_SYMBOL(Scissor);
288 GR_GL_GET_PROC_SYMBOL(StencilFunc);
289 GR_GL_GET_PROC_SYMBOL(StencilMask);
290 GR_GL_GET_PROC_SYMBOL(StencilOp);
291 GR_GL_GET_PROC_SYMBOL(TexImage2D);
292 GR_GL_GET_PROC_SYMBOL(TexParameteri);
293 GR_GL_GET_PROC_SYMBOL(TexSubImage2D);
294 GR_GL_GET_PROC_SYMBOL(Viewport);
295
296 // Capture the remaining entry points as gl extensions.
297 GR_GL_GET_PROC(ActiveTexture);
298 GR_GL_GET_PROC(AttachShader);
299 GR_GL_GET_PROC(BindAttribLocation);
300 GR_GL_GET_PROC(BindBuffer);
301 GR_GL_GET_PROC(BindTexture);
bsalomon@google.com080773c2011-03-15 19:09:25 +0000302 GR_GL_GET_PROC(BlendColor);
twiz@google.com59a190b2011-03-14 21:23:01 +0000303 GR_GL_GET_PROC(BufferData);
304 GR_GL_GET_PROC(BufferSubData);
305 GR_GL_GET_PROC(CompileShader);
306 GR_GL_GET_PROC(CompressedTexImage2D);
307 GR_GL_GET_PROC(CreateProgram);
308 GR_GL_GET_PROC(CreateShader);
309 GR_GL_GET_PROC(DeleteBuffers);
310 GR_GL_GET_PROC(DeleteProgram);
311 GR_GL_GET_PROC(DeleteShader);
312 GR_GL_GET_PROC(DisableVertexAttribArray);
313 GR_GL_GET_PROC(EnableVertexAttribArray);
314 GR_GL_GET_PROC(GenBuffers);
315 GR_GL_GET_PROC(GetBufferParameteriv);
316 GR_GL_GET_PROC(GetProgramInfoLog);
317 GR_GL_GET_PROC(GetProgramiv);
318 GR_GL_GET_PROC(GetShaderInfoLog);
319 GR_GL_GET_PROC(GetShaderiv);
320 GR_GL_GET_PROC(GetUniformLocation);
321 GR_GL_GET_PROC(LinkProgram);
322 GR_GL_GET_PROC(ShaderSource);
323 GR_GL_GET_PROC(StencilFuncSeparate);
324 GR_GL_GET_PROC(StencilMaskSeparate);
325 GR_GL_GET_PROC(StencilOpSeparate);
326 GR_GL_GET_PROC(Uniform1fv);
327 GR_GL_GET_PROC(Uniform1i);
328 GR_GL_GET_PROC(Uniform4fv);
329 GR_GL_GET_PROC(UniformMatrix3fv);
330 GR_GL_GET_PROC(UseProgram);
331 GR_GL_GET_PROC(VertexAttrib4fv);
332 GR_GL_GET_PROC(VertexAttribPointer);
333
334 InitializeGLInterfaceExtensions(glBindings);
335}
336
337} // unnamed namespace
338
339void GrGLSetGLInterface(GrGLInterface* gl_interface) {
340 gGLInterface = gl_interface;
341}
342
343GrGLInterface* GrGLGetGLInterface() {
344 return gGLInterface;
345}
346
347void GrGLSetDefaultGLInterface() {
348 static GrGLInterface gDefaultInterface;
349 static bool gDefaultInitialized = false;
350 GrAssert(!gDefaultInitialized);
351
352 if (!gDefaultInitialized) {
353 GrGLInitializeGLInterface(&gDefaultInterface);
354 GrGLSetGLInterface(&gDefaultInterface);
355 }
356}
357
358bool has_gl_extension(const char* ext) {
359 const char* glstr = reinterpret_cast<const char*>(
360 GrGLGetGLInterface()->fGetString(GL_EXTENSIONS));
361
362 return has_gl_extension_from_string(ext, glstr);
363}
364
365void gl_version(int* major, int* minor) {
366 const char* v = reinterpret_cast<const char*>(
367 GrGLGetGLInterface()->fGetString(GL_VERSION));
368 gl_version_from_string(major, minor, v);
369}