blob: e128d353f00f75211b1fce8bf86afa0308a93c91 [file] [log] [blame]
bsalomon@google.com27847de2011-02-22 20:59:41 +00001/*
2 Copyright 2010 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#include "GrGLConfig.h"
18#include "GrTypes.h"
19#include <stdio.h>
20
21bool has_gl_extension(const char* ext) {
22 const char* glstr = (const char*) glGetString(GL_EXTENSIONS);
23
24 int extLength = strlen(ext);
25
26 while (true) {
27 int n = strcspn(glstr, " ");
28 if (n == extLength && 0 == strncmp(ext, glstr, n)) {
29 return true;
30 }
31 if (0 == glstr[n]) {
32 return false;
33 }
34 glstr += n+1;
35 }
36}
37
38void gl_version(int* major, int* minor) {
39 const char* v = (const char*) glGetString(GL_VERSION);
40 if (NULL == v) {
41 GrAssert(0);
42 *major = 0;
43 *minor = 0;
44 return;
45 }
46#if GR_SUPPORT_GLDESKTOP
47 int n = sscanf(v, "%d.%d", major, minor);
48 if (n != 2) {
49 GrAssert(0);
50 *major = 0;
51 *minor = 0;
52 return;
53 }
54#else
55 char profile[2];
56 int n = sscanf(v, "OpenGL ES-%c%c %d.%d", profile, profile+1, major, minor);
57 bool ok = 4 == n;
58 if (!ok) {
59 int n = sscanf(v, "OpenGL ES %d.%d", major, minor);
60 ok = 2 == n;
61 }
62 if (!ok) {
63 GrAssert(0);
64 *major = 0;
65 *minor = 0;
66 return;
67 }
68#endif
69}
70
71#if defined(GR_GL_PROC_ADDRESS_HEADER)
72 #include GR_GL_PROC_ADDRESS_HEADER
73#endif
74
75typedef void (*glProc)(void);
76
77#define GET_PROC(EXT_STRUCT, PROC_NAME) \
78 *(GrTCast<glProc*>(&(EXT_STRUCT-> PROC_NAME))) = (glProc)GR_GL_PROC_ADDRESS((gl ## PROC_NAME)); \
79 GrAssert(NULL != EXT_STRUCT-> PROC_NAME)
80
81#define GET_SUFFIX_PROC(EXT_STRUCT, PROC_NAME, SUFFIX) \
82 *(GrTCast<glProc*>(&(EXT_STRUCT-> PROC_NAME))) = (glProc)GR_GL_PROC_ADDRESS((gl ## PROC_NAME ## SUFFIX)); \
83 GrAssert(NULL != EXT_STRUCT-> PROC_NAME)
84
85extern void GrGLInitExtensions(GrGLExts* exts) {
86 exts->GenFramebuffers = NULL;
87 exts->BindFramebuffer = NULL;
88 exts->FramebufferTexture2D = NULL;
89 exts->CheckFramebufferStatus = NULL;
90 exts->DeleteFramebuffers = NULL;
91 exts->RenderbufferStorage = NULL;
92 exts->GenRenderbuffers = NULL;
93 exts->DeleteRenderbuffers = NULL;
94 exts->FramebufferRenderbuffer = NULL;
95 exts->BindRenderbuffer = NULL;
96 exts->RenderbufferStorageMultisample = NULL;
97 exts->BlitFramebuffer = NULL;
98 exts->ResolveMultisampleFramebuffer = NULL;
99 exts->FramebufferTexture2DMultisample = NULL;
100 exts->MapBuffer = NULL;
101 exts->UnmapBuffer = NULL;
102
103 GLint major, minor;
104 gl_version(&major, &minor);
105
106 bool fboFound = false;
107#if GR_SUPPORT_GLDESKTOP
108 #if defined(GL_VERSION_3_0) && GL_VERSION_3_0
109 if (!fboFound && major >= 3) { // all of ARB_fbo is in 3.x
110 exts->GenFramebuffers = glGenFramebuffers;
111 exts->BindFramebuffer = glBindFramebuffer;
112 exts->FramebufferTexture2D = glFramebufferTexture2D;
113 exts->CheckFramebufferStatus = glCheckFramebufferStatus;
114 exts->DeleteFramebuffers = glDeleteFramebuffers;
115 exts->RenderbufferStorage = glRenderbufferStorage;
116 exts->GenRenderbuffers = glGenRenderbuffers;
117 exts->DeleteRenderbuffers = glDeleteRenderbuffers;
118 exts->FramebufferRenderbuffer = glFramebufferRenderbuffer;
119 exts->BindRenderbuffer = glBindRenderbuffer;
120 exts->RenderbufferStorageMultisample = glRenderbufferStorageMultisample;
121 exts->BlitFramebuffer = glBlitFramebuffer;
122 fboFound = true;
123 }
124 #endif
125 #if GL_ARB_framebuffer_object
126 if (!fboFound && has_gl_extension("GL_ARB_framebuffer_object")) {
127 // GL_ARB_framebuffer_object doesn't use ARB suffix.
128 GET_PROC(exts, GenFramebuffers);
129 GET_PROC(exts, BindFramebuffer);
130 GET_PROC(exts, FramebufferTexture2D);
131 GET_PROC(exts, CheckFramebufferStatus);
132 GET_PROC(exts, DeleteFramebuffers);
133 GET_PROC(exts, RenderbufferStorage);
134 GET_PROC(exts, GenRenderbuffers);
135 GET_PROC(exts, DeleteRenderbuffers);
136 GET_PROC(exts, FramebufferRenderbuffer);
137 GET_PROC(exts, BindRenderbuffer);
138 GET_PROC(exts, RenderbufferStorageMultisample);
139 GET_PROC(exts, BlitFramebuffer);
140 fboFound = true;
141 }
142 #endif
143 // Mac doesn't declare prototypes for EXT FBO extensions
144 #if GL_EXT_framebuffer_object && !GR_MAC_BUILD
145 if (!fboFound && has_gl_extension("GL_EXT_framebuffer_object")) {
146 GET_SUFFIX_PROC(exts, GenFramebuffers, EXT);
147 GET_SUFFIX_PROC(exts, BindFramebuffer, EXT);
148 GET_SUFFIX_PROC(exts, FramebufferTexture2D, EXT);
149 GET_SUFFIX_PROC(exts, CheckFramebufferStatus, EXT);
150 GET_SUFFIX_PROC(exts, DeleteFramebuffers, EXT);
151 GET_SUFFIX_PROC(exts, RenderbufferStorage, EXT);
152 GET_SUFFIX_PROC(exts, GenRenderbuffers, EXT);
153 GET_SUFFIX_PROC(exts, DeleteRenderbuffers, EXT);
154 GET_SUFFIX_PROC(exts, FramebufferRenderbuffer, EXT);
155 GET_SUFFIX_PROC(exts, BindRenderbuffer, EXT);
156 fboFound = true;
157 // check for fbo ms and fbo blit
158 #if GL_EXT_framebuffer_multisample
159 if (has_gl_extension("GL_EXT_framebuffer_multisample")) {
160 GET_SUFFIX_PROC(exts, RenderbufferStorageMultisample, EXT);
161 }
162 #endif
163 #if GL_EXT_framebuffer_blit
164 if (has_gl_extension("GL_EXT_framebuffer_blit")) {
165 GET_SUFFIX_PROC(exts, BlitFramebuffer, EXT);
166 }
167 #endif
168 }
169 #endif
170 if (!fboFound) {
171 // we require some form of FBO
172 GrAssert(!"No FBOs supported?");
173 }
174 // we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5)
175 exts->MapBuffer = glMapBuffer;
176 exts->UnmapBuffer = glUnmapBuffer;
177#else // !GR_SUPPORT_GLDESKTOP
178 #if GR_SUPPORT_GLES2
179 if (!fboFound && major >= 2) {// ES 2.0 supports FBO
180 exts->GenFramebuffers = glGenFramebuffers;
181 exts->BindFramebuffer = glBindFramebuffer;
182 exts->FramebufferTexture2D = glFramebufferTexture2D;
183 exts->CheckFramebufferStatus = glCheckFramebufferStatus;
184 exts->DeleteFramebuffers = glDeleteFramebuffers;
185 exts->RenderbufferStorage = glRenderbufferStorage;
186 exts->GenRenderbuffers = glGenRenderbuffers;
187 exts->DeleteRenderbuffers = glDeleteRenderbuffers;
188 exts->FramebufferRenderbuffer = glFramebufferRenderbuffer;
189 exts->BindRenderbuffer = glBindRenderbuffer;
190 fboFound = true;
191 }
192 #endif
193 #if GL_OES_framebuffer_object
194 if (!fboFound && has_gl_extension("GL_OES_framebuffer_object")) {
195 GET_SUFFIX_PROC(exts, GenFramebuffers, OES);
196 GET_SUFFIX_PROC(exts, BindFramebuffer, OES);
197 GET_SUFFIX_PROC(exts, FramebufferTexture2D, OES);
198 GET_SUFFIX_PROC(exts, CheckFramebufferStatus, OES);
199 GET_SUFFIX_PROC(exts, DeleteFramebuffers, OES);
200 GET_SUFFIX_PROC(exts, RenderbufferStorage, OES);
201 GET_SUFFIX_PROC(exts, GenRenderbuffers, OES);
202 GET_SUFFIX_PROC(exts, DeleteRenderbuffers, OES);
203 GET_SUFFIX_PROC(exts, FramebufferRenderbuffer, OES);
204 GET_SUFFIX_PROC(exts, BindRenderbuffer, OES);
205 }
206 #endif
207
208 if (!fboFound) {
209 // we require some form of FBO
210 GrAssert(!"No FBOs supported?");
211 }
212
213 #if GL_APPLE_framebuffer_multisample
214 if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
215 GET_SUFFIX_PROC(exts, ResolveMultisampleFramebuffer, APPLE);
216 }
217 #endif
218
219 #if GL_IMG_multisampled_render_to_texture
220 if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) {
221 GET_SUFFIX_PROC(exts, FramebufferTexture2DMultisample, IMG);
222 }
223 #endif
224
225 #if GL_OES_mapbuffer
226 if (has_gl_extension("GL_OES_mapbuffer")) {
227 GET_SUFFIX_PROC(exts, MapBuffer, OES);
228 GET_SUFFIX_PROC(exts, UnmapBuffer, OES);
229 }
230 #endif
231#endif // !GR_SUPPORT_GLDESKTOP
232}
233
234
235///////////////////////////////////////////////////////////////////////////////
236
237void GrGLCheckErr(const char* location, const char* call) {
238 uint32_t err = glGetError();
239 if (GL_NO_ERROR != err) {
240 GrPrintf("---- glGetError %x", err);
241 if (NULL != location) {
242 GrPrintf(" at\n\t%s", location);
243 }
244 if (NULL != call) {
245 GrPrintf("\n\t\t%s", call);
246 }
247 GrPrintf("\n");
248 }
249}
250
251///////////////////////////////////////////////////////////////////////////////
252
253bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START);
254
255bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START);