GrGLInterface.cpp revision 096defe64d408e54474fe19f418c95bf1a554fc7
1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9#include "gl/GrGLInterface.h"
10#include "gl/GrGLExtensions.h"
11#include "gl/GrGLUtil.h"
12
13#include <stdio.h>
14
15SK_DEFINE_INST_COUNT(GrGLInterface)
16
17#if GR_GL_PER_GL_FUNC_CALLBACK
18namespace {
19void GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
20}
21#endif
22
23GrGLInterface::GrGLInterface() {
24    fBindingsExported = kNone_GrGLBinding;
25
26#if GR_GL_PER_GL_FUNC_CALLBACK
27    fCallback = GrGLDefaultInterfaceCallback;
28    fCallbackData = 0;
29#endif
30}
31
32bool GrGLInterface::validate(GrGLBinding binding) const {
33
34    // kNone must be 0 so that the check we're about to do can never succeed if
35    // binding == kNone.
36    GR_STATIC_ASSERT(kNone_GrGLBinding == 0);
37
38    if (0 == (binding & fBindingsExported)) {
39        return false;
40    }
41
42    GrGLExtensions extensions;
43    if (!extensions.init(binding, this)) {
44        return false;
45    }
46
47    // functions that are always required
48    if (NULL == fActiveTexture ||
49        NULL == fAttachShader ||
50        NULL == fBindAttribLocation ||
51        NULL == fBindBuffer ||
52        NULL == fBindTexture ||
53        NULL == fBlendFunc ||
54        NULL == fBlendColor ||      // -> GL >= 1.4, ES >= 2.0 or extension
55        NULL == fBufferData ||
56        NULL == fBufferSubData ||
57        NULL == fClear ||
58        NULL == fClearColor ||
59        NULL == fClearStencil ||
60        NULL == fColorMask ||
61        NULL == fCompileShader ||
62        NULL == fCreateProgram ||
63        NULL == fCreateShader ||
64        NULL == fCullFace ||
65        NULL == fDeleteBuffers ||
66        NULL == fDeleteProgram ||
67        NULL == fDeleteShader ||
68        NULL == fDeleteTextures ||
69        NULL == fDepthMask ||
70        NULL == fDisable ||
71        NULL == fDisableVertexAttribArray ||
72        NULL == fDrawArrays ||
73        NULL == fDrawElements ||
74        NULL == fEnable ||
75        NULL == fEnableVertexAttribArray ||
76        NULL == fFrontFace ||
77        NULL == fGenBuffers ||
78        NULL == fGenTextures ||
79        NULL == fGetBufferParameteriv ||
80        NULL == fGetError ||
81        NULL == fGetIntegerv ||
82        NULL == fGetProgramInfoLog ||
83        NULL == fGetProgramiv ||
84        NULL == fGetShaderInfoLog ||
85        NULL == fGetShaderiv ||
86        NULL == fGetString ||
87        NULL == fGetUniformLocation ||
88        NULL == fLinkProgram ||
89        NULL == fPixelStorei ||
90        NULL == fReadPixels ||
91        NULL == fScissor ||
92        NULL == fShaderSource ||
93        NULL == fStencilFunc ||
94        NULL == fStencilMask ||
95        NULL == fStencilOp ||
96        NULL == fTexImage2D ||
97        NULL == fTexParameteri ||
98        NULL == fTexParameteriv ||
99        NULL == fTexSubImage2D ||
100        NULL == fUniform1f ||
101        NULL == fUniform1i ||
102        NULL == fUniform1fv ||
103        NULL == fUniform1iv ||
104        NULL == fUniform2f ||
105        NULL == fUniform2i ||
106        NULL == fUniform2fv ||
107        NULL == fUniform2iv ||
108        NULL == fUniform3f ||
109        NULL == fUniform3i ||
110        NULL == fUniform3fv ||
111        NULL == fUniform3iv ||
112        NULL == fUniform4f ||
113        NULL == fUniform4i ||
114        NULL == fUniform4fv ||
115        NULL == fUniform4iv ||
116        NULL == fUniformMatrix2fv ||
117        NULL == fUniformMatrix3fv ||
118        NULL == fUniformMatrix4fv ||
119        NULL == fUseProgram ||
120        NULL == fVertexAttrib4fv ||
121        NULL == fVertexAttribPointer ||
122        NULL == fViewport ||
123        NULL == fBindFramebuffer ||
124        NULL == fBindRenderbuffer ||
125        NULL == fCheckFramebufferStatus ||
126        NULL == fDeleteFramebuffers ||
127        NULL == fDeleteRenderbuffers ||
128        NULL == fFinish ||
129        NULL == fFlush ||
130        NULL == fFramebufferRenderbuffer ||
131        NULL == fFramebufferTexture2D ||
132        NULL == fGetFramebufferAttachmentParameteriv ||
133        NULL == fGetRenderbufferParameteriv ||
134        NULL == fGenFramebuffers ||
135        NULL == fGenRenderbuffers ||
136        NULL == fRenderbufferStorage) {
137        return false;
138    }
139
140    GrGLVersion glVer = GrGLGetVersion(this);
141
142    // Now check that baseline ES/Desktop fns not covered above are present
143    // and that we have fn pointers for any advertised extensions that we will
144    // try to use.
145
146    // these functions are part of ES2, we assume they are available
147    // On the desktop we assume they are available if the extension
148    // is present or GL version is high enough.
149    if (kES2_GrGLBinding == binding) {
150        if (NULL == fStencilFuncSeparate ||
151            NULL == fStencilMaskSeparate ||
152            NULL == fStencilOpSeparate) {
153            return false;
154        }
155    } else if (kDesktop_GrGLBinding == binding) {
156
157        if (glVer >= GR_GL_VER(2,0)) {
158            if (NULL == fStencilFuncSeparate ||
159                NULL == fStencilMaskSeparate ||
160                NULL == fStencilOpSeparate) {
161                return false;
162            }
163        }
164        if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
165            return false;
166        }
167        if (glVer >= GR_GL_VER(2,0) || extensions.has("GL_ARB_draw_buffers")) {
168            if (NULL == fDrawBuffers) {
169                return false;
170            }
171        }
172
173        if (glVer >= GR_GL_VER(1,5) || extensions.has("GL_ARB_occlusion_query")) {
174            if (NULL == fGenQueries ||
175                NULL == fDeleteQueries ||
176                NULL == fBeginQuery ||
177                NULL == fEndQuery ||
178                NULL == fGetQueryiv ||
179                NULL == fGetQueryObjectiv ||
180                NULL == fGetQueryObjectuiv) {
181                return false;
182            }
183        }
184        if (glVer >= GR_GL_VER(3,3) ||
185            extensions.has("GL_ARB_timer_query") ||
186            extensions.has("GL_EXT_timer_query")) {
187            if (NULL == fGetQueryObjecti64v ||
188                NULL == fGetQueryObjectui64v) {
189                return false;
190            }
191        }
192        if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
193            if (NULL == fQueryCounter) {
194                return false;
195            }
196        }
197        // The below two blocks are checks for functions used with
198        // GL_NV_path_rendering. We're not enforcing that they be non-NULL
199        // because they aren't actually called at this time.
200        if (false &&
201            (NULL == fMatrixMode ||
202             NULL == fLoadIdentity ||
203             NULL == fLoadMatrixf)) {
204            return false;
205        }
206        if (false && extensions.has("GL_NV_path_rendering")) {
207            if (NULL == fPathCommands ||
208                NULL == fPathCoords ||
209                NULL == fPathSubCommands ||
210                NULL == fPathSubCoords ||
211                NULL == fPathString ||
212                NULL == fPathGlyphs ||
213                NULL == fPathGlyphRange ||
214                NULL == fWeightPaths ||
215                NULL == fCopyPath ||
216                NULL == fInterpolatePaths ||
217                NULL == fTransformPath ||
218                NULL == fPathParameteriv ||
219                NULL == fPathParameteri ||
220                NULL == fPathParameterfv ||
221                NULL == fPathParameterf ||
222                NULL == fPathDashArray ||
223                NULL == fGenPaths ||
224                NULL == fDeletePaths ||
225                NULL == fIsPath ||
226                NULL == fPathStencilFunc ||
227                NULL == fPathStencilDepthOffset ||
228                NULL == fStencilFillPath ||
229                NULL == fStencilStrokePath ||
230                NULL == fStencilFillPathInstanced ||
231                NULL == fStencilStrokePathInstanced ||
232                NULL == fPathCoverDepthFunc ||
233                NULL == fPathColorGen ||
234                NULL == fPathTexGen ||
235                NULL == fPathFogGen ||
236                NULL == fCoverFillPath ||
237                NULL == fCoverStrokePath ||
238                NULL == fCoverFillPathInstanced ||
239                NULL == fCoverStrokePathInstanced ||
240                NULL == fGetPathParameteriv ||
241                NULL == fGetPathParameterfv ||
242                NULL == fGetPathCommands ||
243                NULL == fGetPathCoords ||
244                NULL == fGetPathDashArray ||
245                NULL == fGetPathMetrics ||
246                NULL == fGetPathMetricRange ||
247                NULL == fGetPathSpacing ||
248                NULL == fGetPathColorGeniv ||
249                NULL == fGetPathColorGenfv ||
250                NULL == fGetPathTexGeniv ||
251                NULL == fGetPathTexGenfv ||
252                NULL == fIsPointInFillPath ||
253                NULL == fIsPointInStrokePath ||
254                NULL == fGetPathLength ||
255                NULL == fPointAlongPath) {
256                return false;
257            }
258        }
259    }
260
261    // optional function on desktop before 1.3
262    if (kDesktop_GrGLBinding != binding ||
263        (glVer >= GR_GL_VER(1,3)) ||
264        extensions.has("GL_ARB_texture_compression")) {
265        if (NULL == fCompressedTexImage2D) {
266            return false;
267        }
268    }
269
270    // part of desktop GL, but not ES
271    if (kDesktop_GrGLBinding == binding &&
272        (NULL == fLineWidth ||
273         NULL == fGetTexLevelParameteriv ||
274         NULL == fDrawBuffer ||
275         NULL == fReadBuffer)) {
276        return false;
277    }
278
279    // GL_EXT_texture_storage is part of desktop 4.2
280    // There is a desktop ARB extension and an ES+desktop EXT extension
281    if (kDesktop_GrGLBinding == binding) {
282        if (glVer >= GR_GL_VER(4,2) ||
283            extensions.has("GL_ARB_texture_storage") ||
284            extensions.has("GL_EXT_texture_storage")) {
285            if (NULL == fTexStorage2D) {
286                return false;
287            }
288        }
289    } else if (extensions.has("GL_EXT_texture_storage")) {
290        if (NULL == fTexStorage2D) {
291            return false;
292        }
293    }
294
295    // FBO MSAA
296    if (kDesktop_GrGLBinding == binding) {
297        // GL 3.0 and the ARB extension have multisample + blit
298        if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
299            if (NULL == fRenderbufferStorageMultisample ||
300                NULL == fBlitFramebuffer) {
301                return false;
302            }
303        } else {
304            if (extensions.has("GL_EXT_framebuffer_blit") &&
305                NULL == fBlitFramebuffer) {
306                return false;
307            }
308            if (extensions.has("GL_EXT_framebuffer_multisample") &&
309                NULL == fRenderbufferStorageMultisample) {
310                return false;
311            }
312        }
313    } else {
314        if (extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
315            if (NULL == fRenderbufferStorageMultisample ||
316                NULL == fBlitFramebuffer) {
317                return false;
318            }
319        }
320        if (extensions.has("GL_APPLE_framebuffer_multisample")) {
321            if (NULL == fRenderbufferStorageMultisample ||
322                NULL == fResolveMultisampleFramebuffer) {
323                return false;
324            }
325        }
326        if (extensions.has("GL_IMG_multisampled_render_to_texture")) {
327            if (NULL == fRenderbufferStorageMultisample ||
328                NULL == fFramebufferTexture2DMultisample) {
329                return false;
330            }
331        }
332    }
333
334    // On ES buffer mapping is an extension. On Desktop
335    // buffer mapping was part of original VBO extension
336    // which we require.
337    if (kDesktop_GrGLBinding == binding || extensions.has("GL_OES_mapbuffer")) {
338        if (NULL == fMapBuffer ||
339            NULL == fUnmapBuffer) {
340            return false;
341        }
342    }
343
344    // Dual source blending
345    if (kDesktop_GrGLBinding == binding &&
346        (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_blend_func_extended"))) {
347        if (NULL == fBindFragDataLocationIndexed) {
348            return false;
349        }
350    }
351
352    if (kDesktop_GrGLBinding == binding && glVer >= GR_GL_VER(3, 0)) {
353        if (NULL == fGetStringi) {
354            return false;
355        }
356    }
357
358    if (kDesktop_GrGLBinding == binding) {
359        if (glVer >= GR_GL_VER(3, 0) || extensions.has("GL_ARB_vertex_array_object")) {
360            if (NULL == fBindVertexArray ||
361                NULL == fDeleteVertexArrays ||
362                NULL == fGenVertexArrays) {
363                return false;
364            }
365        }
366    } else {
367        if (extensions.has("GL_OES_vertex_array_object")) {
368            if (NULL == fBindVertexArray ||
369                NULL == fDeleteVertexArrays ||
370                NULL == fGenVertexArrays) {
371                return false;
372            }
373        }
374    }
375
376    return true;
377}
378