1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "GrTypes.h" 11 #include "gl/GrGLInterface.h" 12 #include "gl/GrGLDefines.h" 13 14 #include <stdio.h> 15 16 #if GR_GL_PER_GL_FUNC_CALLBACK 17 namespace { 18 void GrGLDefaultInterfaceCallback(const GrGLInterface*) {} 19 } 20 #endif 21 22 GrGLBinding GrGLGetBindingInUseFromString(const char* versionString) { 23 if (NULL == versionString) { 24 GrAssert(!"NULL GL version string."); 25 return kNone_GrGLBinding; 26 } 27 28 int major, minor; 29 30 // check for desktop 31 int n = sscanf(versionString, "%d.%d", &major, &minor); 32 if (2 == n) { 33 return kDesktop_GrGLBinding; 34 } 35 36 // check for ES 1 37 char profile[2]; 38 n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, 39 &major, &minor); 40 if (4 == n) { 41 // we no longer support ES1. 42 return kNone_GrGLBinding; 43 } 44 45 // check for ES2 46 n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor); 47 if (2 == n) { 48 return kES2_GrGLBinding; 49 } 50 return kNone_GrGLBinding; 51 } 52 53 GrGLVersion GrGLGetVersionFromString(const char* versionString) { 54 if (NULL == versionString) { 55 GrAssert(!"NULL GL version string."); 56 return 0; 57 } 58 59 int major, minor; 60 61 int n = sscanf(versionString, "%d.%d", &major, &minor); 62 if (2 == n) { 63 return GR_GL_VER(major, minor); 64 } 65 66 char profile[2]; 67 n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, 68 &major, &minor); 69 if (4 == n) { 70 return GR_GL_VER(major, minor); 71 } 72 73 n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor); 74 if (2 == n) { 75 return GR_GL_VER(major, minor); 76 } 77 78 return 0; 79 } 80 81 GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) { 82 if (NULL == versionString) { 83 GrAssert(!"NULL GLSL version string."); 84 return 0; 85 } 86 87 int major, minor; 88 89 int n = sscanf(versionString, "%d.%d", &major, &minor); 90 if (2 == n) { 91 return GR_GLSL_VER(major, minor); 92 } 93 94 n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor); 95 if (2 == n) { 96 return GR_GLSL_VER(major, minor); 97 } 98 99 // android hack 100 n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor); 101 if (2 == n) { 102 return GR_GLSL_VER(major, minor); 103 } 104 105 return 0; 106 } 107 108 bool GrGLHasExtensionFromString(const char* ext, const char* extensionString) { 109 int extLength = strlen(ext); 110 111 while (true) { 112 int n = strcspn(extensionString, " "); 113 if (n == extLength && 0 == strncmp(ext, extensionString, n)) { 114 return true; 115 } 116 if (0 == extensionString[n]) { 117 return false; 118 } 119 extensionString += n+1; 120 } 121 122 return false; 123 } 124 125 bool GrGLHasExtension(const GrGLInterface* gl, const char* ext) { 126 const GrGLubyte* glstr; 127 GR_GL_CALL_RET(gl, glstr, GetString(GR_GL_EXTENSIONS)); 128 return GrGLHasExtensionFromString(ext, (const char*) glstr); 129 } 130 131 GrGLBinding GrGLGetBindingInUse(const GrGLInterface* gl) { 132 const GrGLubyte* v; 133 GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION)); 134 return GrGLGetBindingInUseFromString((const char*) v); 135 } 136 137 GrGLVersion GrGLGetVersion(const GrGLInterface* gl) { 138 const GrGLubyte* v; 139 GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION)); 140 return GrGLGetVersionFromString((const char*) v); 141 } 142 143 GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) { 144 const GrGLubyte* v; 145 GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION)); 146 return GrGLGetGLSLVersionFromString((const char*) v); 147 } 148 149 GrGLInterface::GrGLInterface() { 150 fBindingsExported = kNone_GrGLBinding; 151 152 fActiveTexture = NULL; 153 fAttachShader = NULL; 154 fBeginQuery = NULL; 155 fBindAttribLocation = NULL; 156 fBindBuffer = NULL; 157 fBindFragDataLocation = NULL; 158 fBindTexture = NULL; 159 fBlendColor = NULL; 160 fBlendFunc = NULL; 161 fBufferData = NULL; 162 fBufferSubData = NULL; 163 fClear = NULL; 164 fClearColor = NULL; 165 fClearStencil = NULL; 166 fColorMask = NULL; 167 fColorPointer = NULL; 168 fCompileShader = NULL; 169 fCompressedTexImage2D = NULL; 170 fCreateProgram = NULL; 171 fCreateShader = NULL; 172 fCullFace = NULL; 173 fDeleteBuffers = NULL; 174 fDeleteProgram = NULL; 175 fDeleteQueries = NULL; 176 fDeleteShader = NULL; 177 fDeleteTextures = NULL; 178 fDepthMask = NULL; 179 fDisable = NULL; 180 fDisableVertexAttribArray = NULL; 181 fDrawArrays = NULL; 182 fDrawBuffer = NULL; 183 fDrawBuffers = NULL; 184 fDrawElements = NULL; 185 fEndQuery = NULL; 186 fFinish = NULL; 187 fFlush = NULL; 188 fEnable = NULL; 189 fEnableVertexAttribArray = NULL; 190 fFrontFace = NULL; 191 fGenBuffers = NULL; 192 fGenQueries = NULL; 193 fGenTextures = NULL; 194 fGetBufferParameteriv = NULL; 195 fGetError = NULL; 196 fGetIntegerv = NULL; 197 fGetQueryiv = NULL; 198 fGetQueryObjecti64v = NULL; 199 fGetQueryObjectiv = NULL; 200 fGetQueryObjectui64v = NULL; 201 fGetQueryObjectuiv = NULL; 202 fGetProgramInfoLog = NULL; 203 fGetProgramiv = NULL; 204 fGetShaderInfoLog = NULL; 205 fGetShaderiv = NULL; 206 fGetString = NULL; 207 fGetTexLevelParameteriv = NULL; 208 fGetUniformLocation = NULL; 209 fLineWidth = NULL; 210 fLinkProgram = NULL; 211 fPixelStorei = NULL; 212 fQueryCounter = NULL; 213 fReadBuffer = NULL; 214 fReadPixels = NULL; 215 fScissor = NULL; 216 fShaderSource = NULL; 217 fStencilFunc = NULL; 218 fStencilFuncSeparate = NULL; 219 fStencilMask = NULL; 220 fStencilMaskSeparate = NULL; 221 fStencilOp = NULL; 222 fStencilOpSeparate = NULL; 223 fTexImage2D = NULL; 224 fTexParameteri = NULL; 225 fTexStorage2D = NULL; 226 fTexSubImage2D = NULL; 227 fUniform1f = NULL; 228 fUniform1i = NULL; 229 fUniform1fv = NULL; 230 fUniform1iv = NULL; 231 fUniform2f = NULL; 232 fUniform2i = NULL; 233 fUniform2fv = NULL; 234 fUniform2iv = NULL; 235 fUniform3f = NULL; 236 fUniform3i = NULL; 237 fUniform3fv = NULL; 238 fUniform3iv = NULL; 239 fUniform4f = NULL; 240 fUniform4i = NULL; 241 fUniform4fv = NULL; 242 fUniform4iv = NULL; 243 fUniformMatrix2fv = NULL; 244 fUniformMatrix3fv = NULL; 245 fUniformMatrix4fv = NULL; 246 fUseProgram = NULL; 247 fVertexAttrib4fv = NULL; 248 fVertexAttribPointer = NULL; 249 fViewport = NULL; 250 fBindFramebuffer = NULL; 251 fBindRenderbuffer = NULL; 252 fCheckFramebufferStatus = NULL; 253 fDeleteFramebuffers = NULL; 254 fDeleteRenderbuffers = NULL; 255 fFramebufferRenderbuffer = NULL; 256 fFramebufferTexture2D = NULL; 257 fGenFramebuffers = NULL; 258 fGenRenderbuffers = NULL; 259 fGetFramebufferAttachmentParameteriv = NULL; 260 fGetRenderbufferParameteriv = NULL; 261 fRenderbufferStorage = NULL; 262 fRenderbufferStorageMultisample = NULL; 263 fBlitFramebuffer = NULL; 264 fResolveMultisampleFramebuffer = NULL; 265 fMapBuffer = NULL; 266 fUnmapBuffer = NULL; 267 fBindFragDataLocationIndexed = NULL; 268 269 #if GR_GL_PER_GL_FUNC_CALLBACK 270 fCallback = GrGLDefaultInterfaceCallback; 271 fCallbackData = 0; 272 #endif 273 } 274 275 bool GrGLInterface::validate(GrGLBinding binding) const { 276 277 // kNone must be 0 so that the check we're about to do can never succeed if 278 // binding == kNone. 279 GR_STATIC_ASSERT(kNone_GrGLBinding == 0); 280 281 if (0 == (binding & fBindingsExported)) { 282 return false; 283 } 284 285 // functions that are always required 286 if (NULL == fActiveTexture || 287 NULL == fAttachShader || 288 NULL == fBindAttribLocation || 289 NULL == fBindBuffer || 290 NULL == fBindTexture || 291 NULL == fBlendFunc || 292 NULL == fBufferData || 293 NULL == fBufferSubData || 294 NULL == fClear || 295 NULL == fClearColor || 296 NULL == fClearStencil || 297 NULL == fColorMask || 298 NULL == fCompileShader || 299 NULL == fCreateProgram || 300 NULL == fCreateShader || 301 NULL == fCullFace || 302 NULL == fDeleteBuffers || 303 NULL == fDeleteProgram || 304 NULL == fDeleteShader || 305 NULL == fDeleteTextures || 306 NULL == fDepthMask || 307 NULL == fDisable || 308 NULL == fDisableVertexAttribArray || 309 NULL == fDrawArrays || 310 NULL == fDrawElements || 311 NULL == fEnable || 312 NULL == fEnableVertexAttribArray || 313 NULL == fFrontFace || 314 NULL == fGenBuffers || 315 NULL == fGenTextures || 316 NULL == fGetBufferParameteriv || 317 NULL == fGetError || 318 NULL == fGetIntegerv || 319 NULL == fGetProgramInfoLog || 320 NULL == fGetProgramiv || 321 NULL == fGetShaderInfoLog || 322 NULL == fGetShaderiv || 323 NULL == fGetString || 324 NULL == fGetUniformLocation || 325 NULL == fLinkProgram || 326 NULL == fPixelStorei || 327 NULL == fReadPixels || 328 NULL == fScissor || 329 NULL == fShaderSource || 330 NULL == fStencilFunc || 331 NULL == fStencilMask || 332 NULL == fStencilOp || 333 NULL == fTexImage2D || 334 NULL == fTexParameteri || 335 NULL == fTexSubImage2D || 336 NULL == fUniform1f || 337 NULL == fUniform1i || 338 NULL == fUniform1fv || 339 NULL == fUniform1iv || 340 NULL == fUniform2f || 341 NULL == fUniform2i || 342 NULL == fUniform2fv || 343 NULL == fUniform2iv || 344 NULL == fUniform3f || 345 NULL == fUniform3i || 346 NULL == fUniform3fv || 347 NULL == fUniform3iv || 348 NULL == fUniform4f || 349 NULL == fUniform4i || 350 NULL == fUniform4fv || 351 NULL == fUniform4iv || 352 NULL == fUniformMatrix2fv || 353 NULL == fUniformMatrix3fv || 354 NULL == fUniformMatrix4fv || 355 NULL == fUseProgram || 356 NULL == fVertexAttrib4fv || 357 NULL == fVertexAttribPointer || 358 NULL == fViewport || 359 NULL == fBindFramebuffer || 360 NULL == fBindRenderbuffer || 361 NULL == fCheckFramebufferStatus || 362 NULL == fDeleteFramebuffers || 363 NULL == fDeleteRenderbuffers || 364 NULL == fFinish || 365 NULL == fFlush || 366 NULL == fFramebufferRenderbuffer || 367 NULL == fFramebufferTexture2D || 368 NULL == fGetFramebufferAttachmentParameteriv || 369 NULL == fGetRenderbufferParameteriv || 370 NULL == fGenFramebuffers || 371 NULL == fGenRenderbuffers || 372 NULL == fRenderbufferStorage) { 373 return false; 374 } 375 376 const char* ext; 377 GrGLVersion glVer = GrGLGetVersion(this); 378 ext = (const char*)fGetString(GR_GL_EXTENSIONS); 379 380 // Now check that baseline ES/Desktop fns not covered above are present 381 // and that we have fn pointers for any advertised extensions that we will 382 // try to use. 383 384 // these functions are part of ES2, we assume they are available 385 // On the desktop we assume they are available if the extension 386 // is present or GL version is high enough. 387 if (kES2_GrGLBinding == binding) { 388 if (NULL == fBlendColor || 389 NULL == fStencilFuncSeparate || 390 NULL == fStencilMaskSeparate || 391 NULL == fStencilOpSeparate) { 392 return false; 393 } 394 } else if (kDesktop_GrGLBinding == binding) { 395 if (glVer >= GR_GL_VER(2,0)) { 396 if (NULL == fStencilFuncSeparate || 397 NULL == fStencilMaskSeparate || 398 NULL == fStencilOpSeparate) { 399 return false; 400 } 401 } 402 if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) { 403 return false; 404 } 405 if (glVer >= GR_GL_VER(2,0) || 406 GrGLHasExtensionFromString("GL_ARB_draw_buffers", ext)) { 407 if (NULL == fDrawBuffers) { 408 return false; 409 } 410 } 411 if (glVer >= GR_GL_VER(1,4) || 412 GrGLHasExtensionFromString("GL_EXT_blend_color", ext)) { 413 if (NULL == fBlendColor) { 414 return false; 415 } 416 } 417 if (glVer >= GR_GL_VER(1,5) || 418 GrGLHasExtensionFromString("GL_ARB_occlusion_query", ext)) { 419 if (NULL == fGenQueries || 420 NULL == fDeleteQueries || 421 NULL == fBeginQuery || 422 NULL == fEndQuery || 423 NULL == fGetQueryiv || 424 NULL == fGetQueryObjectiv || 425 NULL == fGetQueryObjectuiv) { 426 return false; 427 } 428 } 429 if (glVer >= GR_GL_VER(3,3) || 430 GrGLHasExtensionFromString("GL_ARB_timer_query", ext) || 431 GrGLHasExtensionFromString("GL_EXT_timer_query", ext)) { 432 if (NULL == fGetQueryObjecti64v || 433 NULL == fGetQueryObjectui64v) { 434 return false; 435 } 436 } 437 if (glVer >= GR_GL_VER(3,3) || 438 GrGLHasExtensionFromString("GL_ARB_timer_query", ext)) { 439 if (NULL == fQueryCounter) { 440 return false; 441 } 442 } 443 } 444 445 // optional function on desktop before 1.3 446 if (kDesktop_GrGLBinding != binding || 447 (glVer >= GR_GL_VER(1,3) || 448 GrGLHasExtensionFromString("GL_ARB_texture_compression", ext))) { 449 if (NULL == fCompressedTexImage2D) { 450 return false; 451 } 452 } 453 454 // part of desktop GL, but not ES 455 if (kDesktop_GrGLBinding == binding && 456 (NULL == fLineWidth || 457 NULL == fGetTexLevelParameteriv || 458 NULL == fDrawBuffer || 459 NULL == fReadBuffer)) { 460 return false; 461 } 462 463 // GL_EXT_texture_storage is part of desktop 4.2 464 // There is a desktop ARB extension and an ES+desktop EXT extension 465 if (kDesktop_GrGLBinding == binding) { 466 if (glVer >= GR_GL_VER(4,2) || 467 GrGLHasExtensionFromString("GL_ARB_texture_storage", ext) || 468 GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) { 469 if (NULL == fTexStorage2D) { 470 return false; 471 } 472 } 473 } else if (GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) { 474 if (NULL == fTexStorage2D) { 475 return false; 476 } 477 } 478 479 // FBO MSAA 480 if (kDesktop_GrGLBinding == binding) { 481 // GL 3.0 and the ARB extension have multisample + blit 482 if (glVer >= GR_GL_VER(3,0) || GrGLHasExtensionFromString("GL_ARB_framebuffer_object", ext)) { 483 if (NULL == fRenderbufferStorageMultisample || 484 NULL == fBlitFramebuffer) { 485 return false; 486 } 487 } else { 488 if (GrGLHasExtensionFromString("GL_EXT_framebuffer_blit", ext) && 489 NULL == fBlitFramebuffer) { 490 return false; 491 } 492 if (GrGLHasExtensionFromString("GL_EXT_framebuffer_multisample", ext) && 493 NULL == fRenderbufferStorageMultisample) { 494 return false; 495 } 496 } 497 } else { 498 if (GrGLHasExtensionFromString("GL_CHROMIUM_framebuffer_multisample", ext)) { 499 if (NULL == fRenderbufferStorageMultisample || 500 NULL == fBlitFramebuffer) { 501 return false; 502 } 503 } 504 if (GrGLHasExtensionFromString("GL_APPLE_framebuffer_multisample", ext)) { 505 if (NULL == fRenderbufferStorageMultisample || 506 NULL == fResolveMultisampleFramebuffer) { 507 return false; 508 } 509 } 510 } 511 512 // On ES buffer mapping is an extension. On Desktop 513 // buffer mapping was part of original VBO extension 514 // which we require. 515 if (kDesktop_GrGLBinding == binding || 516 GrGLHasExtensionFromString("GL_OES_mapbuffer", ext)) { 517 if (NULL == fMapBuffer || 518 NULL == fUnmapBuffer) { 519 return false; 520 } 521 } 522 523 // Dual source blending 524 if (kDesktop_GrGLBinding == binding && 525 (glVer >= GR_GL_VER(3,3) || 526 GrGLHasExtensionFromString("GL_ARB_blend_func_extended", ext))) { 527 if (NULL == fBindFragDataLocationIndexed) { 528 return false; 529 } 530 } 531 532 return true; 533 } 534 535