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