blob: 0c6bd8604d1a0d489652b43b5fa9516a1fc4bb27 [file] [log] [blame]
twiz@google.com59a190b2011-03-14 21:23:01 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * 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.
twiz@google.com59a190b2011-03-14 21:23:01 +00006 */
7
8
tomhudson@google.com6bf38b52012-02-14 15:11:59 +00009#include "gl/GrGLInterface.h"
bsalomon@google.com1744f972013-02-26 21:46:32 +000010#include "gl/GrGLExtensions.h"
11#include "gl/GrGLUtil.h"
twiz@google.com59a190b2011-03-14 21:23:01 +000012
13#include <stdio.h>
14
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000015SK_DEFINE_INST_COUNT(GrGLInterface)
16
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +000017#if GR_GL_PER_GL_FUNC_CALLBACK
18namespace {
19void GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
20}
21#endif
22
bsalomon@google.com0b77d682011-08-19 13:28:54 +000023GrGLInterface::GrGLInterface() {
bsalomon@google.com89ec61e2012-02-10 20:05:18 +000024 fBindingsExported = kNone_GrGLBinding;
bsalomon@google.com0b77d682011-08-19 13:28:54 +000025
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +000026#if GR_GL_PER_GL_FUNC_CALLBACK
27 fCallback = GrGLDefaultInterfaceCallback;
28 fCallbackData = 0;
29#endif
bsalomon@google.com0b77d682011-08-19 13:28:54 +000030}
31
bsalomon@google.com89ec61e2012-02-10 20:05:18 +000032bool GrGLInterface::validate(GrGLBinding binding) const {
bsalomon@google.com0b77d682011-08-19 13:28:54 +000033
bsalomon@google.com89ec61e2012-02-10 20:05:18 +000034 // 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);
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000037
bsalomon@google.com89ec61e2012-02-10 20:05:18 +000038 if (0 == (binding & fBindingsExported)) {
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000039 return false;
40 }
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +000041
bsalomon@google.com1744f972013-02-26 21:46:32 +000042 GrGLExtensions extensions;
43 if (!extensions.init(binding, this)) {
44 return false;
45 }
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000046
47 // functions that are always required
48 if (NULL == fActiveTexture ||
49 NULL == fAttachShader ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000050 NULL == fBindAttribLocation ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000051 NULL == fBindBuffer ||
52 NULL == fBindTexture ||
53 NULL == fBlendFunc ||
robertphillips@google.come7884302012-04-18 14:39:58 +000054 NULL == fBlendColor || // -> GL >= 1.4, ES >= 2.0 or extension
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000055 NULL == fBufferData ||
56 NULL == fBufferSubData ||
57 NULL == fClear ||
58 NULL == fClearColor ||
59 NULL == fClearStencil ||
60 NULL == fColorMask ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000061 NULL == fCompileShader ||
62 NULL == fCreateProgram ||
63 NULL == fCreateShader ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000064 NULL == fCullFace ||
65 NULL == fDeleteBuffers ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000066 NULL == fDeleteProgram ||
67 NULL == fDeleteShader ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000068 NULL == fDeleteTextures ||
69 NULL == fDepthMask ||
70 NULL == fDisable ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000071 NULL == fDisableVertexAttribArray ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000072 NULL == fDrawArrays ||
73 NULL == fDrawElements ||
74 NULL == fEnable ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000075 NULL == fEnableVertexAttribArray ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000076 NULL == fFrontFace ||
77 NULL == fGenBuffers ||
78 NULL == fGenTextures ||
79 NULL == fGetBufferParameteriv ||
80 NULL == fGetError ||
81 NULL == fGetIntegerv ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000082 NULL == fGetProgramInfoLog ||
83 NULL == fGetProgramiv ||
84 NULL == fGetShaderInfoLog ||
85 NULL == fGetShaderiv ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000086 NULL == fGetString ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000087 NULL == fGetUniformLocation ||
88 NULL == fLinkProgram ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000089 NULL == fPixelStorei ||
90 NULL == fReadPixels ||
91 NULL == fScissor ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000092 NULL == fShaderSource ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000093 NULL == fStencilFunc ||
94 NULL == fStencilMask ||
95 NULL == fStencilOp ||
96 NULL == fTexImage2D ||
97 NULL == fTexParameteri ||
bsalomon@google.com4d063de2012-05-31 17:59:23 +000098 NULL == fTexParameteriv ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000099 NULL == fTexSubImage2D ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000100 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 ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000121 NULL == fVertexAttribPointer ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000122 NULL == fViewport ||
123 NULL == fBindFramebuffer ||
124 NULL == fBindRenderbuffer ||
125 NULL == fCheckFramebufferStatus ||
126 NULL == fDeleteFramebuffers ||
127 NULL == fDeleteRenderbuffers ||
bsalomon@google.com373a6632011-10-19 20:43:20 +0000128 NULL == fFinish ||
129 NULL == fFlush ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000130 NULL == fFramebufferRenderbuffer ||
131 NULL == fFramebufferTexture2D ||
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000132 NULL == fGetFramebufferAttachmentParameteriv ||
133 NULL == fGetRenderbufferParameteriv ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000134 NULL == fGenFramebuffers ||
135 NULL == fGenRenderbuffers ||
136 NULL == fRenderbufferStorage) {
137 return false;
138 }
139
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000140 GrGLVersion glVer = GrGLGetVersion(this);
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000141
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.
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000149 if (kES2_GrGLBinding == binding) {
robertphillips@google.come7884302012-04-18 14:39:58 +0000150 if (NULL == fStencilFuncSeparate ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000151 NULL == fStencilMaskSeparate ||
152 NULL == fStencilOpSeparate) {
153 return false;
154 }
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000155 } else if (kDesktop_GrGLBinding == binding) {
robertphillips@google.come7884302012-04-18 14:39:58 +0000156
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000157 if (glVer >= GR_GL_VER(2,0)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000158 if (NULL == fStencilFuncSeparate ||
159 NULL == fStencilMaskSeparate ||
160 NULL == fStencilOpSeparate) {
161 return false;
162 }
163 }
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000164 if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
bsalomon@google.combc5cf512011-09-21 16:21:07 +0000165 return false;
166 }
bsalomon@google.com1744f972013-02-26 21:46:32 +0000167 if (glVer >= GR_GL_VER(2,0) || extensions.has("GL_ARB_draw_buffers")) {
bsalomon@google.comd32c5f52011-08-02 19:29:03 +0000168 if (NULL == fDrawBuffers) {
169 return false;
170 }
171 }
robertphillips@google.come7884302012-04-18 14:39:58 +0000172
bsalomon@google.com1744f972013-02-26 21:46:32 +0000173 if (glVer >= GR_GL_VER(1,5) || extensions.has("GL_ARB_occlusion_query")) {
bsalomon@google.com373a6632011-10-19 20:43:20 +0000174 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) ||
bsalomon@google.com1744f972013-02-26 21:46:32 +0000185 extensions.has("GL_ARB_timer_query") ||
186 extensions.has("GL_EXT_timer_query")) {
bsalomon@google.com373a6632011-10-19 20:43:20 +0000187 if (NULL == fGetQueryObjecti64v ||
188 NULL == fGetQueryObjectui64v) {
189 return false;
190 }
191 }
bsalomon@google.com1744f972013-02-26 21:46:32 +0000192 if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
bsalomon@google.com373a6632011-10-19 20:43:20 +0000193 if (NULL == fQueryCounter) {
194 return false;
195 }
196 }
bsalomon@google.comfe11cb62012-06-06 15:17:54 +0000197 // 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 &&
bsalomon@google.comd4340e22012-06-06 15:38:52 +0000201 (NULL == fMatrixMode ||
202 NULL == fLoadIdentity ||
203 NULL == fLoadMatrixf)) {
bsalomon@google.comfe11cb62012-06-06 15:17:54 +0000204 return false;
205 }
bsalomon@google.com1744f972013-02-26 21:46:32 +0000206 if (false && extensions.has("GL_NV_path_rendering")) {
bsalomon@google.comfe11cb62012-06-06 15:17:54 +0000207 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 }
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000259 }
260
261 // optional function on desktop before 1.3
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000262 if (kDesktop_GrGLBinding != binding ||
bsalomon@google.com1744f972013-02-26 21:46:32 +0000263 (glVer >= GR_GL_VER(1,3)) ||
264 extensions.has("GL_ARB_texture_compression")) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000265 if (NULL == fCompressedTexImage2D) {
266 return false;
267 }
268 }
269
bsalomon@google.comd32c5f52011-08-02 19:29:03 +0000270 // part of desktop GL, but not ES
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000271 if (kDesktop_GrGLBinding == binding &&
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000272 (NULL == fLineWidth ||
bsalomon@google.comd32c5f52011-08-02 19:29:03 +0000273 NULL == fGetTexLevelParameteriv ||
bsalomon@google.comc49d66b2011-08-03 14:22:30 +0000274 NULL == fDrawBuffer ||
275 NULL == fReadBuffer)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000276 return false;
277 }
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000278
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000279 // GL_EXT_texture_storage is part of desktop 4.2
280 // There is a desktop ARB extension and an ES+desktop EXT extension
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000281 if (kDesktop_GrGLBinding == binding) {
bsalomon@google.combaa9ea12012-01-06 19:05:43 +0000282 if (glVer >= GR_GL_VER(4,2) ||
bsalomon@google.com1744f972013-02-26 21:46:32 +0000283 extensions.has("GL_ARB_texture_storage") ||
284 extensions.has("GL_EXT_texture_storage")) {
bsalomon@google.combaa9ea12012-01-06 19:05:43 +0000285 if (NULL == fTexStorage2D) {
286 return false;
287 }
288 }
bsalomon@google.com1744f972013-02-26 21:46:32 +0000289 } else if (extensions.has("GL_EXT_texture_storage")) {
bsalomon@google.combaa9ea12012-01-06 19:05:43 +0000290 if (NULL == fTexStorage2D) {
291 return false;
292 }
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000293 }
294
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000295 // FBO MSAA
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000296 if (kDesktop_GrGLBinding == binding) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000297 // GL 3.0 and the ARB extension have multisample + blit
bsalomon@google.com1744f972013-02-26 21:46:32 +0000298 if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000299 if (NULL == fRenderbufferStorageMultisample ||
300 NULL == fBlitFramebuffer) {
301 return false;
302 }
303 } else {
bsalomon@google.com1744f972013-02-26 21:46:32 +0000304 if (extensions.has("GL_EXT_framebuffer_blit") &&
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000305 NULL == fBlitFramebuffer) {
306 return false;
307 }
bsalomon@google.com1744f972013-02-26 21:46:32 +0000308 if (extensions.has("GL_EXT_framebuffer_multisample") &&
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000309 NULL == fRenderbufferStorageMultisample) {
310 return false;
311 }
312 }
313 } else {
bsalomon@google.com1744f972013-02-26 21:46:32 +0000314 if (extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000315 if (NULL == fRenderbufferStorageMultisample ||
316 NULL == fBlitFramebuffer) {
317 return false;
318 }
319 }
bsalomon@google.com1744f972013-02-26 21:46:32 +0000320 if (extensions.has("GL_APPLE_framebuffer_multisample")) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000321 if (NULL == fRenderbufferStorageMultisample ||
322 NULL == fResolveMultisampleFramebuffer) {
323 return false;
324 }
325 }
bsalomon@google.comf3a60c02013-03-19 19:06:09 +0000326 if (extensions.has("GL_IMG_multisampled_render_to_texture")) {
327 if (NULL == fRenderbufferStorageMultisample ||
328 NULL == fFramebufferTexture2DMultisample) {
329 return false;
330 }
331 }
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000332 }
333
334 // On ES buffer mapping is an extension. On Desktop
335 // buffer mapping was part of original VBO extension
336 // which we require.
bsalomon@google.com1744f972013-02-26 21:46:32 +0000337 if (kDesktop_GrGLBinding == binding || extensions.has("GL_OES_mapbuffer")) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000338 if (NULL == fMapBuffer ||
339 NULL == fUnmapBuffer) {
340 return false;
341 }
342 }
343
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000344 // Dual source blending
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000345 if (kDesktop_GrGLBinding == binding &&
bsalomon@google.com1744f972013-02-26 21:46:32 +0000346 (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_blend_func_extended"))) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000347 if (NULL == fBindFragDataLocationIndexed) {
348 return false;
349 }
350 }
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +0000351
bsalomon@google.com1744f972013-02-26 21:46:32 +0000352 if (kDesktop_GrGLBinding == binding && glVer >= GR_GL_VER(3, 0)) {
353 if (NULL == fGetStringi) {
354 return false;
355 }
356 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000357
bsalomon@google.comecd84842013-03-01 15:36:02 +0000358 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 {
bsalomon@google.comecd84842013-03-01 15:36:02 +0000367 if (extensions.has("GL_OES_vertex_array_object")) {
368 if (NULL == fBindVertexArray ||
369 NULL == fDeleteVertexArrays ||
370 NULL == fGenVertexArrays) {
371 return false;
372 }
373 }
bsalomon@google.comecd84842013-03-01 15:36:02 +0000374 }
375
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000376 return true;
377}