GLContext.cpp (105300B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "GLContext.h" 8 9 #include <algorithm> 10 #include <string.h> 11 #include <ctype.h> 12 #include <regex> 13 #include <string> 14 #include <vector> 15 #ifdef MOZ_WIDGET_ANDROID 16 # include <sys/mman.h> 17 #endif 18 #if defined(XP_LINUX) && !defined(ANDROID) 19 // For MesaMemoryLeakWorkaround 20 # include <dlfcn.h> 21 # include <link.h> 22 #endif 23 24 #include "GLBlitHelper.h" 25 #include "GLReadTexImageHelper.h" 26 #include "GLScreenBuffer.h" 27 28 #include "gfxCrashReporterUtils.h" 29 #include "gfxEnv.h" 30 #include "gfxUtils.h" 31 #include "GLContextProvider.h" 32 #include "GLLibraryLoader.h" 33 #include "GLTextureImage.h" 34 #include "nsPrintfCString.h" 35 #include "nsThreadUtils.h" 36 #include "prenv.h" 37 #include "prlink.h" 38 #include "ScopedGLHelpers.h" 39 #include "SharedSurfaceGL.h" 40 #include "GfxTexturesReporter.h" 41 #include "gfx2DGlue.h" 42 #include "mozilla/StaticPrefs_gfx.h" 43 #include "mozilla/StaticPrefs_gl.h" 44 #include "mozilla/IntegerPrintfMacros.h" 45 #include "mozilla/gfx/Logging.h" 46 #include "mozilla/layers/BuildConstants.h" 47 #include "mozilla/layers/TextureForwarder.h" // for LayersIPCChannel 48 49 #include "OGLShaderProgram.h" // for ShaderProgramType 50 51 #include "mozilla/Maybe.h" 52 53 #ifdef XP_MACOSX 54 # include <CoreServices/CoreServices.h> 55 #endif 56 57 #ifdef MOZ_WIDGET_ANDROID 58 # include "mozilla/jni/Utils.h" 59 #endif 60 61 namespace mozilla { 62 namespace gl { 63 64 using namespace mozilla::gfx; 65 using namespace mozilla::layers; 66 67 // Zero-initialized after init(). 68 MOZ_THREAD_LOCAL(const GLContext*) GLContext::sCurrentContext; 69 70 // If adding defines, don't forget to undefine symbols. See #undef block below. 71 // clang-format off 72 #define CORE_SYMBOL(x) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x }} } 73 #define CORE_EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x, "gl" #x #y, "gl" #x #z }} } 74 #define EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x #y, "gl" #x #z }} } 75 #define EXT_SYMBOL3(x,y,z,w) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x #y, "gl" #x #z, "gl" #x #w }} } 76 #define END_SYMBOLS { nullptr, {} } 77 // clang-format on 78 79 // should match the order of GLExtensions, and be null-terminated. 80 static const char* const sExtensionNames[] = { 81 "NO_EXTENSION", 82 "GL_AMD_compressed_ATC_texture", 83 "GL_ANGLE_depth_texture", 84 "GL_ANGLE_framebuffer_blit", 85 "GL_ANGLE_framebuffer_multisample", 86 "GL_ANGLE_instanced_arrays", 87 "GL_ANGLE_multiview", 88 "GL_ANGLE_provoking_vertex", 89 "GL_ANGLE_texture_compression_dxt3", 90 "GL_ANGLE_texture_compression_dxt5", 91 "GL_ANGLE_timer_query", 92 "GL_APPLE_client_storage", 93 "GL_APPLE_fence", 94 "GL_APPLE_framebuffer_multisample", 95 "GL_APPLE_sync", 96 "GL_APPLE_texture_range", 97 "GL_APPLE_vertex_array_object", 98 "GL_ARB_ES2_compatibility", 99 "GL_ARB_ES3_compatibility", 100 "GL_ARB_color_buffer_float", 101 "GL_ARB_compatibility", 102 "GL_ARB_copy_buffer", 103 "GL_ARB_depth_clamp", 104 "GL_ARB_depth_texture", 105 "GL_ARB_draw_buffers", 106 "GL_ARB_draw_instanced", 107 "GL_ARB_framebuffer_object", 108 "GL_ARB_framebuffer_sRGB", 109 "GL_ARB_geometry_shader4", 110 "GL_ARB_half_float_pixel", 111 "GL_ARB_instanced_arrays", 112 "GL_ARB_internalformat_query", 113 "GL_ARB_invalidate_subdata", 114 "GL_ARB_map_buffer_range", 115 "GL_ARB_occlusion_query2", 116 "GL_ARB_pixel_buffer_object", 117 "GL_ARB_provoking_vertex", 118 "GL_ARB_robust_buffer_access_behavior", 119 "GL_ARB_robustness", 120 "GL_ARB_sampler_objects", 121 "GL_ARB_seamless_cube_map", 122 "GL_ARB_shader_texture_lod", 123 "GL_ARB_sync", 124 "GL_ARB_texture_compression", 125 "GL_ARB_texture_compression_bptc", 126 "GL_ARB_texture_compression_rgtc", 127 "GL_ARB_texture_float", 128 "GL_ARB_texture_non_power_of_two", 129 "GL_ARB_texture_rectangle", 130 "GL_ARB_texture_rg", 131 "GL_ARB_texture_storage", 132 "GL_ARB_texture_swizzle", 133 "GL_ARB_timer_query", 134 "GL_ARB_transform_feedback2", 135 "GL_ARB_uniform_buffer_object", 136 "GL_ARB_vertex_array_object", 137 "GL_CHROMIUM_color_buffer_float_rgb", 138 "GL_CHROMIUM_color_buffer_float_rgba", 139 "GL_EXT_bgra", 140 "GL_EXT_blend_minmax", 141 "GL_EXT_color_buffer_float", 142 "GL_EXT_color_buffer_half_float", 143 "GL_EXT_copy_texture", 144 "GL_EXT_depth_clamp", 145 "GL_EXT_disjoint_timer_query", 146 "GL_EXT_draw_buffers", 147 "GL_EXT_draw_buffers2", 148 "GL_EXT_draw_instanced", 149 "GL_EXT_float_blend", 150 "GL_EXT_frag_depth", 151 "GL_EXT_framebuffer_blit", 152 "GL_EXT_framebuffer_multisample", 153 "GL_EXT_framebuffer_object", 154 "GL_EXT_framebuffer_sRGB", 155 "GL_EXT_gpu_shader4", 156 "GL_EXT_map_buffer_range", 157 "GL_EXT_multisampled_render_to_texture", 158 "GL_EXT_occlusion_query_boolean", 159 "GL_EXT_packed_depth_stencil", 160 "GL_EXT_provoking_vertex", 161 "GL_EXT_read_format_bgra", 162 "GL_EXT_robustness", 163 "GL_EXT_sRGB", 164 "GL_EXT_sRGB_write_control", 165 "GL_EXT_shader_texture_lod", 166 "GL_EXT_texture_compression_bptc", 167 "GL_EXT_texture_compression_dxt1", 168 "GL_EXT_texture_compression_rgtc", 169 "GL_EXT_texture_compression_s3tc", 170 "GL_EXT_texture_compression_s3tc_srgb", 171 "GL_EXT_texture_filter_anisotropic", 172 "GL_EXT_texture_format_BGRA8888", 173 "GL_EXT_texture_norm16", 174 "GL_EXT_texture_sRGB", 175 "GL_EXT_texture_storage", 176 "GL_EXT_timer_query", 177 "GL_EXT_transform_feedback", 178 "GL_EXT_unpack_subimage", 179 "GL_EXT_semaphore", 180 "GL_EXT_semaphore_fd", 181 "GL_EXT_memory_object", 182 "GL_EXT_memory_object_fd", 183 "GL_IMG_read_format", 184 "GL_IMG_texture_compression_pvrtc", 185 "GL_IMG_texture_npot", 186 "GL_KHR_debug", 187 "GL_KHR_parallel_shader_compile", 188 "GL_KHR_robust_buffer_access_behavior", 189 "GL_KHR_robustness", 190 "GL_KHR_texture_compression_astc_hdr", 191 "GL_KHR_texture_compression_astc_ldr", 192 "GL_NV_draw_instanced", 193 "GL_NV_fence", 194 "GL_NV_framebuffer_blit", 195 "GL_NV_geometry_program4", 196 "GL_NV_half_float", 197 "GL_NV_instanced_arrays", 198 "GL_NV_primitive_restart", 199 "GL_NV_texture_barrier", 200 "GL_NV_transform_feedback", 201 "GL_NV_transform_feedback2", 202 "GL_OES_EGL_image", 203 "GL_OES_EGL_image_external", 204 "GL_OES_EGL_sync", 205 "GL_OES_compressed_ETC1_RGB8_texture", 206 "GL_OES_depth24", 207 "GL_OES_depth32", 208 "GL_OES_depth_texture", 209 "GL_OES_draw_buffers_indexed", 210 "GL_OES_element_index_uint", 211 "GL_OES_fbo_render_mipmap", 212 "GL_OES_framebuffer_object", 213 "GL_OES_packed_depth_stencil", 214 "GL_OES_rgb8_rgba8", 215 "GL_OES_standard_derivatives", 216 "GL_OES_stencil8", 217 "GL_OES_texture_3D", 218 "GL_OES_texture_float", 219 "GL_OES_texture_float_linear", 220 "GL_OES_texture_half_float", 221 "GL_OES_texture_half_float_linear", 222 "GL_OES_texture_npot", 223 "GL_OES_vertex_array_object", 224 "GL_OVR_multiview2"}; 225 226 static bool ShouldUseTLSIsCurrent(bool useTLSIsCurrent) { 227 if (StaticPrefs::gl_use_tls_is_current() == 0) { 228 return useTLSIsCurrent; 229 } 230 231 return StaticPrefs::gl_use_tls_is_current() > 0; 232 } 233 234 static bool ParseVersion(const std::string& versionStr, 235 uint32_t* const out_major, uint32_t* const out_minor) { 236 static const std::regex kVersionRegex("([0-9]+)\\.([0-9]+)"); 237 std::smatch match; 238 if (!std::regex_search(versionStr, match, kVersionRegex)) return false; 239 240 const auto& majorStr = match.str(1); 241 const auto& minorStr = match.str(2); 242 *out_major = atoi(majorStr.c_str()); 243 *out_minor = atoi(minorStr.c_str()); 244 return true; 245 } 246 247 /*static*/ 248 uint8_t GLContext::ChooseDebugFlags(const CreateContextFlags createFlags) { 249 uint8_t debugFlags = 0; 250 251 #ifdef MOZ_GL_DEBUG_BUILD 252 if (gfxEnv::MOZ_GL_DEBUG()) { 253 debugFlags |= GLContext::DebugFlagEnabled; 254 } 255 256 // Enables extra verbose output, informing of the start and finish of every GL 257 // call. Useful e.g. to record information to investigate graphics system 258 // crashes/lockups 259 if (gfxEnv::MOZ_GL_DEBUG_VERBOSE()) { 260 debugFlags |= GLContext::DebugFlagTrace; 261 } 262 263 // Aborts on GL error. Can be useful to debug quicker code that is known not 264 // to generate any GL error in principle. 265 bool abortOnError = false; 266 267 if (createFlags & CreateContextFlags::NO_VALIDATION) { 268 abortOnError = true; 269 270 const auto& env = gfxEnv::MOZ_GL_DEBUG_ABORT_ON_ERROR(); 271 if (env.as_str == "0") { 272 abortOnError = false; 273 } 274 } 275 276 if (abortOnError) { 277 debugFlags |= GLContext::DebugFlagAbortOnError; 278 } 279 #endif 280 281 return debugFlags; 282 } 283 284 GLContext::GLContext(const GLContextDesc& desc, GLContext* sharedContext, 285 bool useTLSIsCurrent) 286 : mDesc(desc), 287 mUseTLSIsCurrent(ShouldUseTLSIsCurrent(useTLSIsCurrent)), 288 mDebugFlags(ChooseDebugFlags(mDesc.flags)), 289 mSharedContext(sharedContext), 290 mOwningThreadId(Some(PlatformThread::CurrentId())), 291 mWorkAroundDriverBugs( 292 StaticPrefs::gfx_work_around_driver_bugs_AtStartup()) {} 293 294 GLContext::~GLContext() { 295 NS_ASSERTION( 296 IsDestroyed(), 297 "GLContext implementation must call MarkDestroyed in destructor!"); 298 #ifdef MOZ_GL_DEBUG_BUILD 299 if (mSharedContext) { 300 GLContext* tip = mSharedContext; 301 while (tip->mSharedContext) tip = tip->mSharedContext; 302 tip->SharedContextDestroyed(this); 303 tip->ReportOutstandingNames(); 304 } else { 305 ReportOutstandingNames(); 306 } 307 #endif 308 // Ensure we clear sCurrentContext if we were the last context set and avoid 309 // the memory getting reused. 310 if (sCurrentContext.init() && sCurrentContext.get() == this) { 311 sCurrentContext.set(nullptr); 312 } 313 } 314 315 /*static*/ 316 void GLContext::InvalidateCurrentContext() { 317 if (sCurrentContext.init()) { 318 sCurrentContext.set(nullptr); 319 } 320 } 321 322 /*static*/ 323 void GLContext::StaticDebugCallback(GLenum source, GLenum type, GLuint id, 324 GLenum severity, GLsizei length, 325 const GLchar* message, 326 const GLvoid* userParam) { 327 GLContext* gl = (GLContext*)userParam; 328 gl->DebugCallback(source, type, id, severity, length, message); 329 } 330 331 bool GLContext::Init() { 332 MOZ_RELEASE_ASSERT(!mSymbols.fBindFramebuffer, 333 "GFX: GLContext::Init should only be called once."); 334 335 ScopedGfxFeatureReporter reporter("GL Context"); 336 337 if (!InitImpl()) { 338 // If initialization fails, zero the symbols to avoid hard-to-understand 339 // bugs. 340 mSymbols = {}; 341 NS_WARNING("GLContext::InitWithPrefix failed!"); 342 return false; 343 } 344 345 reporter.SetSuccessful(); 346 return true; 347 } 348 349 static bool LoadSymbolsWithDesc(const SymbolLoader& loader, 350 const SymLoadStruct* list, const char* desc) { 351 const auto warnOnFailure = bool(desc); 352 if (loader.LoadSymbols(list, warnOnFailure)) return true; 353 354 ClearSymbols(list); 355 356 if (desc) { 357 const nsPrintfCString err("Failed to load symbols for %s.", desc); 358 NS_ERROR(err.BeginReading()); 359 } 360 return false; 361 } 362 363 bool GLContext::LoadExtSymbols(const SymbolLoader& loader, 364 const SymLoadStruct* list, GLExtensions ext) { 365 const char* extName = sExtensionNames[size_t(ext)]; 366 if (!LoadSymbolsWithDesc(loader, list, extName)) { 367 MarkExtensionUnsupported(ext); 368 return false; 369 } 370 return true; 371 }; 372 373 bool GLContext::LoadFeatureSymbols(const SymbolLoader& loader, 374 const SymLoadStruct* list, 375 GLFeature feature) { 376 const char* featureName = GetFeatureName(feature); 377 if (!LoadSymbolsWithDesc(loader, list, featureName)) { 378 MarkUnsupported(feature); 379 return false; 380 } 381 return true; 382 }; 383 384 bool GLContext::InitImpl() { 385 if (!MakeCurrent(true)) return false; 386 387 const auto loader = GetSymbolLoader(); 388 if (!loader) return false; 389 390 const auto fnLoadSymbols = [&](const SymLoadStruct* const list, 391 const char* const desc) { 392 return LoadSymbolsWithDesc(*loader, list, desc); 393 }; 394 395 // clang-format off 396 const SymLoadStruct coreSymbols[] = { 397 { (PRFuncPtr*) &mSymbols.fActiveTexture, {{ "glActiveTexture", "glActiveTextureARB" }} }, 398 { (PRFuncPtr*) &mSymbols.fAttachShader, {{ "glAttachShader", "glAttachShaderARB" }} }, 399 { (PRFuncPtr*) &mSymbols.fBindAttribLocation, {{ "glBindAttribLocation", "glBindAttribLocationARB" }} }, 400 { (PRFuncPtr*) &mSymbols.fBindBuffer, {{ "glBindBuffer", "glBindBufferARB" }} }, 401 { (PRFuncPtr*) &mSymbols.fBindTexture, {{ "glBindTexture", "glBindTextureARB" }} }, 402 { (PRFuncPtr*) &mSymbols.fBlendColor, {{ "glBlendColor" }} }, 403 { (PRFuncPtr*) &mSymbols.fBlendEquation, {{ "glBlendEquation" }} }, 404 { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, {{ "glBlendEquationSeparate", "glBlendEquationSeparateEXT" }} }, 405 { (PRFuncPtr*) &mSymbols.fBlendFunc, {{ "glBlendFunc" }} }, 406 { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, {{ "glBlendFuncSeparate", "glBlendFuncSeparateEXT" }} }, 407 { (PRFuncPtr*) &mSymbols.fBufferData, {{ "glBufferData" }} }, 408 { (PRFuncPtr*) &mSymbols.fBufferSubData, {{ "glBufferSubData" }} }, 409 { (PRFuncPtr*) &mSymbols.fClear, {{ "glClear" }} }, 410 { (PRFuncPtr*) &mSymbols.fClearColor, {{ "glClearColor" }} }, 411 { (PRFuncPtr*) &mSymbols.fClearStencil, {{ "glClearStencil" }} }, 412 { (PRFuncPtr*) &mSymbols.fColorMask, {{ "glColorMask" }} }, 413 { (PRFuncPtr*) &mSymbols.fCompressedTexImage2D, {{ "glCompressedTexImage2D" }} }, 414 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage2D, {{ "glCompressedTexSubImage2D" }} }, 415 { (PRFuncPtr*) &mSymbols.fCullFace, {{ "glCullFace" }} }, 416 { (PRFuncPtr*) &mSymbols.fDetachShader, {{ "glDetachShader", "glDetachShaderARB" }} }, 417 { (PRFuncPtr*) &mSymbols.fDepthFunc, {{ "glDepthFunc" }} }, 418 { (PRFuncPtr*) &mSymbols.fDepthMask, {{ "glDepthMask" }} }, 419 { (PRFuncPtr*) &mSymbols.fDisable, {{ "glDisable" }} }, 420 { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, {{ "glDisableVertexAttribArray", "glDisableVertexAttribArrayARB" }} }, 421 { (PRFuncPtr*) &mSymbols.fDrawArrays, {{ "glDrawArrays" }} }, 422 { (PRFuncPtr*) &mSymbols.fDrawElements, {{ "glDrawElements" }} }, 423 { (PRFuncPtr*) &mSymbols.fEnable, {{ "glEnable" }} }, 424 { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, {{ "glEnableVertexAttribArray", "glEnableVertexAttribArrayARB" }} }, 425 { (PRFuncPtr*) &mSymbols.fFinish, {{ "glFinish" }} }, 426 { (PRFuncPtr*) &mSymbols.fFlush, {{ "glFlush" }} }, 427 { (PRFuncPtr*) &mSymbols.fFrontFace, {{ "glFrontFace" }} }, 428 { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, {{ "glGetActiveAttrib", "glGetActiveAttribARB" }} }, 429 { (PRFuncPtr*) &mSymbols.fGetActiveUniform, {{ "glGetActiveUniform", "glGetActiveUniformARB" }} }, 430 { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, {{ "glGetAttachedShaders", "glGetAttachedShadersARB" }} }, 431 { (PRFuncPtr*) &mSymbols.fGetAttribLocation, {{ "glGetAttribLocation", "glGetAttribLocationARB" }} }, 432 { (PRFuncPtr*) &mSymbols.fGetIntegerv, {{ "glGetIntegerv" }} }, 433 { (PRFuncPtr*) &mSymbols.fGetFloatv, {{ "glGetFloatv" }} }, 434 { (PRFuncPtr*) &mSymbols.fGetBooleanv, {{ "glGetBooleanv" }} }, 435 { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, {{ "glGetBufferParameteriv", "glGetBufferParameterivARB" }} }, 436 { (PRFuncPtr*) &mSymbols.fGetError, {{ "glGetError" }} }, 437 { (PRFuncPtr*) &mSymbols.fGetProgramiv, {{ "glGetProgramiv", "glGetProgramivARB" }} }, 438 { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, {{ "glGetProgramInfoLog", "glGetProgramInfoLogARB" }} }, 439 { (PRFuncPtr*) &mSymbols.fTexParameteri, {{ "glTexParameteri" }} }, 440 { (PRFuncPtr*) &mSymbols.fTexParameteriv, {{ "glTexParameteriv" }} }, 441 { (PRFuncPtr*) &mSymbols.fTexParameterf, {{ "glTexParameterf" }} }, 442 { (PRFuncPtr*) &mSymbols.fGetString, {{ "glGetString" }} }, 443 { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, {{ "glGetTexParameterfv" }} }, 444 { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, {{ "glGetTexParameteriv" }} }, 445 { (PRFuncPtr*) &mSymbols.fGetUniformfv, {{ "glGetUniformfv", "glGetUniformfvARB" }} }, 446 { (PRFuncPtr*) &mSymbols.fGetUniformiv, {{ "glGetUniformiv", "glGetUniformivARB" }} }, 447 { (PRFuncPtr*) &mSymbols.fGetUniformLocation, {{ "glGetUniformLocation", "glGetUniformLocationARB" }} }, 448 { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, {{ "glGetVertexAttribfv", "glGetVertexAttribfvARB" }} }, 449 { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, {{ "glGetVertexAttribiv", "glGetVertexAttribivARB" }} }, 450 { (PRFuncPtr*) &mSymbols.fGetVertexAttribPointerv, {{ "glGetVertexAttribPointerv" }} }, 451 { (PRFuncPtr*) &mSymbols.fHint, {{ "glHint" }} }, 452 { (PRFuncPtr*) &mSymbols.fIsBuffer, {{ "glIsBuffer", "glIsBufferARB" }} }, 453 { (PRFuncPtr*) &mSymbols.fIsEnabled, {{ "glIsEnabled" }} }, 454 { (PRFuncPtr*) &mSymbols.fIsProgram, {{ "glIsProgram", "glIsProgramARB" }} }, 455 { (PRFuncPtr*) &mSymbols.fIsShader, {{ "glIsShader", "glIsShaderARB" }} }, 456 { (PRFuncPtr*) &mSymbols.fIsTexture, {{ "glIsTexture", "glIsTextureARB" }} }, 457 { (PRFuncPtr*) &mSymbols.fLineWidth, {{ "glLineWidth" }} }, 458 { (PRFuncPtr*) &mSymbols.fLinkProgram, {{ "glLinkProgram", "glLinkProgramARB" }} }, 459 { (PRFuncPtr*) &mSymbols.fPixelStorei, {{ "glPixelStorei" }} }, 460 { (PRFuncPtr*) &mSymbols.fPolygonOffset, {{ "glPolygonOffset" }} }, 461 { (PRFuncPtr*) &mSymbols.fReadPixels, {{ "glReadPixels" }} }, 462 { (PRFuncPtr*) &mSymbols.fSampleCoverage, {{ "glSampleCoverage" }} }, 463 { (PRFuncPtr*) &mSymbols.fScissor, {{ "glScissor" }} }, 464 { (PRFuncPtr*) &mSymbols.fStencilFunc, {{ "glStencilFunc" }} }, 465 { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, {{ "glStencilFuncSeparate", "glStencilFuncSeparateEXT" }} }, 466 { (PRFuncPtr*) &mSymbols.fStencilMask, {{ "glStencilMask" }} }, 467 { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, {{ "glStencilMaskSeparate", "glStencilMaskSeparateEXT" }} }, 468 { (PRFuncPtr*) &mSymbols.fStencilOp, {{ "glStencilOp" }} }, 469 { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, {{ "glStencilOpSeparate", "glStencilOpSeparateEXT" }} }, 470 { (PRFuncPtr*) &mSymbols.fTexImage2D, {{ "glTexImage2D" }} }, 471 { (PRFuncPtr*) &mSymbols.fTexSubImage2D, {{ "glTexSubImage2D" }} }, 472 { (PRFuncPtr*) &mSymbols.fUniform1f, {{ "glUniform1f" }} }, 473 { (PRFuncPtr*) &mSymbols.fUniform1fv, {{ "glUniform1fv" }} }, 474 { (PRFuncPtr*) &mSymbols.fUniform1i, {{ "glUniform1i" }} }, 475 { (PRFuncPtr*) &mSymbols.fUniform1iv, {{ "glUniform1iv" }} }, 476 { (PRFuncPtr*) &mSymbols.fUniform2f, {{ "glUniform2f" }} }, 477 { (PRFuncPtr*) &mSymbols.fUniform2fv, {{ "glUniform2fv" }} }, 478 { (PRFuncPtr*) &mSymbols.fUniform2i, {{ "glUniform2i" }} }, 479 { (PRFuncPtr*) &mSymbols.fUniform2iv, {{ "glUniform2iv" }} }, 480 { (PRFuncPtr*) &mSymbols.fUniform3f, {{ "glUniform3f" }} }, 481 { (PRFuncPtr*) &mSymbols.fUniform3fv, {{ "glUniform3fv" }} }, 482 { (PRFuncPtr*) &mSymbols.fUniform3i, {{ "glUniform3i" }} }, 483 { (PRFuncPtr*) &mSymbols.fUniform3iv, {{ "glUniform3iv" }} }, 484 { (PRFuncPtr*) &mSymbols.fUniform4f, {{ "glUniform4f" }} }, 485 { (PRFuncPtr*) &mSymbols.fUniform4fv, {{ "glUniform4fv" }} }, 486 { (PRFuncPtr*) &mSymbols.fUniform4i, {{ "glUniform4i" }} }, 487 { (PRFuncPtr*) &mSymbols.fUniform4iv, {{ "glUniform4iv" }} }, 488 { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, {{ "glUniformMatrix2fv" }} }, 489 { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, {{ "glUniformMatrix3fv" }} }, 490 { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, {{ "glUniformMatrix4fv" }} }, 491 { (PRFuncPtr*) &mSymbols.fUseProgram, {{ "glUseProgram" }} }, 492 { (PRFuncPtr*) &mSymbols.fValidateProgram, {{ "glValidateProgram" }} }, 493 { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, {{ "glVertexAttribPointer" }} }, 494 { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, {{ "glVertexAttrib1f" }} }, 495 { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, {{ "glVertexAttrib2f" }} }, 496 { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, {{ "glVertexAttrib3f" }} }, 497 { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, {{ "glVertexAttrib4f" }} }, 498 { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, {{ "glVertexAttrib1fv" }} }, 499 { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, {{ "glVertexAttrib2fv" }} }, 500 { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, {{ "glVertexAttrib3fv" }} }, 501 { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, {{ "glVertexAttrib4fv" }} }, 502 { (PRFuncPtr*) &mSymbols.fViewport, {{ "glViewport" }} }, 503 { (PRFuncPtr*) &mSymbols.fCompileShader, {{ "glCompileShader" }} }, 504 { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, {{ "glCopyTexImage2D" }} }, 505 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, {{ "glCopyTexSubImage2D" }} }, 506 { (PRFuncPtr*) &mSymbols.fGetShaderiv, {{ "glGetShaderiv" }} }, 507 { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, {{ "glGetShaderInfoLog" }} }, 508 { (PRFuncPtr*) &mSymbols.fGetShaderSource, {{ "glGetShaderSource" }} }, 509 { (PRFuncPtr*) &mSymbols.fShaderSource, {{ "glShaderSource" }} }, 510 { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, {{ "glVertexAttribPointer" }} }, 511 512 { (PRFuncPtr*) &mSymbols.fGenBuffers, {{ "glGenBuffers", "glGenBuffersARB" }} }, 513 { (PRFuncPtr*) &mSymbols.fGenTextures, {{ "glGenTextures" }} }, 514 { (PRFuncPtr*) &mSymbols.fCreateProgram, {{ "glCreateProgram", "glCreateProgramARB" }} }, 515 { (PRFuncPtr*) &mSymbols.fCreateShader, {{ "glCreateShader", "glCreateShaderARB" }} }, 516 517 { (PRFuncPtr*) &mSymbols.fDeleteBuffers, {{ "glDeleteBuffers", "glDeleteBuffersARB" }} }, 518 { (PRFuncPtr*) &mSymbols.fDeleteTextures, {{ "glDeleteTextures", "glDeleteTexturesARB" }} }, 519 { (PRFuncPtr*) &mSymbols.fDeleteProgram, {{ "glDeleteProgram", "glDeleteProgramARB" }} }, 520 { (PRFuncPtr*) &mSymbols.fDeleteShader, {{ "glDeleteShader", "glDeleteShaderARB" }} }, 521 522 END_SYMBOLS 523 }; 524 // clang-format on 525 526 if (!fnLoadSymbols(coreSymbols, "GL")) return false; 527 528 { 529 const SymLoadStruct symbols[] = { 530 {(PRFuncPtr*)&mSymbols.fGetGraphicsResetStatus, 531 {{"glGetGraphicsResetStatus", "glGetGraphicsResetStatusARB", 532 "glGetGraphicsResetStatusKHR", "glGetGraphicsResetStatusEXT"}}}, 533 END_SYMBOLS}; 534 (void)fnLoadSymbols(symbols, nullptr); 535 536 // We need to call the fGetError symbol directly here because if there is an 537 // unflushed reset status, we don't want to mark the context as lost. That 538 // would prevent us from recovering. 539 auto err = mSymbols.fGetError(); 540 if (err == LOCAL_GL_CONTEXT_LOST) { 541 MOZ_ASSERT(mSymbols.fGetGraphicsResetStatus); 542 const auto status = fGetGraphicsResetStatus(); 543 if (status) { 544 printf_stderr("Unflushed glGetGraphicsResetStatus: 0x%04x\n", status); 545 } 546 err = fGetError(); 547 MOZ_ASSERT(!err); 548 } 549 if (err) { 550 MOZ_ASSERT(false); 551 return false; 552 } 553 } 554 555 //////////////// 556 557 const auto* const versionRawStr = (const char*)fGetString(LOCAL_GL_VERSION); 558 if (!versionRawStr || !*versionRawStr) { 559 // This can happen with Pernosco. 560 NS_WARNING("Empty GL version string"); 561 return false; 562 } 563 564 const std::string versionStr = versionRawStr; 565 if (versionStr.find("OpenGL ES") == 0) { 566 mProfile = ContextProfile::OpenGLES; 567 } 568 569 uint32_t majorVer, minorVer; 570 if (!ParseVersion(versionStr, &majorVer, &minorVer)) { 571 MOZ_ASSERT(false, "Failed to parse GL_VERSION"); 572 return false; 573 } 574 MOZ_ASSERT(majorVer < 10); 575 MOZ_ASSERT(minorVer < 10); 576 mVersion = majorVer * 100 + minorVer * 10; 577 if (mVersion < 200) return false; 578 579 //// 580 581 const auto glslVersionStr = 582 (const char*)fGetString(LOCAL_GL_SHADING_LANGUAGE_VERSION); 583 if (!glslVersionStr) { 584 // This happens on the Android emulators. We'll just return 100 585 mShadingLanguageVersion = 100; 586 } else if (ParseVersion(glslVersionStr, &majorVer, &minorVer)) { 587 MOZ_ASSERT(majorVer < 10); 588 MOZ_ASSERT(minorVer < 100); 589 mShadingLanguageVersion = majorVer * 100 + minorVer; 590 } else { 591 MOZ_ASSERT(false, "Failed to parse GL_SHADING_LANGUAGE_VERSION"); 592 return false; 593 } 594 595 if (ShouldSpew()) { 596 printf_stderr("GL version detected: %u\n", mVersion); 597 printf_stderr("GLSL version detected: %u\n", mShadingLanguageVersion); 598 printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR)); 599 printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER)); 600 } 601 602 //////////////// 603 604 // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2. 605 if (mProfile == ContextProfile::OpenGLES) { 606 const SymLoadStruct symbols[] = {CORE_SYMBOL(GetShaderPrecisionFormat), 607 CORE_SYMBOL(ClearDepthf), 608 CORE_SYMBOL(DepthRangef), END_SYMBOLS}; 609 610 if (!fnLoadSymbols(symbols, "OpenGL ES")) return false; 611 } else { 612 const SymLoadStruct symbols[] = { 613 CORE_SYMBOL(ClearDepth), CORE_SYMBOL(DepthRange), 614 CORE_SYMBOL(ReadBuffer), CORE_SYMBOL(MapBuffer), 615 CORE_SYMBOL(UnmapBuffer), CORE_SYMBOL(PointParameterf), 616 CORE_SYMBOL(DrawBuffer), 617 // The following functions are only used by Skia/GL in desktop mode. 618 // Other parts of Gecko should avoid using these 619 CORE_SYMBOL(DrawBuffers), CORE_SYMBOL(ClientActiveTexture), 620 CORE_SYMBOL(DisableClientState), CORE_SYMBOL(EnableClientState), 621 CORE_SYMBOL(LoadIdentity), CORE_SYMBOL(LoadMatrixf), 622 CORE_SYMBOL(MatrixMode), CORE_SYMBOL(PolygonMode), CORE_SYMBOL(TexGeni), 623 CORE_SYMBOL(TexGenf), CORE_SYMBOL(TexGenfv), CORE_SYMBOL(VertexPointer), 624 END_SYMBOLS}; 625 626 if (!fnLoadSymbols(symbols, "Desktop OpenGL")) return false; 627 } 628 629 //////////////// 630 631 const char* glVendorString = (const char*)fGetString(LOCAL_GL_VENDOR); 632 const char* glRendererString = (const char*)fGetString(LOCAL_GL_RENDERER); 633 if (!glVendorString || !glRendererString) return false; 634 635 // The order of these strings must match up with the order of the enum 636 // defined in GLContext.h for vendor IDs. 637 const char* vendorMatchStrings[size_t(GLVendor::Other) + 1] = { 638 "Intel", "NVIDIA", "ATI", "Qualcomm", "Imagination", 639 "nouveau", "Vivante", "VMware, Inc.", "ARM", "Unknown"}; 640 641 mVendor = GLVendor::Other; 642 for (size_t i = 0; i < size_t(GLVendor::Other); ++i) { 643 if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) { 644 mVendor = GLVendor(i); 645 break; 646 } 647 } 648 649 // The order of these strings must match up with the order of the enum 650 // defined in GLContext.h for renderer IDs. 651 const char* rendererMatchStrings[size_t(GLRenderer::Other) + 1] = { 652 "Adreno 200", 653 "Adreno 205", 654 "Adreno (TM) 200", 655 "Adreno (TM) 205", 656 "Adreno (TM) 305", 657 "Adreno (TM) 320", 658 "Adreno (TM) 330", 659 "Adreno (TM) 420", 660 "Mali-400 MP", 661 "Mali-450 MP", 662 "Mali-T", 663 "PowerVR SGX 530", 664 "PowerVR SGX 540", 665 "PowerVR SGX 544MP", 666 "NVIDIA Tegra", 667 "Android Emulator", 668 "Gallium 0.4 on llvmpipe", 669 "Microsoft Basic Render Driver", 670 "Samsung Xclipse", 671 "Unknown"}; 672 673 mRenderer = GLRenderer::Other; 674 for (size_t i = 0; i < size_t(GLRenderer::Other); ++i) { 675 if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) { 676 mRenderer = GLRenderer(i); 677 break; 678 } 679 } 680 681 { 682 const auto versionStr = (const char*)fGetString(LOCAL_GL_VERSION); 683 if (strstr(versionStr, "Mesa")) { 684 mIsMesa = true; 685 } 686 } 687 688 const auto Once = []() { 689 static bool did = false; 690 if (did) return false; 691 did = true; 692 return true; 693 }; 694 695 bool printRenderer = ShouldSpew(); 696 printRenderer |= (kIsDebug && Once()); 697 if (printRenderer) { 698 printf_stderr("GL_VENDOR: %s\n", glVendorString); 699 printf_stderr("mVendor: %s\n", vendorMatchStrings[size_t(mVendor)]); 700 printf_stderr("GL_RENDERER: %s\n", glRendererString); 701 printf_stderr("mRenderer: %s\n", rendererMatchStrings[size_t(mRenderer)]); 702 printf_stderr("mIsMesa: %i\n", int(mIsMesa)); 703 } 704 705 //////////////// 706 707 if (mVersion >= 300) { // Both GL3 and ES3. 708 const SymLoadStruct symbols[] = { 709 {(PRFuncPtr*)&mSymbols.fGetStringi, {{"glGetStringi"}}}, END_SYMBOLS}; 710 711 if (!fnLoadSymbols(symbols, "GetStringi")) { 712 MOZ_RELEASE_ASSERT(false, "GFX: GetStringi is required!"); 713 return false; 714 } 715 } 716 717 InitExtensions(); 718 if (mProfile != ContextProfile::OpenGLES) { 719 if (mVersion >= 310 && !IsExtensionSupported(ARB_compatibility)) { 720 mProfile = ContextProfile::OpenGLCore; 721 } else { 722 mProfile = ContextProfile::OpenGLCompatibility; 723 } 724 } 725 MOZ_ASSERT(mProfile != ContextProfile::Unknown); 726 727 if (ShouldSpew()) { 728 const char* profileStr = ""; 729 if (mProfile == ContextProfile::OpenGLES) { 730 profileStr = " es"; 731 } else if (mProfile == ContextProfile::OpenGLCore) { 732 profileStr = " core"; 733 } 734 printf_stderr("Detected profile: %u%s\n", mVersion, profileStr); 735 } 736 737 InitFeatures(); 738 739 //// 740 741 // Disable extensions with partial or incorrect support. 742 if (WorkAroundDriverBugs()) { 743 if (Renderer() == GLRenderer::AdrenoTM320) { 744 MarkUnsupported(GLFeature::standard_derivatives); 745 } 746 747 if (Renderer() == GLRenderer::AndroidEmulator) { 748 // Bug 1665300 749 mSymbols.fGetGraphicsResetStatus = 0; 750 } 751 752 if (Vendor() == GLVendor::Vivante) { 753 // bug 958256 754 MarkUnsupported(GLFeature::standard_derivatives); 755 } 756 757 if (Renderer() == GLRenderer::MicrosoftBasicRenderDriver) { 758 // Bug 978966: on Microsoft's "Basic Render Driver" (software renderer) 759 // multisampling hardcodes blending with the default blendfunc, which 760 // breaks WebGL. 761 MarkUnsupported(GLFeature::framebuffer_multisample); 762 } 763 764 if (IsMesa()) { 765 // DrawElementsInstanced hangs the driver. 766 MarkUnsupported(GLFeature::robust_buffer_access_behavior); 767 } 768 769 if (Renderer() == GLRenderer::SamsungXclipse) { 770 MarkUnsupported(GLFeature::invalidate_framebuffer); 771 } 772 } 773 774 if (IsExtensionSupported(GLContext::ARB_pixel_buffer_object)) { 775 MOZ_ASSERT( 776 (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer), 777 "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer" 778 " being available!"); 779 } 780 781 //////////////////////////////////////////////////////////////////////////// 782 783 const auto fnLoadForFeature = [&](const SymLoadStruct* list, 784 GLFeature feature) { 785 return this->LoadFeatureSymbols(*loader, list, feature); 786 }; 787 788 // Check for ARB_framebuffer_objects 789 if (IsSupported(GLFeature::framebuffer_object)) { 790 // https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt 791 const SymLoadStruct symbols[] = { 792 CORE_SYMBOL(IsRenderbuffer), 793 CORE_SYMBOL(BindRenderbuffer), 794 CORE_SYMBOL(DeleteRenderbuffers), 795 CORE_SYMBOL(GenRenderbuffers), 796 CORE_SYMBOL(RenderbufferStorage), 797 CORE_SYMBOL(RenderbufferStorageMultisample), 798 CORE_SYMBOL(GetRenderbufferParameteriv), 799 CORE_SYMBOL(IsFramebuffer), 800 CORE_SYMBOL(BindFramebuffer), 801 CORE_SYMBOL(DeleteFramebuffers), 802 CORE_SYMBOL(GenFramebuffers), 803 CORE_SYMBOL(CheckFramebufferStatus), 804 CORE_SYMBOL(FramebufferTexture2D), 805 CORE_SYMBOL(FramebufferTextureLayer), 806 CORE_SYMBOL(FramebufferRenderbuffer), 807 CORE_SYMBOL(GetFramebufferAttachmentParameteriv), 808 CORE_SYMBOL(BlitFramebuffer), 809 CORE_SYMBOL(GenerateMipmap), 810 END_SYMBOLS}; 811 fnLoadForFeature(symbols, GLFeature::framebuffer_object); 812 } 813 814 if (!IsSupported(GLFeature::framebuffer_object)) { 815 // Check for aux symbols based on extensions 816 if (IsSupported(GLFeature::framebuffer_object_EXT_OES)) { 817 const SymLoadStruct symbols[] = { 818 CORE_EXT_SYMBOL2(IsRenderbuffer, EXT, OES), 819 CORE_EXT_SYMBOL2(BindRenderbuffer, EXT, OES), 820 CORE_EXT_SYMBOL2(DeleteRenderbuffers, EXT, OES), 821 CORE_EXT_SYMBOL2(GenRenderbuffers, EXT, OES), 822 CORE_EXT_SYMBOL2(RenderbufferStorage, EXT, OES), 823 CORE_EXT_SYMBOL2(GetRenderbufferParameteriv, EXT, OES), 824 CORE_EXT_SYMBOL2(IsFramebuffer, EXT, OES), 825 CORE_EXT_SYMBOL2(BindFramebuffer, EXT, OES), 826 CORE_EXT_SYMBOL2(DeleteFramebuffers, EXT, OES), 827 CORE_EXT_SYMBOL2(GenFramebuffers, EXT, OES), 828 CORE_EXT_SYMBOL2(CheckFramebufferStatus, EXT, OES), 829 CORE_EXT_SYMBOL2(FramebufferTexture2D, EXT, OES), 830 CORE_EXT_SYMBOL2(FramebufferRenderbuffer, EXT, OES), 831 CORE_EXT_SYMBOL2(GetFramebufferAttachmentParameteriv, EXT, OES), 832 CORE_EXT_SYMBOL2(GenerateMipmap, EXT, OES), 833 END_SYMBOLS}; 834 fnLoadForFeature(symbols, GLFeature::framebuffer_object_EXT_OES); 835 } 836 837 if (IsSupported(GLFeature::framebuffer_blit)) { 838 const SymLoadStruct symbols[] = { 839 EXT_SYMBOL3(BlitFramebuffer, ANGLE, EXT, NV), END_SYMBOLS}; 840 fnLoadForFeature(symbols, GLFeature::framebuffer_blit); 841 } 842 843 if (IsSupported(GLFeature::framebuffer_multisample)) { 844 const SymLoadStruct symbols[] = { 845 EXT_SYMBOL3(RenderbufferStorageMultisample, ANGLE, APPLE, EXT), 846 END_SYMBOLS}; 847 fnLoadForFeature(symbols, GLFeature::framebuffer_multisample); 848 } 849 850 if (IsExtensionSupported(GLContext::ARB_geometry_shader4) || 851 IsExtensionSupported(GLContext::NV_geometry_program4)) { 852 const SymLoadStruct symbols[] = { 853 EXT_SYMBOL2(FramebufferTextureLayer, ARB, EXT), END_SYMBOLS}; 854 if (!fnLoadSymbols(symbols, 855 "ARB_geometry_shader4/NV_geometry_program4")) { 856 MarkExtensionUnsupported(GLContext::ARB_geometry_shader4); 857 MarkExtensionUnsupported(GLContext::NV_geometry_program4); 858 } 859 } 860 } 861 862 if (!IsSupported(GLFeature::framebuffer_object) && 863 !IsSupported(GLFeature::framebuffer_object_EXT_OES)) { 864 NS_ERROR("GLContext requires support for framebuffer objects."); 865 return false; 866 } 867 MOZ_RELEASE_ASSERT(mSymbols.fBindFramebuffer, 868 "GFX: mSymbols.fBindFramebuffer zero or not set."); 869 870 //////////////// 871 872 const auto err = fGetError(); 873 MOZ_RELEASE_ASSERT(!IsBadCallError(err)); 874 if (err) return false; 875 876 LoadMoreSymbols(*loader); 877 878 //////////////////////////////////////////////////////////////////////////// 879 880 raw_fGetIntegerv(LOCAL_GL_VIEWPORT, mViewportRect); 881 raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mScissorRect); 882 raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); 883 raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize); 884 raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize); 885 raw_fGetIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS, mMaxViewportDims); 886 887 if (mWorkAroundDriverBugs) { 888 int maxTexSize = INT32_MAX; 889 int maxCubeSize = INT32_MAX; 890 #ifdef XP_MACOSX 891 // https://bugzilla.mozilla.org/show_bug.cgi?id=1544446 892 // Mojave exposes 16k textures, but gives FRAMEBUFFER_UNSUPPORTED for any 893 // 16k*16k FB except rgba8 without depth/stencil. 894 // The max supported sizes changes based on involved formats. 895 // (RGBA32F more restrictive than RGBA16F) 896 maxTexSize = 8192; 897 #endif 898 #ifdef MOZ_X11 899 if (mVendor == GLVendor::Nouveau) { 900 // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau. 901 maxCubeSize = 2048; 902 } else if (mVendor == GLVendor::Intel) { 903 // Bug 1199923. Driver seems to report a larger max size than 904 // actually supported. 905 maxTexSize = mMaxTextureSize / 2; 906 } 907 // Bug 1367570. Explicitly set vertex attributes [1,3] to opaque 908 // black because Nvidia doesn't do it for us. 909 if (mVendor == GLVendor::NVIDIA) { 910 for (size_t i = 1; i <= 3; ++i) { 911 mSymbols.fVertexAttrib4f(i, 0, 0, 0, 1); 912 } 913 } 914 #endif 915 if (Renderer() == GLRenderer::AdrenoTM420) { 916 // see bug 1194923. Calling glFlush before glDeleteFramebuffers 917 // prevents occasional driver crash. 918 mNeedsFlushBeforeDeleteFB = true; 919 } 920 921 // - 922 923 const auto fnLimit = [&](int* const driver, const int limit) { 924 if (*driver > limit) { 925 *driver = limit; 926 mNeedsTextureSizeChecks = true; 927 } 928 }; 929 930 fnLimit(&mMaxTextureSize, maxTexSize); 931 fnLimit(&mMaxRenderbufferSize, maxTexSize); 932 933 maxCubeSize = std::min(maxCubeSize, maxTexSize); 934 fnLimit(&mMaxCubeMapTextureSize, maxCubeSize); 935 } 936 937 if (IsSupported(GLFeature::framebuffer_multisample)) { 938 fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples); 939 } 940 941 mMaxTexOrRbSize = std::min(mMaxTextureSize, mMaxRenderbufferSize); 942 943 #ifdef MOZ_WIDGET_ANDROID 944 if (Renderer() == GLRenderer::SamsungXclipse && jni::GetAPIVersion() >= 35) { 945 // On Samsung Xclipse GPUs on Android 15 attribute values for the final 946 // vertex in a buffer may be incorrect. Padding the buffer to contain 947 // enough space for an additional vertex avoids the issue. See bug 1983036. 948 GLint maxVertexAttribStride; 949 raw_fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIB_STRIDE, &maxVertexAttribStride); 950 mVertexBufferExtraPadding = Some(maxVertexAttribStride); 951 } 952 #endif 953 954 //////////////////////////////////////////////////////////////////////////// 955 956 // We're ready for final setup. 957 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); 958 MOZ_GL_ASSERT(this, IsCurrent()); 959 960 if (ShouldSpew() && IsExtensionSupported(KHR_debug)) { 961 fEnable(LOCAL_GL_DEBUG_OUTPUT); 962 fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS); 963 fDebugMessageCallback(&StaticDebugCallback, (void*)this); 964 fDebugMessageControl(LOCAL_GL_DONT_CARE, LOCAL_GL_DONT_CARE, 965 LOCAL_GL_DONT_CARE, 0, nullptr, true); 966 } 967 968 return true; 969 } 970 971 void GLContext::LoadMoreSymbols(const SymbolLoader& loader) { 972 const auto fnLoadForExt = [&](const SymLoadStruct* list, GLExtensions ext) { 973 return this->LoadExtSymbols(loader, list, ext); 974 }; 975 976 const auto fnLoadForFeature = [&](const SymLoadStruct* list, 977 GLFeature feature) { 978 return this->LoadFeatureSymbols(loader, list, feature); 979 }; 980 981 const auto fnLoadFeatureByCore = [&](const SymLoadStruct* coreList, 982 const SymLoadStruct* extList, 983 GLFeature feature) { 984 const bool useCore = this->IsFeatureProvidedByCoreSymbols(feature); 985 const auto list = useCore ? coreList : extList; 986 return fnLoadForFeature(list, feature); 987 }; 988 989 if (IsSupported(GLFeature::robustness)) { 990 const auto resetStrategy = 991 GetIntAs<GLuint>(LOCAL_GL_RESET_NOTIFICATION_STRATEGY); 992 if (resetStrategy != LOCAL_GL_LOSE_CONTEXT_ON_RESET) { 993 NS_WARNING( 994 "Robustness supported, strategy is not LOSE_CONTEXT_ON_RESET!"); 995 if (ShouldSpew()) { 996 const bool isDisabled = 997 (resetStrategy == LOCAL_GL_NO_RESET_NOTIFICATION); 998 printf_stderr("Strategy: %s (0x%04x)", 999 (isDisabled ? "disabled" : "unrecognized"), 1000 resetStrategy); 1001 } 1002 MarkUnsupported(GLFeature::robustness); 1003 } 1004 } 1005 1006 if (IsSupported(GLFeature::sync)) { 1007 const SymLoadStruct symbols[] = { 1008 CORE_SYMBOL(FenceSync), CORE_SYMBOL(IsSync), 1009 CORE_SYMBOL(DeleteSync), CORE_SYMBOL(ClientWaitSync), 1010 CORE_SYMBOL(WaitSync), CORE_SYMBOL(GetInteger64v), 1011 CORE_SYMBOL(GetSynciv), END_SYMBOLS}; 1012 fnLoadForFeature(symbols, GLFeature::sync); 1013 } 1014 1015 if (IsExtensionSupported(OES_EGL_image)) { 1016 const SymLoadStruct symbols[] = { 1017 {(PRFuncPtr*)&mSymbols.fEGLImageTargetTexture2D, 1018 {{"glEGLImageTargetTexture2DOES"}}}, 1019 {(PRFuncPtr*)&mSymbols.fEGLImageTargetRenderbufferStorage, 1020 {{"glEGLImageTargetRenderbufferStorageOES"}}}, 1021 END_SYMBOLS}; 1022 fnLoadForExt(symbols, OES_EGL_image); 1023 } 1024 1025 if (IsExtensionSupported(APPLE_texture_range)) { 1026 const SymLoadStruct symbols[] = {CORE_SYMBOL(TextureRangeAPPLE), 1027 END_SYMBOLS}; 1028 fnLoadForExt(symbols, APPLE_texture_range); 1029 } 1030 1031 if (IsExtensionSupported(APPLE_fence)) { 1032 const SymLoadStruct symbols[] = {CORE_SYMBOL(FinishObjectAPPLE), 1033 CORE_SYMBOL(TestObjectAPPLE), END_SYMBOLS}; 1034 fnLoadForExt(symbols, APPLE_fence); 1035 } 1036 1037 // clang-format off 1038 1039 if (IsSupported(GLFeature::vertex_array_object)) { 1040 const SymLoadStruct coreSymbols[] = { 1041 { (PRFuncPtr*) &mSymbols.fIsVertexArray, {{ "glIsVertexArray" }} }, 1042 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, {{ "glGenVertexArrays" }} }, 1043 { (PRFuncPtr*) &mSymbols.fBindVertexArray, {{ "glBindVertexArray" }} }, 1044 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, {{ "glDeleteVertexArrays" }} }, 1045 END_SYMBOLS 1046 }; 1047 const SymLoadStruct extSymbols[] = { 1048 { (PRFuncPtr*) &mSymbols.fIsVertexArray, {{ "glIsVertexArrayARB", "glIsVertexArrayOES", "glIsVertexArrayAPPLE" }} }, 1049 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, {{ "glGenVertexArraysARB", "glGenVertexArraysOES", "glGenVertexArraysAPPLE" }} }, 1050 { (PRFuncPtr*) &mSymbols.fBindVertexArray, {{ "glBindVertexArrayARB", "glBindVertexArrayOES", "glBindVertexArrayAPPLE" }} }, 1051 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, {{ "glDeleteVertexArraysARB", "glDeleteVertexArraysOES", "glDeleteVertexArraysAPPLE" }} }, 1052 END_SYMBOLS 1053 }; 1054 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::vertex_array_object); 1055 } 1056 1057 if (IsSupported(GLFeature::draw_instanced)) { 1058 const SymLoadStruct coreSymbols[] = { 1059 { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, {{ "glDrawArraysInstanced" }} }, 1060 { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, {{ "glDrawElementsInstanced" }} }, 1061 END_SYMBOLS 1062 }; 1063 const SymLoadStruct extSymbols[] = { 1064 { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, {{ "glDrawArraysInstancedARB", "glDrawArraysInstancedEXT", "glDrawArraysInstancedNV", "glDrawArraysInstancedANGLE" }} }, 1065 { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, {{ "glDrawElementsInstancedARB", "glDrawElementsInstancedEXT", "glDrawElementsInstancedNV", "glDrawElementsInstancedANGLE" }} 1066 }, 1067 END_SYMBOLS 1068 }; 1069 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_instanced); 1070 } 1071 1072 if (IsSupported(GLFeature::instanced_arrays)) { 1073 const SymLoadStruct coreSymbols[] = { 1074 { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, {{ "glVertexAttribDivisor" }} }, 1075 END_SYMBOLS 1076 }; 1077 const SymLoadStruct extSymbols[] = { 1078 { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, {{ "glVertexAttribDivisorARB", "glVertexAttribDivisorNV", "glVertexAttribDivisorANGLE" }} }, 1079 END_SYMBOLS 1080 }; 1081 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::instanced_arrays); 1082 } 1083 1084 if (IsSupported(GLFeature::texture_storage)) { 1085 const SymLoadStruct coreSymbols[] = { 1086 { (PRFuncPtr*) &mSymbols.fTexStorage2D, {{ "glTexStorage2D" }} }, 1087 { (PRFuncPtr*) &mSymbols.fTexStorage3D, {{ "glTexStorage3D" }} }, 1088 END_SYMBOLS 1089 }; 1090 const SymLoadStruct extSymbols[] = { 1091 { (PRFuncPtr*) &mSymbols.fTexStorage2D, {{ "glTexStorage2DEXT" }} }, 1092 { (PRFuncPtr*) &mSymbols.fTexStorage3D, {{ "glTexStorage3DEXT" }} }, 1093 END_SYMBOLS 1094 }; 1095 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_storage); 1096 } 1097 1098 if (IsSupported(GLFeature::sampler_objects)) { 1099 const SymLoadStruct symbols[] = { 1100 { (PRFuncPtr*) &mSymbols.fGenSamplers, {{ "glGenSamplers" }} }, 1101 { (PRFuncPtr*) &mSymbols.fDeleteSamplers, {{ "glDeleteSamplers" }} }, 1102 { (PRFuncPtr*) &mSymbols.fIsSampler, {{ "glIsSampler" }} }, 1103 { (PRFuncPtr*) &mSymbols.fBindSampler, {{ "glBindSampler" }} }, 1104 { (PRFuncPtr*) &mSymbols.fSamplerParameteri, {{ "glSamplerParameteri" }} }, 1105 { (PRFuncPtr*) &mSymbols.fSamplerParameteriv, {{ "glSamplerParameteriv" }} }, 1106 { (PRFuncPtr*) &mSymbols.fSamplerParameterf, {{ "glSamplerParameterf" }} }, 1107 { (PRFuncPtr*) &mSymbols.fSamplerParameterfv, {{ "glSamplerParameterfv" }} }, 1108 { (PRFuncPtr*) &mSymbols.fGetSamplerParameteriv, {{ "glGetSamplerParameteriv" }} }, 1109 { (PRFuncPtr*) &mSymbols.fGetSamplerParameterfv, {{ "glGetSamplerParameterfv" }} }, 1110 END_SYMBOLS 1111 }; 1112 fnLoadForFeature(symbols, GLFeature::sampler_objects); 1113 } 1114 1115 // ARB_transform_feedback2/NV_transform_feedback2 is a 1116 // superset of EXT_transform_feedback/NV_transform_feedback 1117 // and adds glPauseTransformFeedback & 1118 // glResumeTransformFeedback, which are required for WebGL2. 1119 if (IsSupported(GLFeature::transform_feedback2)) { 1120 const SymLoadStruct coreSymbols[] = { 1121 { (PRFuncPtr*) &mSymbols.fBindBufferBase, {{ "glBindBufferBase" }} }, 1122 { (PRFuncPtr*) &mSymbols.fBindBufferRange, {{ "glBindBufferRange" }} }, 1123 { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, {{ "glGenTransformFeedbacks" }} }, 1124 { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, {{ "glBindTransformFeedback" }} }, 1125 { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, {{ "glDeleteTransformFeedbacks" }} }, 1126 { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, {{ "glIsTransformFeedback" }} }, 1127 { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, {{ "glBeginTransformFeedback" }} }, 1128 { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, {{ "glEndTransformFeedback" }} }, 1129 { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, {{ "glTransformFeedbackVaryings" }} }, 1130 { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, {{ "glGetTransformFeedbackVarying" }} }, 1131 { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, {{ "glPauseTransformFeedback" }} }, 1132 { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, {{ "glResumeTransformFeedback" }} }, 1133 END_SYMBOLS 1134 }; 1135 const SymLoadStruct extSymbols[] = { 1136 { (PRFuncPtr*) &mSymbols.fBindBufferBase, {{ "glBindBufferBaseEXT", "glBindBufferBaseNV" }} }, 1137 { (PRFuncPtr*) &mSymbols.fBindBufferRange, {{ "glBindBufferRangeEXT", "glBindBufferRangeNV" }} }, 1138 { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, {{ "glGenTransformFeedbacksNV" }} }, 1139 { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, {{ "glBindTransformFeedbackNV" }} }, 1140 { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, {{ "glDeleteTransformFeedbacksNV" }} }, 1141 { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, {{ "glIsTransformFeedbackNV" }} }, 1142 { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, {{ "glBeginTransformFeedbackEXT", "glBeginTransformFeedbackNV" }} }, 1143 { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, {{ "glEndTransformFeedbackEXT", "glEndTransformFeedbackNV" }} }, 1144 { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, {{ "glTransformFeedbackVaryingsEXT", "glTransformFeedbackVaryingsNV" }} }, 1145 { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, {{ "glGetTransformFeedbackVaryingEXT", "glGetTransformFeedbackVaryingNV" }} }, 1146 { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, {{ "glPauseTransformFeedbackNV" }} }, 1147 { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, {{ "glResumeTransformFeedbackNV" }} }, 1148 END_SYMBOLS 1149 }; 1150 if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::transform_feedback2)) { 1151 // Also mark bind_buffer_offset as unsupported. 1152 MarkUnsupported(GLFeature::bind_buffer_offset); 1153 } 1154 } 1155 1156 if (IsSupported(GLFeature::bind_buffer_offset)) { 1157 const SymLoadStruct coreSymbols[] = { 1158 { (PRFuncPtr*) &mSymbols.fBindBufferOffset, {{ "glBindBufferOffset" }} }, 1159 END_SYMBOLS 1160 }; 1161 const SymLoadStruct extSymbols[] = { 1162 { (PRFuncPtr*) &mSymbols.fBindBufferOffset, 1163 {{ "glBindBufferOffsetEXT", "glBindBufferOffsetNV" }} 1164 }, 1165 END_SYMBOLS 1166 }; 1167 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::bind_buffer_offset); 1168 } 1169 1170 if (IsSupported(GLFeature::query_counter)) { 1171 const SymLoadStruct coreSymbols[] = { 1172 { (PRFuncPtr*) &mSymbols.fQueryCounter, {{ "glQueryCounter" }} }, 1173 END_SYMBOLS 1174 }; 1175 const SymLoadStruct extSymbols[] = { 1176 { (PRFuncPtr*) &mSymbols.fQueryCounter, {{ "glQueryCounterEXT", "glQueryCounterANGLE" }} }, 1177 END_SYMBOLS 1178 }; 1179 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_counter); 1180 } 1181 1182 if (IsSupported(GLFeature::query_objects)) { 1183 const SymLoadStruct coreSymbols[] = { 1184 { (PRFuncPtr*) &mSymbols.fBeginQuery, {{ "glBeginQuery" }} }, 1185 { (PRFuncPtr*) &mSymbols.fGenQueries, {{ "glGenQueries" }} }, 1186 { (PRFuncPtr*) &mSymbols.fDeleteQueries, {{ "glDeleteQueries" }} }, 1187 { (PRFuncPtr*) &mSymbols.fEndQuery, {{ "glEndQuery" }} }, 1188 { (PRFuncPtr*) &mSymbols.fGetQueryiv, {{ "glGetQueryiv" }} }, 1189 { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, {{ "glGetQueryObjectuiv" }} }, 1190 { (PRFuncPtr*) &mSymbols.fIsQuery, {{ "glIsQuery" }} }, 1191 END_SYMBOLS 1192 }; 1193 const SymLoadStruct extSymbols[] = { 1194 { (PRFuncPtr*) &mSymbols.fBeginQuery, {{ "glBeginQueryEXT", "glBeginQueryANGLE" }} }, 1195 { (PRFuncPtr*) &mSymbols.fGenQueries, {{ "glGenQueriesEXT", "glGenQueriesANGLE" }} }, 1196 { (PRFuncPtr*) &mSymbols.fDeleteQueries, {{ "glDeleteQueriesEXT", "glDeleteQueriesANGLE" }} }, 1197 { (PRFuncPtr*) &mSymbols.fEndQuery, {{ "glEndQueryEXT", "glEndQueryANGLE" }} }, 1198 { (PRFuncPtr*) &mSymbols.fGetQueryiv, {{ "glGetQueryivEXT", "glGetQueryivANGLE" }} }, 1199 { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, {{ "glGetQueryObjectuivEXT", "glGetQueryObjectuivANGLE" }} }, 1200 { (PRFuncPtr*) &mSymbols.fIsQuery, {{ "glIsQueryEXT", "glIsQueryANGLE" }} }, 1201 END_SYMBOLS 1202 }; 1203 if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_objects)) { 1204 MarkUnsupported(GLFeature::get_query_object_i64v); 1205 MarkUnsupported(GLFeature::get_query_object_iv); 1206 MarkUnsupported(GLFeature::occlusion_query); 1207 MarkUnsupported(GLFeature::occlusion_query_boolean); 1208 MarkUnsupported(GLFeature::occlusion_query2); 1209 } 1210 } 1211 1212 if (IsSupported(GLFeature::get_query_object_i64v)) { 1213 const SymLoadStruct coreSymbols[] = { 1214 { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, {{ "glGetQueryObjecti64v" }} }, 1215 { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, {{ "glGetQueryObjectui64v" }} }, 1216 END_SYMBOLS 1217 }; 1218 const SymLoadStruct extSymbols[] = { 1219 { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, {{ "glGetQueryObjecti64vEXT", "glGetQueryObjecti64vANGLE" }} }, 1220 { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, {{ "glGetQueryObjectui64vEXT", "glGetQueryObjectui64vANGLE" }} }, 1221 END_SYMBOLS 1222 }; 1223 if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_i64v)) { 1224 MarkUnsupported(GLFeature::query_counter); 1225 } 1226 } 1227 1228 if (IsSupported(GLFeature::get_query_object_iv)) { 1229 const SymLoadStruct coreSymbols[] = { 1230 { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, {{ "glGetQueryObjectiv" }} }, 1231 END_SYMBOLS 1232 }; 1233 const SymLoadStruct extSymbols[] = { 1234 { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, {{ "glGetQueryObjectivEXT", "glGetQueryObjectivANGLE" }} }, 1235 END_SYMBOLS 1236 }; 1237 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_iv); 1238 } 1239 1240 if (IsSupported(GLFeature::clear_buffers)) { 1241 const SymLoadStruct symbols[] = { 1242 { (PRFuncPtr*) &mSymbols.fClearBufferfi, {{ "glClearBufferfi", }} }, 1243 { (PRFuncPtr*) &mSymbols.fClearBufferfv, {{ "glClearBufferfv", }} }, 1244 { (PRFuncPtr*) &mSymbols.fClearBufferiv, {{ "glClearBufferiv", }} }, 1245 { (PRFuncPtr*) &mSymbols.fClearBufferuiv, {{ "glClearBufferuiv" }} }, 1246 END_SYMBOLS 1247 }; 1248 fnLoadForFeature(symbols, GLFeature::clear_buffers); 1249 } 1250 1251 if (IsSupported(GLFeature::copy_buffer)) { 1252 const SymLoadStruct symbols[] = { 1253 { (PRFuncPtr*) &mSymbols.fCopyBufferSubData, {{ "glCopyBufferSubData" }} }, 1254 END_SYMBOLS 1255 }; 1256 fnLoadForFeature(symbols, GLFeature::copy_buffer); 1257 } 1258 1259 if (IsSupported(GLFeature::draw_buffers)) { 1260 const SymLoadStruct coreSymbols[] = { 1261 { (PRFuncPtr*) &mSymbols.fDrawBuffers, {{ "glDrawBuffers" }} }, 1262 END_SYMBOLS 1263 }; 1264 const SymLoadStruct extSymbols[] = { 1265 { (PRFuncPtr*) &mSymbols.fDrawBuffers, {{ "glDrawBuffersARB", "glDrawBuffersEXT" }} }, 1266 END_SYMBOLS 1267 }; 1268 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers); 1269 } 1270 1271 if (IsSupported(GLFeature::draw_buffers_indexed)) { 1272 const SymLoadStruct coreSymbols[] = { 1273 { (PRFuncPtr*) &mSymbols.fBlendEquationSeparatei, {{ "glBlendEquationSeparatei" }} }, 1274 { (PRFuncPtr*) &mSymbols.fBlendFuncSeparatei, {{ "glBlendFuncSeparatei" }} }, 1275 { (PRFuncPtr*) &mSymbols.fColorMaski, {{ "glColorMaski" }} }, 1276 { (PRFuncPtr*) &mSymbols.fDisablei, {{ "glDisablei" }} }, 1277 { (PRFuncPtr*) &mSymbols.fEnablei, {{ "glEnablei" }} }, 1278 END_SYMBOLS 1279 }; 1280 const SymLoadStruct extSymbols[] = { 1281 { (PRFuncPtr*) &mSymbols.fBlendEquationSeparatei, {{ "glBlendEquationSeparateiOES" }} }, 1282 { (PRFuncPtr*) &mSymbols.fBlendFuncSeparatei, {{ "glBlendFuncSeparateiOES" }} }, 1283 { (PRFuncPtr*) &mSymbols.fColorMaski, {{ "glColorMaskiOES" }} }, 1284 { (PRFuncPtr*) &mSymbols.fDisablei, {{ "glDisableiOES" }} }, 1285 { (PRFuncPtr*) &mSymbols.fEnablei, {{ "glEnableiOES" }} }, 1286 END_SYMBOLS 1287 }; 1288 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers_indexed); 1289 } 1290 1291 if (IsSupported(GLFeature::get_integer_indexed)) { 1292 const SymLoadStruct coreSymbols[] = { 1293 { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, {{ "glGetIntegeri_v" }} }, 1294 END_SYMBOLS 1295 }; 1296 const SymLoadStruct extSymbols[] ={ 1297 { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, {{ "glGetIntegerIndexedvEXT" }} }, 1298 END_SYMBOLS 1299 }; 1300 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_integer_indexed); 1301 } 1302 1303 if (IsSupported(GLFeature::get_integer64_indexed)) { 1304 const SymLoadStruct symbols[] = { 1305 { (PRFuncPtr*) &mSymbols.fGetInteger64i_v, {{ "glGetInteger64i_v" }} }, 1306 END_SYMBOLS 1307 }; 1308 fnLoadForFeature(symbols, GLFeature::get_integer64_indexed); 1309 } 1310 1311 if (IsSupported(GLFeature::gpu_shader4)) { 1312 const SymLoadStruct symbols[] = { 1313 { (PRFuncPtr*) &mSymbols.fGetVertexAttribIiv, {{ "glGetVertexAttribIiv", "glGetVertexAttribIivEXT" }} }, 1314 { (PRFuncPtr*) &mSymbols.fGetVertexAttribIuiv, {{ "glGetVertexAttribIuiv", "glGetVertexAttribIuivEXT" }} }, 1315 { (PRFuncPtr*) &mSymbols.fVertexAttribI4i, {{ "glVertexAttribI4i", "glVertexAttribI4iEXT" }} }, 1316 { (PRFuncPtr*) &mSymbols.fVertexAttribI4iv, {{ "glVertexAttribI4iv", "glVertexAttribI4ivEXT" }} }, 1317 { (PRFuncPtr*) &mSymbols.fVertexAttribI4ui, {{ "glVertexAttribI4ui", "glVertexAttribI4uiEXT" }} }, 1318 { (PRFuncPtr*) &mSymbols.fVertexAttribI4uiv, {{ "glVertexAttribI4uiv", "glVertexAttribI4uivEXT" }} }, 1319 { (PRFuncPtr*) &mSymbols.fVertexAttribIPointer, {{ "glVertexAttribIPointer", "glVertexAttribIPointerEXT" }} }, 1320 { (PRFuncPtr*) &mSymbols.fUniform1ui, {{ "glUniform1ui", "glUniform1uiEXT" }} }, 1321 { (PRFuncPtr*) &mSymbols.fUniform2ui, {{ "glUniform2ui", "glUniform2uiEXT" }} }, 1322 { (PRFuncPtr*) &mSymbols.fUniform3ui, {{ "glUniform3ui", "glUniform3uiEXT" }} }, 1323 { (PRFuncPtr*) &mSymbols.fUniform4ui, {{ "glUniform4ui", "glUniform4uiEXT" }} }, 1324 { (PRFuncPtr*) &mSymbols.fUniform1uiv, {{ "glUniform1uiv", "glUniform1uivEXT" }} }, 1325 { (PRFuncPtr*) &mSymbols.fUniform2uiv, {{ "glUniform2uiv", "glUniform2uivEXT" }} }, 1326 { (PRFuncPtr*) &mSymbols.fUniform3uiv, {{ "glUniform3uiv", "glUniform3uivEXT" }} }, 1327 { (PRFuncPtr*) &mSymbols.fUniform4uiv, {{ "glUniform4uiv", "glUniform4uivEXT" }} }, 1328 { (PRFuncPtr*) &mSymbols.fGetFragDataLocation, {{ "glGetFragDataLocation", "glGetFragDataLocationEXT" }} }, 1329 { (PRFuncPtr*) &mSymbols.fGetUniformuiv, {{ "glGetUniformuiv", "glGetUniformuivEXT" }} }, 1330 END_SYMBOLS 1331 }; 1332 fnLoadForFeature(symbols, GLFeature::gpu_shader4); 1333 } 1334 1335 if (IsSupported(GLFeature::map_buffer_range)) { 1336 const SymLoadStruct symbols[] = { 1337 { (PRFuncPtr*) &mSymbols.fMapBufferRange, {{ "glMapBufferRange" }} }, 1338 { (PRFuncPtr*) &mSymbols.fFlushMappedBufferRange, {{ "glFlushMappedBufferRange" }} }, 1339 { (PRFuncPtr*) &mSymbols.fUnmapBuffer, {{ "glUnmapBuffer" }} }, 1340 END_SYMBOLS 1341 }; 1342 fnLoadForFeature(symbols, GLFeature::map_buffer_range); 1343 } 1344 1345 if (IsSupported(GLFeature::texture_3D)) { 1346 const SymLoadStruct coreSymbols[] = { 1347 { (PRFuncPtr*) &mSymbols.fTexImage3D, {{ "glTexImage3D" }} }, 1348 { (PRFuncPtr*) &mSymbols.fTexSubImage3D, {{ "glTexSubImage3D" }} }, 1349 END_SYMBOLS 1350 }; 1351 const SymLoadStruct extSymbols[] = { 1352 { (PRFuncPtr*) &mSymbols.fTexImage3D, {{ "glTexImage3DOES" }} }, 1353 { (PRFuncPtr*) &mSymbols.fTexSubImage3D, {{ "glTexSubImage3DOES" }} }, 1354 END_SYMBOLS 1355 }; 1356 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D); 1357 } 1358 1359 if (IsSupported(GLFeature::texture_3D_compressed)) { 1360 const SymLoadStruct coreSymbols[] = { 1361 { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, {{ "glCompressedTexImage3D" }} }, 1362 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, {{ "glCompressedTexSubImage3D" }} }, 1363 END_SYMBOLS 1364 }; 1365 const SymLoadStruct extSymbols[] = { 1366 { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, {{ "glCompressedTexImage3DARB", "glCompressedTexImage3DOES" }} }, 1367 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, {{ "glCompressedTexSubImage3DARB", "glCompressedTexSubImage3DOES" }} }, 1368 END_SYMBOLS 1369 }; 1370 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_compressed); 1371 } 1372 1373 if (IsSupported(GLFeature::texture_3D_copy)) { 1374 const SymLoadStruct coreSymbols[] = { 1375 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, {{ "glCopyTexSubImage3D" }} }, 1376 END_SYMBOLS 1377 }; 1378 const SymLoadStruct extSymbols[] = { 1379 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, {{ "glCopyTexSubImage3DEXT", "glCopyTexSubImage3DOES" }} }, 1380 END_SYMBOLS 1381 }; 1382 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_copy); 1383 } 1384 1385 if (IsSupported(GLFeature::uniform_buffer_object)) { 1386 // Note: Don't query for glGetActiveUniformName because it is not 1387 // supported by GL ES 3. 1388 const SymLoadStruct symbols[] = { 1389 { (PRFuncPtr*) &mSymbols.fGetUniformIndices, {{ "glGetUniformIndices" }} }, 1390 { (PRFuncPtr*) &mSymbols.fGetActiveUniformsiv, {{ "glGetActiveUniformsiv" }} }, 1391 { (PRFuncPtr*) &mSymbols.fGetUniformBlockIndex, {{ "glGetUniformBlockIndex" }} }, 1392 { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockiv, {{ "glGetActiveUniformBlockiv" }} }, 1393 { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockName, {{ "glGetActiveUniformBlockName" }} }, 1394 { (PRFuncPtr*) &mSymbols.fUniformBlockBinding, {{ "glUniformBlockBinding" }} }, 1395 END_SYMBOLS 1396 }; 1397 fnLoadForFeature(symbols, GLFeature::uniform_buffer_object); 1398 } 1399 1400 if (IsSupported(GLFeature::uniform_matrix_nonsquare)) { 1401 const SymLoadStruct symbols[] = { 1402 { (PRFuncPtr*) &mSymbols.fUniformMatrix2x3fv, {{ "glUniformMatrix2x3fv" }} }, 1403 { (PRFuncPtr*) &mSymbols.fUniformMatrix2x4fv, {{ "glUniformMatrix2x4fv" }} }, 1404 { (PRFuncPtr*) &mSymbols.fUniformMatrix3x2fv, {{ "glUniformMatrix3x2fv" }} }, 1405 { (PRFuncPtr*) &mSymbols.fUniformMatrix3x4fv, {{ "glUniformMatrix3x4fv" }} }, 1406 { (PRFuncPtr*) &mSymbols.fUniformMatrix4x2fv, {{ "glUniformMatrix4x2fv" }} }, 1407 { (PRFuncPtr*) &mSymbols.fUniformMatrix4x3fv, {{ "glUniformMatrix4x3fv" }} }, 1408 END_SYMBOLS 1409 }; 1410 fnLoadForFeature(symbols, GLFeature::uniform_matrix_nonsquare); 1411 } 1412 1413 if (IsSupported(GLFeature::internalformat_query)) { 1414 const SymLoadStruct symbols[] = { 1415 CORE_SYMBOL(GetInternalformativ), 1416 END_SYMBOLS 1417 }; 1418 fnLoadForFeature(symbols, GLFeature::internalformat_query); 1419 } 1420 1421 if (IsSupported(GLFeature::invalidate_framebuffer)) { 1422 const SymLoadStruct symbols[] = { 1423 { (PRFuncPtr*) &mSymbols.fInvalidateFramebuffer, {{ "glInvalidateFramebuffer" }} }, 1424 { (PRFuncPtr*) &mSymbols.fInvalidateSubFramebuffer, {{ "glInvalidateSubFramebuffer" }} }, 1425 END_SYMBOLS 1426 }; 1427 fnLoadForFeature(symbols, GLFeature::invalidate_framebuffer); 1428 } 1429 1430 if (IsSupported(GLFeature::multiview)) { 1431 const SymLoadStruct symbols[] = { 1432 { (PRFuncPtr*) &mSymbols.fFramebufferTextureMultiview, {{ 1433 "glFramebufferTextureMultiviewOVR", 1434 "glFramebufferTextureMultiviewLayeredANGLE" 1435 }} }, 1436 END_SYMBOLS 1437 }; 1438 fnLoadForFeature(symbols, GLFeature::multiview); 1439 } 1440 1441 if (IsSupported(GLFeature::prim_restart)) { 1442 const SymLoadStruct symbols[] = { 1443 { (PRFuncPtr*) &mSymbols.fPrimitiveRestartIndex, {{ "glPrimitiveRestartIndex", "glPrimitiveRestartIndexNV" }} }, 1444 END_SYMBOLS 1445 }; 1446 fnLoadForFeature(symbols, GLFeature::prim_restart); 1447 } 1448 1449 if (IsExtensionSupported(KHR_debug)) { 1450 const SymLoadStruct symbols[] = { 1451 { (PRFuncPtr*) &mSymbols.fDebugMessageControl, {{ "glDebugMessageControl", "glDebugMessageControlKHR", }} }, 1452 { (PRFuncPtr*) &mSymbols.fDebugMessageInsert, {{ "glDebugMessageInsert", "glDebugMessageInsertKHR", }} }, 1453 { (PRFuncPtr*) &mSymbols.fDebugMessageCallback, {{ "glDebugMessageCallback", "glDebugMessageCallbackKHR" }} }, 1454 { (PRFuncPtr*) &mSymbols.fGetDebugMessageLog, {{ "glGetDebugMessageLog", "glGetDebugMessageLogKHR", }} }, 1455 { (PRFuncPtr*) &mSymbols.fGetPointerv, {{ "glGetPointerv", "glGetPointervKHR", }} }, 1456 { (PRFuncPtr*) &mSymbols.fPushDebugGroup, {{ "glPushDebugGroup", "glPushDebugGroupKHR", }} }, 1457 { (PRFuncPtr*) &mSymbols.fPopDebugGroup, {{ "glPopDebugGroup", "glPopDebugGroupKHR", }} }, 1458 { (PRFuncPtr*) &mSymbols.fObjectLabel, {{ "glObjectLabel", "glObjectLabelKHR", }} }, 1459 { (PRFuncPtr*) &mSymbols.fGetObjectLabel, {{ "glGetObjectLabel", "glGetObjectLabelKHR", }} }, 1460 { (PRFuncPtr*) &mSymbols.fObjectPtrLabel, {{ "glObjectPtrLabel", "glObjectPtrLabelKHR", }} }, 1461 { (PRFuncPtr*) &mSymbols.fGetObjectPtrLabel, {{ "glGetObjectPtrLabel", "glGetObjectPtrLabelKHR", }} }, 1462 END_SYMBOLS 1463 }; 1464 fnLoadForExt(symbols, KHR_debug); 1465 } 1466 1467 if (IsExtensionSupported(NV_fence)) { 1468 const SymLoadStruct symbols[] = { 1469 { (PRFuncPtr*) &mSymbols.fGenFences, {{ "glGenFencesNV" }} }, 1470 { (PRFuncPtr*) &mSymbols.fDeleteFences, {{ "glDeleteFencesNV" }} }, 1471 { (PRFuncPtr*) &mSymbols.fSetFence, {{ "glSetFenceNV" }} }, 1472 { (PRFuncPtr*) &mSymbols.fTestFence, {{ "glTestFenceNV" }} }, 1473 { (PRFuncPtr*) &mSymbols.fFinishFence, {{ "glFinishFenceNV" }} }, 1474 { (PRFuncPtr*) &mSymbols.fIsFence, {{ "glIsFenceNV" }} }, 1475 { (PRFuncPtr*) &mSymbols.fGetFenceiv, {{ "glGetFenceivNV" }} }, 1476 END_SYMBOLS 1477 }; 1478 fnLoadForExt(symbols, NV_fence); 1479 } 1480 1481 // clang-format on 1482 1483 if (IsExtensionSupported(NV_texture_barrier)) { 1484 const SymLoadStruct symbols[] = { 1485 {(PRFuncPtr*)&mSymbols.fTextureBarrier, {{"glTextureBarrierNV"}}}, 1486 END_SYMBOLS}; 1487 fnLoadForExt(symbols, NV_texture_barrier); 1488 } 1489 1490 if (IsSupported(GLFeature::read_buffer)) { 1491 const SymLoadStruct symbols[] = {CORE_SYMBOL(ReadBuffer), END_SYMBOLS}; 1492 fnLoadForFeature(symbols, GLFeature::read_buffer); 1493 } 1494 1495 if (IsExtensionSupported(APPLE_framebuffer_multisample)) { 1496 const SymLoadStruct symbols[] = { 1497 CORE_SYMBOL(ResolveMultisampleFramebufferAPPLE), END_SYMBOLS}; 1498 fnLoadForExt(symbols, APPLE_framebuffer_multisample); 1499 } 1500 1501 if (IsSupported(GLFeature::provoking_vertex)) { 1502 const SymLoadStruct symbols[] = {{(PRFuncPtr*)&mSymbols.fProvokingVertex, 1503 {{ 1504 "glProvokingVertex", 1505 "glProvokingVertexANGLE", 1506 "glProvokingVertexEXT", 1507 }}}, 1508 END_SYMBOLS}; 1509 fnLoadForFeature(symbols, GLFeature::provoking_vertex); 1510 } 1511 1512 if (IsExtensionSupported(EXT_semaphore)) { 1513 const SymLoadStruct symbols[] = { 1514 {(PRFuncPtr*)&mSymbols.fDeleteSemaphoresEXT, 1515 {{"glDeleteSemaphoresEXT"}}}, 1516 {(PRFuncPtr*)&mSymbols.fGenSemaphoresEXT, {{"glGenSemaphoresEXT"}}}, 1517 {(PRFuncPtr*)&mSymbols.fGetSemaphoreParameterui64vEXT, 1518 {{"glGetSemaphoreParameterui64vEXT"}}}, 1519 {(PRFuncPtr*)&mSymbols.fIsSemaphoreEXT, {{"glIsSemaphoreEXT"}}}, 1520 {(PRFuncPtr*)&mSymbols.fSemaphoreParameterui64vEXT, 1521 {{"glSemaphoreParameterui64vEXT"}}}, 1522 {(PRFuncPtr*)&mSymbols.fSignalSemaphoreEXT, {{"glSignalSemaphoreEXT"}}}, 1523 {(PRFuncPtr*)&mSymbols.fWaitSemaphoreEXT, {{"glWaitSemaphoreEXT"}}}, 1524 END_SYMBOLS}; 1525 fnLoadForExt(symbols, EXT_semaphore); 1526 } 1527 1528 if (IsExtensionSupported(EXT_semaphore_fd)) { 1529 const SymLoadStruct symbols[] = { 1530 {(PRFuncPtr*)&mSymbols.fImportSemaphoreFdEXT, 1531 {{"glImportSemaphoreFdEXT"}}}, 1532 END_SYMBOLS}; 1533 fnLoadForExt(symbols, EXT_semaphore_fd); 1534 } 1535 1536 if (IsExtensionSupported(EXT_memory_object)) { 1537 const SymLoadStruct symbols[] = { 1538 {(PRFuncPtr*)&mSymbols.fGetUnsignedBytevEXT, 1539 {{"glGetUnsignedBytevEXT"}}}, 1540 {(PRFuncPtr*)&mSymbols.fGetUnsignedBytei_vEXT, 1541 {{"glGetUnsignedBytei_vEXT"}}}, 1542 {(PRFuncPtr*)&mSymbols.fDeleteMemoryObjectsEXT, 1543 {{"glDeleteMemoryObjectsEXT"}}}, 1544 {(PRFuncPtr*)&mSymbols.fIsMemoryObjectEXT, {{"glIsMemoryObjectEXT"}}}, 1545 {(PRFuncPtr*)&mSymbols.fCreateMemoryObjectsEXT, 1546 {{"glCreateMemoryObjectsEXT"}}}, 1547 {(PRFuncPtr*)&mSymbols.fMemoryObjectParameterivEXT, 1548 {{"glMemoryObjectParameterivEXT"}}}, 1549 {(PRFuncPtr*)&mSymbols.fGetMemoryObjectParameterivEXT, 1550 {{"glGetMemoryObjectParameterivEXT"}}}, 1551 {(PRFuncPtr*)&mSymbols.fTexStorageMem2DEXT, {{"glTexStorageMem2DEXT"}}}, 1552 {(PRFuncPtr*)&mSymbols.fTexStorageMem2DMultisampleEXT, 1553 {{"glTexStorageMem2DMultisampleEXT"}}}, 1554 {(PRFuncPtr*)&mSymbols.fTexStorageMem3DEXT, {{"glTexStorageMem3DEXT"}}}, 1555 {(PRFuncPtr*)&mSymbols.fTexStorageMem3DMultisampleEXT, 1556 {{"glTexStorageMem3DMultisampleEXT"}}}, 1557 {(PRFuncPtr*)&mSymbols.fBufferStorageMemEXT, 1558 {{"glBufferStorageMemEXT"}}}, 1559 {(PRFuncPtr*)&mSymbols.fTextureStorageMem2DEXT, 1560 {{"glTextureStorageMem2DEXT"}}}, 1561 {(PRFuncPtr*)&mSymbols.fTextureStorageMem2DMultisampleEXT, 1562 {{"glTextureStorageMem2DMultisampleEXT"}}}, 1563 {(PRFuncPtr*)&mSymbols.fTextureStorageMem3DEXT, 1564 {{"glTextureStorageMem3DEXT"}}}, 1565 {(PRFuncPtr*)&mSymbols.fTextureStorageMem3DMultisampleEXT, 1566 {{"glTextureStorageMem3DMultisampleEXT"}}}, 1567 {(PRFuncPtr*)&mSymbols.fNamedBufferStorageMemEXT, 1568 {{"glNamedBufferStorageMemEXT"}}}, 1569 END_SYMBOLS}; 1570 fnLoadForExt(symbols, EXT_memory_object); 1571 } 1572 1573 if (IsExtensionSupported(EXT_memory_object_fd)) { 1574 const SymLoadStruct symbols[] = { 1575 {(PRFuncPtr*)&mSymbols.fImportMemoryFdEXT, {{"glImportMemoryFdEXT"}}}, 1576 END_SYMBOLS}; 1577 fnLoadForExt(symbols, EXT_memory_object_fd); 1578 } 1579 1580 // Load developer symbols, don't fail if we can't find them. 1581 const SymLoadStruct devSymbols[] = {CORE_SYMBOL(GetTexImage), 1582 CORE_SYMBOL(GetTexLevelParameteriv), 1583 END_SYMBOLS}; 1584 const bool warnOnFailures = ShouldSpew(); 1585 (void)loader.LoadSymbols(devSymbols, warnOnFailures); 1586 } 1587 1588 #undef CORE_SYMBOL 1589 #undef CORE_EXT_SYMBOL2 1590 #undef EXT_SYMBOL2 1591 #undef EXT_SYMBOL3 1592 #undef END_SYMBOLS 1593 1594 void GLContext::DebugCallback(GLenum source, GLenum type, GLuint id, 1595 GLenum severity, GLsizei length, 1596 const GLchar* message) { 1597 nsAutoCString sourceStr; 1598 switch (source) { 1599 case LOCAL_GL_DEBUG_SOURCE_API: 1600 sourceStr = "SOURCE_API"_ns; 1601 break; 1602 case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM: 1603 sourceStr = "SOURCE_WINDOW_SYSTEM"_ns; 1604 break; 1605 case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER: 1606 sourceStr = "SOURCE_SHADER_COMPILER"_ns; 1607 break; 1608 case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY: 1609 sourceStr = "SOURCE_THIRD_PARTY"_ns; 1610 break; 1611 case LOCAL_GL_DEBUG_SOURCE_APPLICATION: 1612 sourceStr = "SOURCE_APPLICATION"_ns; 1613 break; 1614 case LOCAL_GL_DEBUG_SOURCE_OTHER: 1615 sourceStr = "SOURCE_OTHER"_ns; 1616 break; 1617 default: 1618 sourceStr = nsPrintfCString("<source 0x%04x>", source); 1619 break; 1620 } 1621 1622 nsAutoCString typeStr; 1623 switch (type) { 1624 case LOCAL_GL_DEBUG_TYPE_ERROR: 1625 typeStr = "TYPE_ERROR"_ns; 1626 break; 1627 case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: 1628 typeStr = "TYPE_DEPRECATED_BEHAVIOR"_ns; 1629 break; 1630 case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: 1631 typeStr = "TYPE_UNDEFINED_BEHAVIOR"_ns; 1632 break; 1633 case LOCAL_GL_DEBUG_TYPE_PORTABILITY: 1634 typeStr = "TYPE_PORTABILITY"_ns; 1635 break; 1636 case LOCAL_GL_DEBUG_TYPE_PERFORMANCE: 1637 typeStr = "TYPE_PERFORMANCE"_ns; 1638 break; 1639 case LOCAL_GL_DEBUG_TYPE_OTHER: 1640 typeStr = "TYPE_OTHER"_ns; 1641 break; 1642 case LOCAL_GL_DEBUG_TYPE_MARKER: 1643 typeStr = "TYPE_MARKER"_ns; 1644 break; 1645 default: 1646 typeStr = nsPrintfCString("<type 0x%04x>", type); 1647 break; 1648 } 1649 1650 nsAutoCString sevStr; 1651 switch (severity) { 1652 case LOCAL_GL_DEBUG_SEVERITY_HIGH: 1653 sevStr = "SEVERITY_HIGH"_ns; 1654 break; 1655 case LOCAL_GL_DEBUG_SEVERITY_MEDIUM: 1656 sevStr = "SEVERITY_MEDIUM"_ns; 1657 break; 1658 case LOCAL_GL_DEBUG_SEVERITY_LOW: 1659 sevStr = "SEVERITY_LOW"_ns; 1660 break; 1661 case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION: 1662 sevStr = "SEVERITY_NOTIFICATION"_ns; 1663 break; 1664 default: 1665 sevStr = nsPrintfCString("<severity 0x%04x>", severity); 1666 break; 1667 } 1668 1669 printf_stderr("[KHR_debug: 0x%" PRIxPTR "] ID %u: %s, %s, %s:\n %s\n", 1670 (uintptr_t)this, id, sourceStr.BeginReading(), 1671 typeStr.BeginReading(), sevStr.BeginReading(), message); 1672 } 1673 1674 void GLContext::InitExtensions() { 1675 MOZ_GL_ASSERT(this, IsCurrent()); 1676 1677 std::vector<nsCString> driverExtensionList; 1678 1679 [&]() { 1680 if (mSymbols.fGetStringi) { 1681 GLuint count = 0; 1682 if (GetPotentialInteger(LOCAL_GL_NUM_EXTENSIONS, (GLint*)&count)) { 1683 for (GLuint i = 0; i < count; i++) { 1684 // This is UTF-8. 1685 const char* rawExt = (const char*)fGetStringi(LOCAL_GL_EXTENSIONS, i); 1686 1687 // We CANNOT use nsDependentCString here, because the spec doesn't 1688 // guarantee that the pointers returned are different, only that their 1689 // contents are. On Flame, each of these index string queries returns 1690 // the same address. 1691 driverExtensionList.push_back(nsCString(rawExt)); 1692 } 1693 return; 1694 } 1695 } 1696 1697 const char* rawExts = (const char*)fGetString(LOCAL_GL_EXTENSIONS); 1698 if (rawExts) { 1699 nsDependentCString exts(rawExts); 1700 SplitByChar(exts, ' ', &driverExtensionList); 1701 } 1702 }(); 1703 const auto err = fGetError(); 1704 MOZ_ALWAYS_TRUE(!IsBadCallError(err)); 1705 1706 const bool shouldDumpExts = ShouldDumpExts(); 1707 if (shouldDumpExts) { 1708 printf_stderr("%i GL driver extensions: (*: recognized)\n", 1709 (uint32_t)driverExtensionList.size()); 1710 } 1711 1712 MarkBitfieldByStrings(driverExtensionList, shouldDumpExts, sExtensionNames, 1713 &mAvailableExtensions); 1714 1715 if (WorkAroundDriverBugs()) { 1716 if (Vendor() == GLVendor::Qualcomm) { 1717 // Some Adreno drivers do not report GL_OES_EGL_sync, but they really do 1718 // support it. 1719 MarkExtensionSupported(OES_EGL_sync); 1720 } 1721 1722 if (Vendor() == GLVendor::ATI) { 1723 // ATI drivers say this extension exists, but we can't 1724 // actually find the EGLImageTargetRenderbufferStorageOES 1725 // extension function pointer in the drivers. 1726 MarkExtensionUnsupported(OES_EGL_image); 1727 } 1728 1729 if (Vendor() == GLVendor::Imagination && Renderer() == GLRenderer::SGX540) { 1730 // Bug 980048 1731 MarkExtensionUnsupported(OES_EGL_sync); 1732 } 1733 1734 if (Vendor() == GLVendor::ARM && (Renderer() == GLRenderer::Mali400MP || 1735 Renderer() == GLRenderer::Mali450MP)) { 1736 // Bug 1264505 1737 MarkExtensionUnsupported(OES_EGL_image_external); 1738 } 1739 1740 if (Renderer() == GLRenderer::AndroidEmulator) { 1741 // the Android emulator, which we use to run B2G reftests on, 1742 // doesn't expose the OES_rgb8_rgba8 extension, but it seems to 1743 // support it (tautologically, as it only runs on desktop GL). 1744 MarkExtensionSupported(OES_rgb8_rgba8); 1745 } 1746 1747 if (Vendor() == GLVendor::VMware && 1748 Renderer() == GLRenderer::GalliumLlvmpipe) { 1749 // The llvmpipe driver that is used on linux try servers appears to have 1750 // buggy support for s3tc/dxt1 compressed textures. 1751 // See Bug 975824. 1752 MarkExtensionUnsupported(EXT_texture_compression_s3tc); 1753 MarkExtensionUnsupported(EXT_texture_compression_dxt1); 1754 MarkExtensionUnsupported(ANGLE_texture_compression_dxt3); 1755 MarkExtensionUnsupported(ANGLE_texture_compression_dxt5); 1756 } 1757 1758 #ifdef XP_MACOSX 1759 // OSX supports EXT_texture_sRGB in Legacy contexts, but not in Core 1760 // contexts. Though EXT_texture_sRGB was included into GL2.1, it *excludes* 1761 // the interactions with s3tc. Strictly speaking, you must advertize support 1762 // for EXT_texture_sRGB in order to allow for srgb+s3tc on desktop GL. The 1763 // omission of EXT_texture_sRGB in OSX Core contexts appears to be a bug. 1764 MarkExtensionSupported(EXT_texture_sRGB); 1765 #endif 1766 } 1767 1768 if (shouldDumpExts) { 1769 printf_stderr("\nActivated extensions:\n"); 1770 1771 for (size_t i = 0; i < mAvailableExtensions.size(); i++) { 1772 if (!mAvailableExtensions[i]) continue; 1773 1774 const char* ext = sExtensionNames[i]; 1775 printf_stderr("[%i] %s\n", (uint32_t)i, ext); 1776 } 1777 } 1778 } 1779 1780 void GLContext::PlatformStartup() { 1781 RegisterStrongMemoryReporter(new GfxTexturesReporter()); 1782 } 1783 1784 // Common code for checking for both GL extensions and GLX extensions. 1785 bool GLContext::ListHasExtension(const GLubyte* extensions, 1786 const char* extension) { 1787 // fix bug 612572 - we were crashing as we were calling this function with 1788 // extensions==null 1789 if (extensions == nullptr || extension == nullptr) return false; 1790 1791 const GLubyte* start; 1792 GLubyte* where; 1793 GLubyte* terminator; 1794 1795 /* Extension names should not have spaces. */ 1796 where = (GLubyte*)strchr(extension, ' '); 1797 if (where || *extension == '\0') return false; 1798 1799 /* 1800 * It takes a bit of care to be fool-proof about parsing the 1801 * OpenGL extensions string. Don't be fooled by sub-strings, 1802 * etc. 1803 */ 1804 start = extensions; 1805 for (;;) { 1806 where = (GLubyte*)strstr((const char*)start, extension); 1807 if (!where) { 1808 break; 1809 } 1810 terminator = where + strlen(extension); 1811 if (where == start || *(where - 1) == ' ') { 1812 if (*terminator == ' ' || *terminator == '\0') { 1813 return true; 1814 } 1815 } 1816 start = terminator; 1817 } 1818 return false; 1819 } 1820 1821 bool GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus) { 1822 MOZ_ASSERT(fb); 1823 1824 ScopedBindFramebuffer autoFB(this, fb); 1825 MOZ_GL_ASSERT(this, fIsFramebuffer(fb)); 1826 1827 GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); 1828 if (pStatus) *pStatus = status; 1829 1830 return status == LOCAL_GL_FRAMEBUFFER_COMPLETE; 1831 } 1832 1833 void GLContext::AttachBuffersToFB(GLuint colorTex, GLuint colorRB, 1834 GLuint depthRB, GLuint stencilRB, GLuint fb, 1835 GLenum target) { 1836 MOZ_ASSERT(fb); 1837 MOZ_ASSERT(!(colorTex && colorRB)); 1838 1839 ScopedBindFramebuffer autoFB(this, fb); 1840 MOZ_GL_ASSERT(this, fIsFramebuffer(fb)); // It only counts after being bound. 1841 1842 if (colorTex) { 1843 MOZ_GL_ASSERT(this, fIsTexture(colorTex)); 1844 MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D || 1845 target == LOCAL_GL_TEXTURE_RECTANGLE_ARB); 1846 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, 1847 target, colorTex, 0); 1848 } else if (colorRB) { 1849 MOZ_GL_ASSERT(this, fIsRenderbuffer(colorRB)); 1850 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, 1851 LOCAL_GL_RENDERBUFFER, colorRB); 1852 } 1853 1854 if (depthRB) { 1855 MOZ_GL_ASSERT(this, fIsRenderbuffer(depthRB)); 1856 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, 1857 LOCAL_GL_RENDERBUFFER, depthRB); 1858 } 1859 1860 if (stencilRB) { 1861 MOZ_GL_ASSERT(this, fIsRenderbuffer(stencilRB)); 1862 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, 1863 LOCAL_GL_RENDERBUFFER, stencilRB); 1864 } 1865 } 1866 1867 bool GLContext::AssembleOffscreenFBs(const GLuint colorMSRB, 1868 const GLuint depthRB, 1869 const GLuint stencilRB, 1870 const GLuint texture, GLuint* drawFB_out, 1871 GLuint* readFB_out) { 1872 if (!colorMSRB && !texture) { 1873 MOZ_ASSERT(!depthRB && !stencilRB); 1874 1875 if (drawFB_out) *drawFB_out = 0; 1876 if (readFB_out) *readFB_out = 0; 1877 1878 return true; 1879 } 1880 1881 ScopedBindFramebuffer autoFB(this); 1882 1883 GLuint drawFB = 0; 1884 GLuint readFB = 0; 1885 1886 if (texture) { 1887 readFB = 0; 1888 fGenFramebuffers(1, &readFB); 1889 BindFB(readFB); 1890 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, 1891 LOCAL_GL_TEXTURE_2D, texture, 0); 1892 } 1893 1894 if (colorMSRB) { 1895 drawFB = 0; 1896 fGenFramebuffers(1, &drawFB); 1897 BindFB(drawFB); 1898 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, 1899 LOCAL_GL_RENDERBUFFER, colorMSRB); 1900 } else { 1901 drawFB = readFB; 1902 } 1903 MOZ_ASSERT(GetIntAs<GLuint>(LOCAL_GL_FRAMEBUFFER_BINDING) == drawFB); 1904 1905 if (depthRB) { 1906 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, 1907 LOCAL_GL_RENDERBUFFER, depthRB); 1908 } 1909 1910 if (stencilRB) { 1911 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, 1912 LOCAL_GL_RENDERBUFFER, stencilRB); 1913 } 1914 1915 // We should be all resized. Check for framebuffer completeness. 1916 GLenum status; 1917 bool isComplete = true; 1918 1919 if (!IsFramebufferComplete(drawFB, &status)) { 1920 NS_WARNING("DrawFBO: Incomplete"); 1921 #ifdef MOZ_GL_DEBUG_BUILD 1922 if (ShouldSpew()) { 1923 printf_stderr("Framebuffer status: %X\n", status); 1924 } 1925 #endif 1926 isComplete = false; 1927 } 1928 1929 if (!IsFramebufferComplete(readFB, &status)) { 1930 NS_WARNING("ReadFBO: Incomplete"); 1931 #ifdef MOZ_GL_DEBUG_BUILD 1932 if (ShouldSpew()) { 1933 printf_stderr("Framebuffer status: %X\n", status); 1934 } 1935 #endif 1936 isComplete = false; 1937 } 1938 1939 if (drawFB_out) { 1940 *drawFB_out = drawFB; 1941 } else if (drawFB) { 1942 MOZ_CRASH("drawFB created when not requested!"); 1943 } 1944 1945 if (readFB_out) { 1946 *readFB_out = readFB; 1947 } else if (readFB) { 1948 MOZ_CRASH("readFB created when not requested!"); 1949 } 1950 1951 return isComplete; 1952 } 1953 1954 void GLContext::MarkDestroyed() { 1955 if (IsDestroyed()) return; 1956 1957 OnMarkDestroyed(); 1958 1959 // Null these before they're naturally nulled after dtor, as we want GLContext 1960 // to still be alive in *their* dtors. 1961 mBlitHelper = nullptr; 1962 mReadTexImageHelper = nullptr; 1963 1964 mContextLost = true; 1965 mSymbols = {}; 1966 } 1967 1968 // - 1969 1970 #ifdef MOZ_GL_DEBUG_BUILD 1971 /* static */ 1972 void GLContext::AssertNotPassingStackBufferToTheGL(const void* ptr) { 1973 int somethingOnTheStack; 1974 const void* someStackPtr = &somethingOnTheStack; 1975 const int page_bits = 12; 1976 intptr_t page = reinterpret_cast<uintptr_t>(ptr) >> page_bits; 1977 intptr_t someStackPage = 1978 reinterpret_cast<uintptr_t>(someStackPtr) >> page_bits; 1979 uintptr_t pageDistance = std::abs(page - someStackPage); 1980 1981 // Explanation for the "distance <= 1" check here as opposed to just 1982 // an equality check. 1983 // 1984 // Here we assume that pages immediately adjacent to the someStackAddress 1985 // page, are also stack pages. That allows to catch the case where the calling 1986 // frame put a buffer on the stack, and we just crossed the page boundary. 1987 // That is likely to happen, precisely, when using stack arrays. I hit that 1988 // specifically with CompositorOGL::Initialize. 1989 // 1990 // In theory we could be unlucky and wrongly assert here. If that happens, 1991 // it will only affect debug builds, and looking at stacks we'll be able to 1992 // see that this assert is wrong and revert to the conservative and safe 1993 // approach of only asserting when address and someStackAddress are 1994 // on the same page. 1995 bool isStackAddress = pageDistance <= 1; 1996 MOZ_ASSERT(!isStackAddress, 1997 "Please don't pass stack arrays to the GL. " 1998 "Consider using HeapCopyOfStackArray. " 1999 "See bug 1005658."); 2000 } 2001 2002 void GLContext::CreatedProgram(GLContext* aOrigin, GLuint aName) { 2003 mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName)); 2004 } 2005 2006 void GLContext::CreatedShader(GLContext* aOrigin, GLuint aName) { 2007 mTrackedShaders.AppendElement(NamedResource(aOrigin, aName)); 2008 } 2009 2010 void GLContext::CreatedBuffers(GLContext* aOrigin, GLsizei aCount, 2011 GLuint* aNames) { 2012 for (GLsizei i = 0; i < aCount; ++i) { 2013 mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i])); 2014 } 2015 } 2016 2017 void GLContext::CreatedQueries(GLContext* aOrigin, GLsizei aCount, 2018 GLuint* aNames) { 2019 for (GLsizei i = 0; i < aCount; ++i) { 2020 mTrackedQueries.AppendElement(NamedResource(aOrigin, aNames[i])); 2021 } 2022 } 2023 2024 void GLContext::CreatedTextures(GLContext* aOrigin, GLsizei aCount, 2025 GLuint* aNames) { 2026 for (GLsizei i = 0; i < aCount; ++i) { 2027 mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i])); 2028 } 2029 } 2030 2031 void GLContext::CreatedFramebuffers(GLContext* aOrigin, GLsizei aCount, 2032 GLuint* aNames) { 2033 for (GLsizei i = 0; i < aCount; ++i) { 2034 mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i])); 2035 } 2036 } 2037 2038 void GLContext::CreatedRenderbuffers(GLContext* aOrigin, GLsizei aCount, 2039 GLuint* aNames) { 2040 for (GLsizei i = 0; i < aCount; ++i) { 2041 mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i])); 2042 } 2043 } 2044 2045 static void RemoveNamesFromArray(GLContext* aOrigin, GLsizei aCount, 2046 const GLuint* aNames, 2047 nsTArray<GLContext::NamedResource>& aArray) { 2048 for (GLsizei j = 0; j < aCount; ++j) { 2049 GLuint name = aNames[j]; 2050 // name 0 can be ignored 2051 if (name == 0) continue; 2052 2053 for (uint32_t i = 0; i < aArray.Length(); ++i) { 2054 if (aArray[i].name == name) { 2055 aArray.RemoveElementAt(i); 2056 break; 2057 } 2058 } 2059 } 2060 } 2061 2062 void GLContext::DeletedProgram(GLContext* aOrigin, GLuint aName) { 2063 RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms); 2064 } 2065 2066 void GLContext::DeletedShader(GLContext* aOrigin, GLuint aName) { 2067 RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders); 2068 } 2069 2070 void GLContext::DeletedBuffers(GLContext* aOrigin, GLsizei aCount, 2071 const GLuint* aNames) { 2072 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers); 2073 } 2074 2075 void GLContext::DeletedQueries(GLContext* aOrigin, GLsizei aCount, 2076 const GLuint* aNames) { 2077 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedQueries); 2078 } 2079 2080 void GLContext::DeletedTextures(GLContext* aOrigin, GLsizei aCount, 2081 const GLuint* aNames) { 2082 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures); 2083 } 2084 2085 void GLContext::DeletedFramebuffers(GLContext* aOrigin, GLsizei aCount, 2086 const GLuint* aNames) { 2087 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers); 2088 } 2089 2090 void GLContext::DeletedRenderbuffers(GLContext* aOrigin, GLsizei aCount, 2091 const GLuint* aNames) { 2092 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers); 2093 } 2094 2095 static void MarkContextDestroyedInArray( 2096 GLContext* aContext, nsTArray<GLContext::NamedResource>& aArray) { 2097 for (uint32_t i = 0; i < aArray.Length(); ++i) { 2098 if (aArray[i].origin == aContext) aArray[i].originDeleted = true; 2099 } 2100 } 2101 2102 void GLContext::SharedContextDestroyed(GLContext* aChild) { 2103 MarkContextDestroyedInArray(aChild, mTrackedPrograms); 2104 MarkContextDestroyedInArray(aChild, mTrackedShaders); 2105 MarkContextDestroyedInArray(aChild, mTrackedTextures); 2106 MarkContextDestroyedInArray(aChild, mTrackedFramebuffers); 2107 MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers); 2108 MarkContextDestroyedInArray(aChild, mTrackedBuffers); 2109 MarkContextDestroyedInArray(aChild, mTrackedQueries); 2110 } 2111 2112 static void ReportArrayContents( 2113 const char* title, const nsTArray<GLContext::NamedResource>& aArray) { 2114 if (aArray.Length() == 0) return; 2115 2116 printf_stderr("%s:\n", title); 2117 2118 nsTArray<GLContext::NamedResource> copy(aArray.Clone()); 2119 copy.Sort(); 2120 2121 // Accumulate the output in a buffer to avoid interleaved output. 2122 nsCString line; 2123 2124 GLContext* lastContext = nullptr; 2125 for (uint32_t i = 0; i < copy.Length(); ++i) { 2126 if (lastContext != copy[i].origin) { 2127 if (lastContext) { 2128 printf_stderr("%s\n", line.BeginReading()); 2129 line.Assign(""); 2130 } 2131 line.Append(nsPrintfCString(" [%p - %s] ", copy[i].origin, 2132 copy[i].originDeleted ? "deleted" : "live")); 2133 lastContext = copy[i].origin; 2134 } 2135 line.AppendInt(copy[i].name); 2136 line.Append(' '); 2137 } 2138 printf_stderr("%s\n", line.BeginReading()); 2139 } 2140 2141 void GLContext::ReportOutstandingNames() { 2142 if (!ShouldSpew()) return; 2143 2144 printf_stderr("== GLContext %p Outstanding ==\n", this); 2145 2146 ReportArrayContents("Outstanding Textures", mTrackedTextures); 2147 ReportArrayContents("Outstanding Buffers", mTrackedBuffers); 2148 ReportArrayContents("Outstanding Queries", mTrackedQueries); 2149 ReportArrayContents("Outstanding Programs", mTrackedPrograms); 2150 ReportArrayContents("Outstanding Shaders", mTrackedShaders); 2151 ReportArrayContents("Outstanding Framebuffers", mTrackedFramebuffers); 2152 ReportArrayContents("Outstanding Renderbuffers", mTrackedRenderbuffers); 2153 } 2154 2155 #endif // ifdef MOZ_GL_DEBUG_BUILD 2156 2157 bool GLContext::IsOffscreenSizeAllowed(const IntSize& aSize) const { 2158 int32_t biggerDimension = std::max(aSize.width, aSize.height); 2159 int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize); 2160 return biggerDimension <= maxAllowed; 2161 } 2162 2163 bool GLContext::IsValidOwningThread() const { 2164 if (!mOwningThreadId) return true; // Free for all! 2165 return PlatformThread::CurrentId() == *mOwningThreadId; 2166 } 2167 2168 GLBlitHelper* GLContext::BlitHelper() { 2169 if (!mBlitHelper) { 2170 mBlitHelper.reset(new GLBlitHelper(this)); 2171 } 2172 2173 return mBlitHelper.get(); 2174 } 2175 2176 GLReadTexImageHelper* GLContext::ReadTexImageHelper() { 2177 if (!mReadTexImageHelper) { 2178 mReadTexImageHelper = MakeUnique<GLReadTexImageHelper>(this); 2179 } 2180 2181 return mReadTexImageHelper.get(); 2182 } 2183 2184 void GLContext::FlushIfHeavyGLCallsSinceLastFlush() { 2185 if (!mHeavyGLCallsSinceLastFlush) { 2186 return; 2187 } 2188 if (MakeCurrent()) { 2189 fFlush(); 2190 } 2191 } 2192 2193 /*static*/ 2194 bool GLContext::ShouldDumpExts() { return gfxEnv::MOZ_GL_DUMP_EXTS(); } 2195 2196 bool DoesStringMatch(const char* aString, const char* aWantedString) { 2197 if (!aString || !aWantedString) return false; 2198 2199 const char* occurrence = strstr(aString, aWantedString); 2200 2201 // aWanted not found 2202 if (!occurrence) return false; 2203 2204 // aWantedString preceded by alpha character 2205 if (occurrence != aString && isalpha(*(occurrence - 1))) return false; 2206 2207 // aWantedVendor followed by alpha character 2208 const char* afterOccurrence = occurrence + strlen(aWantedString); 2209 if (isalpha(*afterOccurrence)) return false; 2210 2211 return true; 2212 } 2213 2214 /*static*/ 2215 bool GLContext::ShouldSpew() { return gfxEnv::MOZ_GL_SPEW(); } 2216 2217 void SplitByChar(const nsACString& str, const char delim, 2218 std::vector<nsCString>* const out) { 2219 uint32_t start = 0; 2220 while (true) { 2221 int32_t end = str.FindChar(' ', start); 2222 if (end == -1) break; 2223 2224 uint32_t len = (uint32_t)end - start; 2225 nsDependentCSubstring substr(str, start, len); 2226 out->push_back(nsCString(substr)); 2227 2228 start = end + 1; 2229 } 2230 2231 nsDependentCSubstring substr(str, start); 2232 out->push_back(nsCString(substr)); 2233 } 2234 2235 void GLContext::fCopyTexImage2D(GLenum target, GLint level, 2236 GLenum internalformat, GLint x, GLint y, 2237 GLsizei width, GLsizei height, GLint border) { 2238 if (!IsTextureSizeSafeToPassToDriver(target, width, height)) { 2239 // pass wrong values to cause the GL to generate GL_INVALID_VALUE. 2240 // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver. 2241 level = -1; 2242 width = -1; 2243 height = -1; 2244 border = -1; 2245 } 2246 2247 BeforeGLReadCall(); 2248 raw_fCopyTexImage2D(target, level, internalformat, x, y, width, height, 2249 border); 2250 AfterGLReadCall(); 2251 } 2252 2253 void GLContext::fGetIntegerv(const GLenum pname, GLint* const params) const { 2254 const auto AssertBinding = [&](const char* const name, const GLenum binding, 2255 const GLuint expected) { 2256 if (MOZ_LIKELY(!mDebugFlags)) return; 2257 GLuint actual = 0; 2258 raw_fGetIntegerv(binding, (GLint*)&actual); 2259 if (actual != expected) { 2260 gfxCriticalError() << "Misprediction: " << name << " expected " 2261 << expected << ", was " << actual; 2262 } 2263 }; 2264 2265 switch (pname) { 2266 case LOCAL_GL_MAX_TEXTURE_SIZE: 2267 MOZ_ASSERT(mMaxTextureSize > 0); 2268 *params = mMaxTextureSize; 2269 return; 2270 2271 case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE: 2272 MOZ_ASSERT(mMaxCubeMapTextureSize > 0); 2273 *params = mMaxCubeMapTextureSize; 2274 return; 2275 2276 case LOCAL_GL_MAX_RENDERBUFFER_SIZE: 2277 MOZ_ASSERT(mMaxRenderbufferSize > 0); 2278 *params = mMaxRenderbufferSize; 2279 return; 2280 2281 case LOCAL_GL_VIEWPORT: 2282 for (size_t i = 0; i < 4; i++) { 2283 params[i] = mViewportRect[i]; 2284 } 2285 return; 2286 2287 case LOCAL_GL_SCISSOR_BOX: 2288 for (size_t i = 0; i < 4; i++) { 2289 params[i] = mScissorRect[i]; 2290 } 2291 return; 2292 2293 case LOCAL_GL_DRAW_FRAMEBUFFER_BINDING: 2294 if (mElideDuplicateBindFramebuffers) { 2295 static_assert(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING == 2296 LOCAL_GL_FRAMEBUFFER_BINDING); 2297 AssertBinding("GL_DRAW_FRAMEBUFFER_BINDING", 2298 LOCAL_GL_DRAW_FRAMEBUFFER_BINDING, mCachedDrawFb); 2299 *params = static_cast<GLint>(mCachedDrawFb); 2300 return; 2301 } 2302 break; 2303 2304 case LOCAL_GL_READ_FRAMEBUFFER_BINDING: 2305 if (mElideDuplicateBindFramebuffers) { 2306 if (IsSupported(GLFeature::framebuffer_blit)) { 2307 AssertBinding("GL_READ_FRAMEBUFFER_BINDING", 2308 LOCAL_GL_READ_FRAMEBUFFER_BINDING, mCachedReadFb); 2309 } 2310 *params = static_cast<GLint>(mCachedReadFb); 2311 return; 2312 } 2313 break; 2314 2315 default: 2316 break; 2317 } 2318 raw_fGetIntegerv(pname, params); 2319 } 2320 2321 void GLContext::fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, 2322 GLenum format, GLenum type, GLvoid* pixels) { 2323 BeforeGLReadCall(); 2324 raw_fReadPixels(x, y, width, height, format, type, pixels); 2325 AfterGLReadCall(); 2326 2327 // Check if GL is giving back 1.0 alpha for 2328 // RGBA reads to RGBA images from no-alpha buffers. 2329 #ifdef XP_MACOSX 2330 if (WorkAroundDriverBugs() && Vendor() == gl::GLVendor::NVIDIA && 2331 format == LOCAL_GL_RGBA && type == LOCAL_GL_UNSIGNED_BYTE && 2332 !IsCoreProfile() && width && height) { 2333 GLint alphaBits = 0; 2334 fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits); 2335 if (!alphaBits) { 2336 const uint32_t alphaMask = 0xff000000; 2337 2338 uint32_t* itr = (uint32_t*)pixels; 2339 uint32_t testPixel = *itr; 2340 if ((testPixel & alphaMask) != alphaMask) { 2341 // We need to set the alpha channel to 1.0 manually. 2342 uint32_t* itrEnd = 2343 itr + width * height; // Stride is guaranteed to be width*4. 2344 2345 for (; itr != itrEnd; itr++) { 2346 *itr |= alphaMask; 2347 } 2348 } 2349 } 2350 } 2351 #endif 2352 } 2353 2354 void GLContext::fDeleteFramebuffers(GLsizei n, const GLuint* names) { 2355 // Avoid crash by flushing before glDeleteFramebuffers. See bug 1194923. 2356 if (mNeedsFlushBeforeDeleteFB) { 2357 fFlush(); 2358 } 2359 2360 if (n == 1 && *names == 0) { 2361 // Deleting framebuffer 0 causes hangs on the DROID. See bug 623228. 2362 } else { 2363 raw_fDeleteFramebuffers(n, names); 2364 } 2365 TRACKING_CONTEXT(DeletedFramebuffers(this, n, names)); 2366 } 2367 2368 #ifdef MOZ_WIDGET_ANDROID 2369 /** 2370 * Conservatively estimate whether there is enough available 2371 * contiguous virtual address space to map a newly allocated texture. 2372 */ 2373 static bool WillTextureMapSucceed(GLsizei width, GLsizei height, GLenum format, 2374 GLenum type) { 2375 bool willSucceed = false; 2376 // Some drivers leave large gaps between textures, so require 2377 // there to be double the actual size of the texture available. 2378 size_t size = width * height * GetBytesPerTexel(format, type) * 2; 2379 2380 void* p = mmap(nullptr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 2381 if (p != MAP_FAILED) { 2382 willSucceed = true; 2383 munmap(p, size); 2384 } 2385 2386 return willSucceed; 2387 } 2388 #endif // MOZ_WIDGET_ANDROID 2389 2390 void GLContext::fTexImage2D(GLenum target, GLint level, GLint internalformat, 2391 GLsizei width, GLsizei height, GLint border, 2392 GLenum format, GLenum type, const GLvoid* pixels) { 2393 if (!IsTextureSizeSafeToPassToDriver(target, width, height)) { 2394 // pass wrong values to cause the GL to generate GL_INVALID_VALUE. 2395 // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver. 2396 level = -1; 2397 width = -1; 2398 height = -1; 2399 border = -1; 2400 } 2401 #if MOZ_WIDGET_ANDROID 2402 if (mTextureAllocCrashesOnMapFailure) { 2403 // We have no way of knowing whether this texture already has 2404 // storage allocated for it, and therefore whether this check 2405 // is necessary. We must therefore assume it does not and 2406 // always perform the check. 2407 if (!WillTextureMapSucceed(width, height, internalformat, type)) { 2408 return; 2409 } 2410 } 2411 #endif 2412 raw_fTexImage2D(target, level, internalformat, width, height, border, format, 2413 type, pixels); 2414 } 2415 2416 UniquePtr<Texture> CreateTexture(GLContext& gl, const gfx::IntSize& size) { 2417 const GLenum target = LOCAL_GL_TEXTURE_2D; 2418 const GLenum format = LOCAL_GL_RGBA; 2419 2420 auto tex = MakeUnique<Texture>(gl); 2421 ScopedBindTexture autoTex(&gl, tex->name, target); 2422 2423 gl.fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR); 2424 gl.fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR); 2425 gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); 2426 gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); 2427 2428 gl.fTexImage2D(target, 0, format, size.width, size.height, 0, format, 2429 LOCAL_GL_UNSIGNED_BYTE, nullptr); 2430 2431 return tex; 2432 } 2433 2434 uint32_t GetBytesPerTexel(GLenum format, GLenum type) { 2435 // If there is no defined format or type, we're not taking up any memory 2436 if (!format || !type) { 2437 return 0; 2438 } 2439 2440 if (format == LOCAL_GL_DEPTH_COMPONENT) { 2441 if (type == LOCAL_GL_UNSIGNED_SHORT) 2442 return 2; 2443 else if (type == LOCAL_GL_UNSIGNED_INT) 2444 return 4; 2445 } else if (format == LOCAL_GL_DEPTH_STENCIL) { 2446 if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT) return 4; 2447 } 2448 2449 if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT || 2450 type == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV) { 2451 uint32_t multiplier = type == LOCAL_GL_UNSIGNED_BYTE ? 1 : 4; 2452 switch (format) { 2453 case LOCAL_GL_ALPHA: 2454 case LOCAL_GL_LUMINANCE: 2455 case LOCAL_GL_R8: 2456 return 1 * multiplier; 2457 case LOCAL_GL_LUMINANCE_ALPHA: 2458 case LOCAL_GL_R16: 2459 return 2 * multiplier; 2460 case LOCAL_GL_RGB: 2461 return 3 * multiplier; 2462 case LOCAL_GL_RGBA: 2463 case LOCAL_GL_BGRA_EXT: 2464 return 4 * multiplier; 2465 default: 2466 break; 2467 } 2468 } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 || 2469 type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 || 2470 type == LOCAL_GL_UNSIGNED_SHORT_5_6_5 || 2471 type == LOCAL_GL_UNSIGNED_SHORT) { 2472 return 2; 2473 } 2474 2475 gfxCriticalError() << "Unknown texture type " << type << " or format " 2476 << format; 2477 return 0; 2478 } 2479 2480 void GLContext::ResetTLSCurrentContext() { 2481 if (sCurrentContext.init()) { 2482 sCurrentContext.set(nullptr); 2483 } 2484 } 2485 2486 bool GLContext::MakeCurrent(bool aForce) const { 2487 if (MOZ_UNLIKELY(IsContextLost())) return false; 2488 2489 if (MOZ_LIKELY(!aForce)) { 2490 bool isCurrent; 2491 if (mUseTLSIsCurrent && sCurrentContext.init()) { 2492 isCurrent = (sCurrentContext.get() == this); 2493 } else { 2494 isCurrent = IsCurrentImpl(); 2495 } 2496 if (MOZ_LIKELY(isCurrent)) { 2497 MOZ_ASSERT(IsCurrentImpl() || 2498 MakeCurrentImpl()); // Might have lost context. 2499 return true; 2500 } 2501 } 2502 if (!IsValidOwningThread()) { 2503 gfxCriticalError() << "MakeCurrent called on a thread other than the" 2504 << " creating thread!"; 2505 if (gfxEnv::MOZ_GL_RELEASE_ASSERT_CONTEXT_OWNERSHIP()) { 2506 MOZ_CRASH("MOZ_GL_RELEASE_ASSERT_CONTEXT_OWNERSHIP"); 2507 } 2508 } 2509 if (!MakeCurrentImpl()) return false; 2510 2511 if (sCurrentContext.init()) { 2512 sCurrentContext.set(this); 2513 } 2514 return true; 2515 } 2516 2517 void GLContext::ResetSyncCallCount(const char* resetReason) const { 2518 if (ShouldSpew()) { 2519 printf_stderr("On %s, mSyncGLCallCount = %" PRIu64 "\n", resetReason, 2520 mSyncGLCallCount); 2521 } 2522 2523 mSyncGLCallCount = 0; 2524 } 2525 2526 // - 2527 2528 bool CheckContextLost(const GLContext* const gl) { 2529 return gl->CheckContextLost(); 2530 } 2531 2532 // - 2533 2534 GLenum GLContext::GetError() const { 2535 if (mContextLost) return LOCAL_GL_CONTEXT_LOST; 2536 2537 if (mImplicitMakeCurrent) { 2538 (void)MakeCurrent(); 2539 } 2540 2541 const auto fnGetError = [&]() { 2542 const auto ret = mSymbols.fGetError(); 2543 if (ret == LOCAL_GL_CONTEXT_LOST) { 2544 OnContextLostError(); 2545 mTopError = ret; // Promote to top! 2546 } 2547 return ret; 2548 }; 2549 2550 auto ret = fnGetError(); 2551 2552 { 2553 auto flushedErr = ret; 2554 uint32_t i = 1; 2555 while (flushedErr && !mContextLost) { 2556 if (i == 100) { 2557 gfxCriticalError() << "Flushing glGetError still " 2558 << gfx::hexa(flushedErr) << " after " << i 2559 << " calls."; 2560 break; 2561 } 2562 flushedErr = fnGetError(); 2563 i += 1; 2564 } 2565 } 2566 2567 if (mTopError) { 2568 ret = mTopError; 2569 mTopError = 0; 2570 } 2571 2572 if (mDebugFlags & DebugFlagTrace) { 2573 const auto errStr = GLErrorToString(ret); 2574 printf_stderr("[gl:%p] GetError() -> %s\n", this, errStr.c_str()); 2575 } 2576 return ret; 2577 } 2578 2579 GLenum GLContext::fGetGraphicsResetStatus() const { 2580 OnSyncCall(); 2581 2582 GLenum ret = 0; 2583 if (mSymbols.fGetGraphicsResetStatus) { 2584 if (mImplicitMakeCurrent) { 2585 (void)MakeCurrent(); 2586 } 2587 ret = mSymbols.fGetGraphicsResetStatus(); 2588 } else { 2589 if (!MakeCurrent(true)) { 2590 ret = LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB; 2591 } 2592 } 2593 2594 if (mDebugFlags & DebugFlagTrace) { 2595 printf_stderr("[gl:%p] GetGraphicsResetStatus() -> 0x%04x\n", this, ret); 2596 } 2597 2598 return ret; 2599 } 2600 2601 void GLContext::OnContextLostError() const { 2602 if (mDebugFlags & DebugFlagTrace) { 2603 printf_stderr("[gl:%p] CONTEXT_LOST\n", this); 2604 } 2605 mContextLost = true; 2606 } 2607 2608 // -- 2609 2610 /*static*/ std::string GLContext::GLErrorToString(const GLenum err) { 2611 switch (err) { 2612 case LOCAL_GL_NO_ERROR: 2613 return "GL_NO_ERROR"; 2614 case LOCAL_GL_INVALID_ENUM: 2615 return "GL_INVALID_ENUM"; 2616 case LOCAL_GL_INVALID_VALUE: 2617 return "GL_INVALID_VALUE"; 2618 case LOCAL_GL_INVALID_OPERATION: 2619 return "GL_INVALID_OPERATION"; 2620 case LOCAL_GL_STACK_OVERFLOW: 2621 return "GL_STACK_OVERFLOW"; 2622 case LOCAL_GL_STACK_UNDERFLOW: 2623 return "GL_STACK_UNDERFLOW"; 2624 case LOCAL_GL_OUT_OF_MEMORY: 2625 return "GL_OUT_OF_MEMORY"; 2626 case LOCAL_GL_TABLE_TOO_LARGE: 2627 return "GL_TABLE_TOO_LARGE"; 2628 case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION: 2629 return "GL_INVALID_FRAMEBUFFER_OPERATION"; 2630 case LOCAL_GL_CONTEXT_LOST: 2631 return "GL_CONTEXT_LOST"; 2632 } 2633 2634 const nsPrintfCString hex("<enum 0x%04x>", err); 2635 return hex.BeginReading(); 2636 } 2637 2638 // -- 2639 2640 void GLContext::BeforeGLCall_Debug(const char* const funcName) const { 2641 MOZ_ASSERT(mDebugFlags); 2642 2643 if (mDebugFlags & DebugFlagTrace) { 2644 printf_stderr("[gl:%p] > %s\n", this, funcName); 2645 } 2646 2647 MOZ_ASSERT(!mDebugErrorScope); 2648 mDebugErrorScope.reset(new LocalErrorScope(*this)); 2649 } 2650 2651 void GLContext::AfterGLCall_Debug(const char* const funcName) const { 2652 MOZ_ASSERT(mDebugFlags); 2653 2654 // calling fFinish() immediately after every GL call makes sure that if this 2655 // GL command crashes, the stack trace will actually point to it. Otherwise, 2656 // OpenGL being an asynchronous API, stack traces tend to be meaningless 2657 mSymbols.fFinish(); 2658 2659 const auto err = mDebugErrorScope->GetError(); 2660 mDebugErrorScope = nullptr; 2661 if (!mTopError) { 2662 mTopError = err; 2663 } 2664 2665 if (mDebugFlags & DebugFlagTrace) { 2666 printf_stderr("[gl:%p] < %s [%s]\n", this, funcName, 2667 GLErrorToString(err).c_str()); 2668 } 2669 2670 if (err && !mLocalErrorScopeStack.size()) { 2671 const auto errStr = GLErrorToString(err); 2672 const auto text = nsPrintfCString("%s: Generated unexpected %s error", 2673 funcName, errStr.c_str()); 2674 printf_stderr("[gl:%p] %s.\n", this, text.BeginReading()); 2675 2676 const bool abortOnError = mDebugFlags & DebugFlagAbortOnError; 2677 if (abortOnError && err != LOCAL_GL_CONTEXT_LOST) { 2678 gfxCriticalErrorOnce() << text.BeginReading(); 2679 MOZ_CRASH( 2680 "Aborting... (Run with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)"); 2681 } 2682 } 2683 } 2684 2685 /*static*/ 2686 void GLContext::OnImplicitMakeCurrentFailure(const char* const funcName) { 2687 gfxCriticalError() << "Ignoring call to " << funcName << " with failed" 2688 << " mImplicitMakeCurrent."; 2689 } 2690 2691 bool GLContext::CreateOffscreenDefaultFb(const gfx::IntSize& size) { 2692 mOffscreenDefaultFb = MozFramebuffer::Create(this, size, 0, true); 2693 return bool(mOffscreenDefaultFb); 2694 } 2695 2696 // Some of Mesa's drivers allocate heap memory when loaded and don't 2697 // free it when unloaded; this causes Leak Sanitizer to detect leaks and 2698 // fail to unwind the stack, so suppressions don't work. This 2699 // workaround leaks a reference to the driver library so that it's never 2700 // unloaded. Because the leak isn't significant for real usage, only 2701 // ASan runs in CI, this is applied only to the software renderer. 2702 // 2703 // See bug 1702394 for more details. 2704 void MesaMemoryLeakWorkaround() { 2705 #if defined(XP_LINUX) && !defined(ANDROID) 2706 Maybe<nsAutoCString> foundPath; 2707 2708 dl_iterate_phdr( 2709 [](dl_phdr_info* info, size_t size, void* data) { 2710 auto& foundPath = *reinterpret_cast<Maybe<nsAutoCString>*>(data); 2711 nsDependentCString thisPath(info->dlpi_name); 2712 if (StringEndsWith(thisPath, "/swrast_dri.so"_ns)) { 2713 foundPath.emplace(thisPath); 2714 return 1; 2715 } 2716 return 0; 2717 }, 2718 &foundPath); 2719 2720 if (foundPath) { 2721 // Deliberately leak to prevent unload 2722 (void)dlopen(foundPath->get(), RTLD_LAZY); 2723 } 2724 #endif // XP_LINUX but not ANDROID 2725 } 2726 2727 } /* namespace gl */ 2728 } /* namespace mozilla */