tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 */