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 #if GR_GL_PER_GL_FUNC_CALLBACK 16 namespace { 17 void GrGLDefaultInterfaceCallback(const GrGLInterface*) {} 18 } 19 #endif 20 21 const GrGLInterface* GrGLInterfaceAddTestDebugMarker(const GrGLInterface* interface, 22 GrGLInsertEventMarkerProc insertEventMarkerFn, 23 GrGLPushGroupMarkerProc pushGroupMarkerFn, 24 GrGLPopGroupMarkerProc popGroupMarkerFn) { 25 GrGLInterface* newInterface = GrGLInterface::NewClone(interface); 26 27 if (!newInterface->fExtensions.has("GL_EXT_debug_marker")) { 28 newInterface->fExtensions.add("GL_EXT_debug_marker"); 29 } 30 31 newInterface->fFunctions.fInsertEventMarker = insertEventMarkerFn; 32 newInterface->fFunctions.fPushGroupMarker = pushGroupMarkerFn; 33 newInterface->fFunctions.fPopGroupMarker = popGroupMarkerFn; 34 35 return newInterface; 36 } 37 38 const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface* interface) { 39 GrGLInterface* newInterface = GrGLInterface::NewClone(interface); 40 41 newInterface->fExtensions.remove("GL_NV_path_rendering"); 42 newInterface->fFunctions.fPathCommands = NULL; 43 newInterface->fFunctions.fPathCoords = NULL; 44 newInterface->fFunctions.fPathParameteri = NULL; 45 newInterface->fFunctions.fPathParameterf = NULL; 46 newInterface->fFunctions.fGenPaths = NULL; 47 newInterface->fFunctions.fDeletePaths = NULL; 48 newInterface->fFunctions.fIsPath = NULL; 49 newInterface->fFunctions.fPathStencilFunc = NULL; 50 newInterface->fFunctions.fStencilFillPath = NULL; 51 newInterface->fFunctions.fStencilStrokePath = NULL; 52 newInterface->fFunctions.fStencilFillPathInstanced = NULL; 53 newInterface->fFunctions.fStencilStrokePathInstanced = NULL; 54 newInterface->fFunctions.fPathTexGen = NULL; 55 newInterface->fFunctions.fCoverFillPath = NULL; 56 newInterface->fFunctions.fCoverStrokePath = NULL; 57 newInterface->fFunctions.fCoverFillPathInstanced = NULL; 58 newInterface->fFunctions.fCoverStrokePathInstanced = NULL; 59 newInterface->fFunctions.fStencilThenCoverFillPath = NULL; 60 newInterface->fFunctions.fStencilThenCoverStrokePath = NULL; 61 newInterface->fFunctions.fStencilThenCoverFillPathInstanced = NULL; 62 newInterface->fFunctions.fStencilThenCoverStrokePathInstanced = NULL; 63 newInterface->fFunctions.fProgramPathFragmentInputGen = NULL; 64 newInterface->fFunctions.fPathMemoryGlyphIndexArray = NULL; 65 return newInterface; 66 } 67 68 GrGLInterface::GrGLInterface() { 69 fStandard = kNone_GrGLStandard; 70 71 #if GR_GL_PER_GL_FUNC_CALLBACK 72 fCallback = GrGLDefaultInterfaceCallback; 73 fCallbackData = 0; 74 #endif 75 } 76 77 GrGLInterface* GrGLInterface::NewClone(const GrGLInterface* interface) { 78 SkASSERT(interface); 79 80 GrGLInterface* clone = SkNEW(GrGLInterface); 81 clone->fStandard = interface->fStandard; 82 clone->fExtensions = interface->fExtensions; 83 clone->fFunctions = interface->fFunctions; 84 #if GR_GL_PER_GL_FUNC_CALLBACK 85 clone->fCallback = interface->fCallback; 86 clone->fCallbackData = interface->fCallbackData; 87 #endif 88 return clone; 89 } 90 91 #ifdef SK_DEBUG 92 static int kIsDebug = 1; 93 #else 94 static int kIsDebug = 0; 95 #endif 96 97 #define RETURN_FALSE_INTERFACE \ 98 if (kIsDebug) { SkDebugf("%s:%d GrGLInterface::validate() failed.\n", __FILE__, __LINE__); } \ 99 return false; 100 101 bool GrGLInterface::validate() const { 102 103 if (kNone_GrGLStandard == fStandard) { 104 RETURN_FALSE_INTERFACE 105 } 106 107 if (!fExtensions.isInitialized()) { 108 RETURN_FALSE_INTERFACE 109 } 110 111 // functions that are always required 112 if (NULL == fFunctions.fActiveTexture || 113 NULL == fFunctions.fAttachShader || 114 NULL == fFunctions.fBindAttribLocation || 115 NULL == fFunctions.fBindBuffer || 116 NULL == fFunctions.fBindTexture || 117 NULL == fFunctions.fBlendFunc || 118 NULL == fFunctions.fBlendColor || // -> GL >= 1.4, ES >= 2.0 or extension 119 NULL == fFunctions.fBufferData || 120 NULL == fFunctions.fBufferSubData || 121 NULL == fFunctions.fClear || 122 NULL == fFunctions.fClearColor || 123 NULL == fFunctions.fClearStencil || 124 NULL == fFunctions.fColorMask || 125 NULL == fFunctions.fCompileShader || 126 NULL == fFunctions.fCopyTexSubImage2D || 127 NULL == fFunctions.fCreateProgram || 128 NULL == fFunctions.fCreateShader || 129 NULL == fFunctions.fCullFace || 130 NULL == fFunctions.fDeleteBuffers || 131 NULL == fFunctions.fDeleteProgram || 132 NULL == fFunctions.fDeleteShader || 133 NULL == fFunctions.fDeleteTextures || 134 NULL == fFunctions.fDepthMask || 135 NULL == fFunctions.fDisable || 136 NULL == fFunctions.fDisableVertexAttribArray || 137 NULL == fFunctions.fDrawArrays || 138 NULL == fFunctions.fDrawElements || 139 NULL == fFunctions.fEnable || 140 NULL == fFunctions.fEnableVertexAttribArray || 141 NULL == fFunctions.fFrontFace || 142 NULL == fFunctions.fGenBuffers || 143 NULL == fFunctions.fGenTextures || 144 NULL == fFunctions.fGetBufferParameteriv || 145 NULL == fFunctions.fGenerateMipmap || 146 NULL == fFunctions.fGetError || 147 NULL == fFunctions.fGetIntegerv || 148 NULL == fFunctions.fGetProgramInfoLog || 149 NULL == fFunctions.fGetProgramiv || 150 NULL == fFunctions.fGetShaderInfoLog || 151 NULL == fFunctions.fGetShaderiv || 152 NULL == fFunctions.fGetString || 153 NULL == fFunctions.fGetUniformLocation || 154 NULL == fFunctions.fLinkProgram || 155 NULL == fFunctions.fLineWidth || 156 NULL == fFunctions.fPixelStorei || 157 NULL == fFunctions.fReadPixels || 158 NULL == fFunctions.fScissor || 159 NULL == fFunctions.fShaderSource || 160 NULL == fFunctions.fStencilFunc || 161 NULL == fFunctions.fStencilMask || 162 NULL == fFunctions.fStencilOp || 163 NULL == fFunctions.fTexImage2D || 164 NULL == fFunctions.fTexParameteri || 165 NULL == fFunctions.fTexParameteriv || 166 NULL == fFunctions.fTexSubImage2D || 167 NULL == fFunctions.fUniform1f || 168 NULL == fFunctions.fUniform1i || 169 NULL == fFunctions.fUniform1fv || 170 NULL == fFunctions.fUniform1iv || 171 NULL == fFunctions.fUniform2f || 172 NULL == fFunctions.fUniform2i || 173 NULL == fFunctions.fUniform2fv || 174 NULL == fFunctions.fUniform2iv || 175 NULL == fFunctions.fUniform3f || 176 NULL == fFunctions.fUniform3i || 177 NULL == fFunctions.fUniform3fv || 178 NULL == fFunctions.fUniform3iv || 179 NULL == fFunctions.fUniform4f || 180 NULL == fFunctions.fUniform4i || 181 NULL == fFunctions.fUniform4fv || 182 NULL == fFunctions.fUniform4iv || 183 NULL == fFunctions.fUniformMatrix2fv || 184 NULL == fFunctions.fUniformMatrix3fv || 185 NULL == fFunctions.fUniformMatrix4fv || 186 NULL == fFunctions.fUseProgram || 187 NULL == fFunctions.fVertexAttrib4fv || 188 NULL == fFunctions.fVertexAttribPointer || 189 NULL == fFunctions.fViewport || 190 NULL == fFunctions.fBindFramebuffer || 191 NULL == fFunctions.fBindRenderbuffer || 192 NULL == fFunctions.fCheckFramebufferStatus || 193 NULL == fFunctions.fDeleteFramebuffers || 194 NULL == fFunctions.fDeleteRenderbuffers || 195 NULL == fFunctions.fFinish || 196 NULL == fFunctions.fFlush || 197 NULL == fFunctions.fFramebufferRenderbuffer || 198 NULL == fFunctions.fFramebufferTexture2D || 199 NULL == fFunctions.fGetFramebufferAttachmentParameteriv || 200 NULL == fFunctions.fGetRenderbufferParameteriv || 201 NULL == fFunctions.fGenFramebuffers || 202 NULL == fFunctions.fGenRenderbuffers || 203 NULL == fFunctions.fRenderbufferStorage) { 204 RETURN_FALSE_INTERFACE 205 } 206 207 GrGLVersion glVer = GrGLGetVersion(this); 208 if (GR_GL_INVALID_VER == glVer) { 209 RETURN_FALSE_INTERFACE 210 } 211 212 // Now check that baseline ES/Desktop fns not covered above are present 213 // and that we have fn pointers for any advertised fExtensions that we will 214 // try to use. 215 216 // these functions are part of ES2, we assume they are available 217 // On the desktop we assume they are available if the extension 218 // is present or GL version is high enough. 219 if (kGLES_GrGLStandard == fStandard) { 220 if (NULL == fFunctions.fStencilFuncSeparate || 221 NULL == fFunctions.fStencilMaskSeparate || 222 NULL == fFunctions.fStencilOpSeparate) { 223 RETURN_FALSE_INTERFACE 224 } 225 } else if (kGL_GrGLStandard == fStandard) { 226 227 if (glVer >= GR_GL_VER(2,0)) { 228 if (NULL == fFunctions.fStencilFuncSeparate || 229 NULL == fFunctions.fStencilMaskSeparate || 230 NULL == fFunctions.fStencilOpSeparate) { 231 RETURN_FALSE_INTERFACE 232 } 233 } 234 if (glVer >= GR_GL_VER(3,0) && NULL == fFunctions.fBindFragDataLocation) { 235 RETURN_FALSE_INTERFACE 236 } 237 if (glVer >= GR_GL_VER(2,0) || fExtensions.has("GL_ARB_draw_buffers")) { 238 if (NULL == fFunctions.fDrawBuffers) { 239 RETURN_FALSE_INTERFACE 240 } 241 } 242 243 if (glVer >= GR_GL_VER(1,5) || fExtensions.has("GL_ARB_occlusion_query")) { 244 if (NULL == fFunctions.fGenQueries || 245 NULL == fFunctions.fDeleteQueries || 246 NULL == fFunctions.fBeginQuery || 247 NULL == fFunctions.fEndQuery || 248 NULL == fFunctions.fGetQueryiv || 249 NULL == fFunctions.fGetQueryObjectiv || 250 NULL == fFunctions.fGetQueryObjectuiv) { 251 RETURN_FALSE_INTERFACE 252 } 253 } 254 if (glVer >= GR_GL_VER(3,3) || 255 fExtensions.has("GL_ARB_timer_query") || 256 fExtensions.has("GL_EXT_timer_query")) { 257 if (NULL == fFunctions.fGetQueryObjecti64v || 258 NULL == fFunctions.fGetQueryObjectui64v) { 259 RETURN_FALSE_INTERFACE 260 } 261 } 262 if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_timer_query")) { 263 if (NULL == fFunctions.fQueryCounter) { 264 RETURN_FALSE_INTERFACE 265 } 266 } 267 } 268 269 // optional function on desktop before 1.3 270 if (kGL_GrGLStandard != fStandard || 271 (glVer >= GR_GL_VER(1,3)) || 272 fExtensions.has("GL_ARB_texture_compression")) { 273 if (NULL == fFunctions.fCompressedTexImage2D 274 #if 0 275 || NULL == fFunctions.fCompressedTexSubImage2D 276 #endif 277 ) { 278 RETURN_FALSE_INTERFACE 279 } 280 } 281 282 // part of desktop GL, but not ES 283 if (kGL_GrGLStandard == fStandard && 284 (NULL == fFunctions.fGetTexLevelParameteriv || 285 NULL == fFunctions.fDrawBuffer || 286 NULL == fFunctions.fReadBuffer)) { 287 RETURN_FALSE_INTERFACE 288 } 289 290 // GL_EXT_texture_storage is part of desktop 4.2 291 // There is a desktop ARB extension and an ES+desktop EXT extension 292 if (kGL_GrGLStandard == fStandard) { 293 if (glVer >= GR_GL_VER(4,2) || 294 fExtensions.has("GL_ARB_texture_storage") || 295 fExtensions.has("GL_EXT_texture_storage")) { 296 if (NULL == fFunctions.fTexStorage2D) { 297 RETURN_FALSE_INTERFACE 298 } 299 } 300 } else if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_texture_storage")) { 301 if (NULL == fFunctions.fTexStorage2D) { 302 RETURN_FALSE_INTERFACE 303 } 304 } 305 306 if (fExtensions.has("GL_EXT_discard_framebuffer")) { 307 // FIXME: Remove this once Chromium is updated to provide this function 308 #if 0 309 if (NULL == fFunctions.fDiscardFramebuffer) { 310 RETURN_FALSE_INTERFACE 311 } 312 #endif 313 } 314 315 // FBO MSAA 316 if (kGL_GrGLStandard == fStandard) { 317 // GL 3.0 and the ARB extension have multisample + blit 318 if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_ARB_framebuffer_object")) { 319 if (NULL == fFunctions.fRenderbufferStorageMultisample || 320 NULL == fFunctions.fBlitFramebuffer) { 321 RETURN_FALSE_INTERFACE 322 } 323 } else { 324 if (fExtensions.has("GL_EXT_framebuffer_blit") && 325 NULL == fFunctions.fBlitFramebuffer) { 326 RETURN_FALSE_INTERFACE 327 } 328 if (fExtensions.has("GL_EXT_framebuffer_multisample") && 329 NULL == fFunctions.fRenderbufferStorageMultisample) { 330 RETURN_FALSE_INTERFACE 331 } 332 } 333 } else { 334 if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_CHROMIUM_framebuffer_multisample")) { 335 if (NULL == fFunctions.fRenderbufferStorageMultisample || 336 NULL == fFunctions.fBlitFramebuffer) { 337 RETURN_FALSE_INTERFACE 338 } 339 } 340 if (fExtensions.has("GL_APPLE_framebuffer_multisample")) { 341 if (NULL == fFunctions.fRenderbufferStorageMultisampleES2APPLE || 342 NULL == fFunctions.fResolveMultisampleFramebuffer) { 343 RETURN_FALSE_INTERFACE 344 } 345 } 346 if (fExtensions.has("GL_IMG_multisampled_render_to_texture") || 347 fExtensions.has("GL_EXT_multisampled_render_to_texture")) { 348 if (NULL == fFunctions.fRenderbufferStorageMultisampleES2EXT || 349 NULL == fFunctions.fFramebufferTexture2DMultisample) { 350 RETURN_FALSE_INTERFACE 351 } 352 } 353 } 354 355 // On ES buffer mapping is an extension. On Desktop 356 // buffer mapping was part of original VBO extension 357 // which we require. 358 if (kGL_GrGLStandard == fStandard || fExtensions.has("GL_OES_mapbuffer")) { 359 if (NULL == fFunctions.fMapBuffer || 360 NULL == fFunctions.fUnmapBuffer) { 361 RETURN_FALSE_INTERFACE 362 } 363 } 364 365 // Dual source blending 366 if (kGL_GrGLStandard == fStandard && 367 (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_blend_func_extended"))) { 368 if (NULL == fFunctions.fBindFragDataLocationIndexed) { 369 RETURN_FALSE_INTERFACE 370 } 371 } 372 373 // glGetStringi was added in version 3.0 of both desktop and ES. 374 if (glVer >= GR_GL_VER(3, 0)) { 375 if (NULL == fFunctions.fGetStringi) { 376 RETURN_FALSE_INTERFACE 377 } 378 } 379 380 if (kGL_GrGLStandard == fStandard) { 381 if (glVer >= GR_GL_VER(3, 0) || fExtensions.has("GL_ARB_vertex_array_object")) { 382 if (NULL == fFunctions.fBindVertexArray || 383 NULL == fFunctions.fDeleteVertexArrays || 384 NULL == fFunctions.fGenVertexArrays) { 385 RETURN_FALSE_INTERFACE 386 } 387 } 388 } else { 389 if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_OES_vertex_array_object")) { 390 if (NULL == fFunctions.fBindVertexArray || 391 NULL == fFunctions.fDeleteVertexArrays || 392 NULL == fFunctions.fGenVertexArrays) { 393 RETURN_FALSE_INTERFACE 394 } 395 } 396 } 397 398 if (fExtensions.has("GL_EXT_debug_marker")) { 399 if (NULL == fFunctions.fInsertEventMarker || 400 NULL == fFunctions.fPushGroupMarker || 401 NULL == fFunctions.fPopGroupMarker) { 402 RETURN_FALSE_INTERFACE 403 } 404 } 405 406 if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) || 407 fExtensions.has("GL_ARB_invalidate_subdata")) { 408 if (NULL == fFunctions.fInvalidateBufferData || 409 NULL == fFunctions.fInvalidateBufferSubData || 410 NULL == fFunctions.fInvalidateFramebuffer || 411 NULL == fFunctions.fInvalidateSubFramebuffer || 412 NULL == fFunctions.fInvalidateTexImage || 413 NULL == fFunctions.fInvalidateTexSubImage) { 414 RETURN_FALSE_INTERFACE; 415 } 416 } else if (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0)) { 417 // ES 3.0 adds the framebuffer functions but not the others. 418 if (NULL == fFunctions.fInvalidateFramebuffer || 419 NULL == fFunctions.fInvalidateSubFramebuffer) { 420 RETURN_FALSE_INTERFACE; 421 } 422 } 423 424 if (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_CHROMIUM_map_sub")) { 425 if (NULL == fFunctions.fMapBufferSubData || 426 NULL == fFunctions.fMapTexSubImage2D || 427 NULL == fFunctions.fUnmapBufferSubData || 428 NULL == fFunctions.fUnmapTexSubImage2D) { 429 RETURN_FALSE_INTERFACE; 430 } 431 } 432 433 // These functions are added to the 3.0 version of both GLES and GL. 434 if (glVer >= GR_GL_VER(3,0) || 435 (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_map_buffer_range")) || 436 (kGL_GrGLStandard == fStandard && fExtensions.has("GL_ARB_map_buffer_range"))) { 437 if (NULL == fFunctions.fMapBufferRange || 438 NULL == fFunctions.fFlushMappedBufferRange) { 439 RETURN_FALSE_INTERFACE; 440 } 441 } 442 443 if ((kGL_GrGLStandard == fStandard && fExtensions.has("GL_EXT_direct_state_access")) || 444 (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_NV_path_rendering"))) { 445 if (NULL == fFunctions.fMatrixLoadf || 446 NULL == fFunctions.fMatrixLoadIdentity) { 447 RETURN_FALSE_INTERFACE 448 } 449 } 450 451 if ((kGL_GrGLStandard == fStandard && 452 (glVer >= GR_GL_VER(4,3) || fExtensions.has("GL_ARB_program_interface_query"))) || 453 (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) { 454 if (NULL == fFunctions.fGetProgramResourceLocation) { 455 RETURN_FALSE_INTERFACE 456 } 457 } 458 459 if (fExtensions.has("GL_NV_path_rendering")) { 460 if (NULL == fFunctions.fPathCommands || 461 NULL == fFunctions.fPathCoords || 462 NULL == fFunctions.fPathParameteri || 463 NULL == fFunctions.fPathParameterf || 464 NULL == fFunctions.fGenPaths || 465 NULL == fFunctions.fDeletePaths || 466 NULL == fFunctions.fIsPath || 467 NULL == fFunctions.fPathStencilFunc || 468 NULL == fFunctions.fStencilFillPath || 469 NULL == fFunctions.fStencilStrokePath || 470 NULL == fFunctions.fStencilFillPathInstanced || 471 NULL == fFunctions.fStencilStrokePathInstanced || 472 NULL == fFunctions.fCoverFillPath || 473 NULL == fFunctions.fCoverStrokePath || 474 NULL == fFunctions.fCoverFillPathInstanced || 475 NULL == fFunctions.fCoverStrokePathInstanced) { 476 RETURN_FALSE_INTERFACE 477 } 478 if (kGL_GrGLStandard == fStandard) { 479 // Some methods only exist on desktop 480 if (NULL == fFunctions.fPathTexGen) { 481 RETURN_FALSE_INTERFACE 482 } 483 } else { 484 // All additions through v1.3 exist on GLES 485 if (NULL == fFunctions.fStencilThenCoverFillPath || 486 NULL == fFunctions.fStencilThenCoverStrokePath || 487 NULL == fFunctions.fStencilThenCoverFillPathInstanced || 488 NULL == fFunctions.fStencilThenCoverStrokePathInstanced || 489 NULL == fFunctions.fProgramPathFragmentInputGen || 490 NULL == fFunctions.fPathMemoryGlyphIndexArray) { 491 RETURN_FALSE_INTERFACE 492 } 493 } 494 } 495 496 return true; 497 } 498