blob: f961194b7a7dc746746898f5d793a6713e41a33c [file] [log] [blame]
bsalomon@google.com42ab7ea2011-01-19 17:19:40 +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 <stdio.h>
19
20bool has_gl_extension(const char* ext) {
21 const char* glstr = (const char*) glGetString(GL_EXTENSIONS);
22
23 int extLength = strlen(ext);
24
25 while (true) {
26 int n = strcspn(glstr, " ");
27 if (n == extLength && 0 == strncmp(ext, glstr, n)) {
28 return true;
29 }
30 if (0 == glstr[n]) {
31 return false;
32 }
33 glstr += n+1;
34 }
35}
36
37void gl_version(int* major, int* minor) {
38 const char* v = (const char*) glGetString(GL_VERSION);
39 if (NULL == v) {
40 GrAssert(0);
41 *major = 0;
42 *minor = 0;
43 return;
44 }
45#if GR_SUPPORT_GLDESKTOP
46 int n = sscanf(v, "%d.%d", major, minor);
47 if (n != 2) {
48 GrAssert(0);
49 *major = 0;
50 *minor = 0;
51 return;
52 }
53#else
54 char profile[2];
55 int n = sscanf(v, "OpenGL ES-%c%c %d.%d", profile, profile+1, major, minor);
56 bool ok = 4 == n;
57 if (!ok) {
58 int n = sscanf(v, "OpenGL ES %d.%d", major, minor);
59 ok = 2 == n;
60 }
61 if (!ok) {
62 GrAssert(0);
63 *major = 0;
64 *minor = 0;
65 return;
66 }
67#endif
68}
69
70#if defined(GR_GL_PROC_ADDRESS_HEADER)
71 #include GR_GL_PROC_ADDRESS_HEADER
72#endif
73
74typedef void (*glProc)(void);
75
76#define GET_PROC(EXT_STRUCT, PROC_NAME) \
77 *((glProc*) &(EXT_STRUCT-> PROC_NAME)) = (glProc) GR_GL_PROC_ADDRESS((gl ## PROC_NAME)); \
78 GrAssert(NULL != EXT_STRUCT-> PROC_NAME)
79
80#define GET_SUFFIX_PROC(EXT_STRUCT, PROC_NAME, SUFFIX) \
81 *((glProc*) &(EXT_STRUCT-> PROC_NAME)) = (glProc) GR_GL_PROC_ADDRESS((gl ## PROC_NAME ## SUFFIX)); \
82 GrAssert(NULL != EXT_STRUCT-> PROC_NAME)
83
84extern void GrGLInitExtensions(GrGLExts* exts) {
85 exts->GenFramebuffers = NULL;
86 exts->BindFramebuffer = NULL;
87 exts->FramebufferTexture2D = NULL;
88 exts->CheckFramebufferStatus = NULL;
89 exts->DeleteFramebuffers = NULL;
90 exts->RenderbufferStorage = NULL;
91 exts->GenRenderbuffers = NULL;
92 exts->DeleteRenderbuffers = NULL;
93 exts->FramebufferRenderbuffer = NULL;
94 exts->BindRenderbuffer = NULL;
95 exts->RenderbufferStorageMultisample = NULL;
96 exts->BlitFramebuffer = NULL;
97 exts->ResolveMultisampleFramebuffer = NULL;
98 exts->FramebufferTexture2DMultisample = NULL;
99 exts->MapBuffer = NULL;
100 exts->UnmapBuffer = NULL;
101
102 GLint major, minor;
103 gl_version(&major, &minor);
104#if GR_SUPPORT_GLDESKTOP
105
106 bool fboFound = false;
107 #if GL_VERSION_3_0
108 if (!fboFound && major >= 3) { // all of ARB_fbo is in 3.x
109 exts->GenFramebuffers = glGenFramebuffers;
110 exts->BindFramebuffer = glBindFramebuffer;
111 exts->FramebufferTexture2D = glFramebufferTexture2D;
112 exts->CheckFramebufferStatus = glCheckFramebufferStatus;
113 exts->DeleteFramebuffers = glDeleteFramebuffers;
114 exts->RenderbufferStorage = glRenderbufferStorage;
115 exts->GenRenderbuffers = glGenRenderbuffers;
116 exts->DeleteRenderbuffers = glDeleteRenderbuffers;
117 exts->FramebufferRenderbuffer = glFramebufferRenderbuffer;
118 exts->BindRenderbuffer = glBindRenderbuffer;
119 exts->RenderbufferStorageMultisample = glRenderbufferStorageMultisample;
120 exts->BlitFramebuffer = glBlitFramebuffer;
121 fboFound = true;
122 }
123 #endif
124 #if GL_ARB_framebuffer_object
125 if (!fboFound && has_gl_extension("GL_ARB_framebuffer_object")) {
126 // GL_ARB_framebuffer_object doesn't use ARB suffix.
127 GET_PROC(exts, GenFramebuffers);
128 GET_PROC(exts, BindFramebuffer);
129 GET_PROC(exts, FramebufferTexture2D);
130 GET_PROC(exts, CheckFramebufferStatus);
131 GET_PROC(exts, DeleteFramebuffers);
132 GET_PROC(exts, RenderbufferStorage);
133 GET_PROC(exts, GenRenderbuffers);
134 GET_PROC(exts, DeleteRenderbuffers);
135 GET_PROC(exts, FramebufferRenderbuffer);
136 GET_PROC(exts, BindRenderbuffer);
137 GET_PROC(exts, RenderbufferStorageMultisample);
138 GET_PROC(exts, BlitFramebuffer);
139 fboFound = true;
140 }
141 #endif
142 // Mac doesn't declare prototypes for EXT FBO extensions
143 #if GL_EXT_framebuffer_object && !GR_MAC_BUILD
144 if (!fboFound && has_gl_extension("GL_EXT_framebuffer_object")) {
145 GET_SUFFIX_PROC(exts, GenFramebuffers, EXT);
146 GET_SUFFIX_PROC(exts, BindFramebuffer, EXT);
147 GET_SUFFIX_PROC(exts, FramebufferTexture2D, EXT);
148 GET_SUFFIX_PROC(exts, CheckFramebufferStatus, EXT);
149 GET_SUFFIX_PROC(exts, DeleteFramebuffers, EXT);
150 GET_SUFFIX_PROC(exts, RenderbufferStorage, EXT);
151 GET_SUFFIX_PROC(exts, GenRenderbuffers, EXT);
152 GET_SUFFIX_PROC(exts, DeleteRenderbuffers, EXT);
153 GET_SUFFIX_PROC(exts, FramebufferRenderbuffer, EXT);
154 GET_SUFFIX_PROC(exts, BindRenderbuffer, EXT);
155 fboFound = true;
156 // check for fbo ms and fbo blit
157 #if GL_EXT_framebuffer_multisample
158 if (has_gl_extension("GL_EXT_framebuffer_multisample")) {
159 GET_SUFFIX_PROC(exts, RenderbufferStorageMultisample, EXT);
160 }
161 #endif
162 #if GL_EXT_framebuffer_blit
163 if (has_gl_extension("GL_EXT_framebuffer_blit")) {
164 GET_SUFFIX_PROC(exts, BlitFramebuffer, EXT);
165 }
166 #endif
167 }
168 #endif
169 if (!fboFound) {
170 // we require some form of FBO
171 GrAssert(!"No FBOs supported?");
172 }
173 // we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5)
174 exts->MapBuffer = glMapBuffer;
175 exts->UnmapBuffer = glUnmapBuffer;
176#else // !GR_SUPPORT_GLDESKTOP
177 bool foundFBO = false;
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 gPrintGL = true;
254
255
256