LCOV - code coverage report
Current view: top level - gfx/gl - GLContext.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 3 1461 0.2 %
Date: 2017-07-14 16:53:18 Functions: 1 82 1.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim: set ts=8 sts=4 et sw=4 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 <stdio.h>
      11             : #include <string.h>
      12             : #include <ctype.h>
      13             : #include <regex>
      14             : #include <string>
      15             : #include <vector>
      16             : #ifdef MOZ_WIDGET_ANDROID
      17             : #include <sys/mman.h>
      18             : #endif
      19             : 
      20             : #include "GLBlitHelper.h"
      21             : #include "GLReadTexImageHelper.h"
      22             : #include "GLScreenBuffer.h"
      23             : 
      24             : #include "gfxCrashReporterUtils.h"
      25             : #include "gfxEnv.h"
      26             : #include "gfxUtils.h"
      27             : #include "GLContextProvider.h"
      28             : #include "GLTextureImage.h"
      29             : #include "nsPrintfCString.h"
      30             : #include "nsThreadUtils.h"
      31             : #include "prenv.h"
      32             : #include "prlink.h"
      33             : #include "ScopedGLHelpers.h"
      34             : #include "SharedSurfaceGL.h"
      35             : #include "GfxTexturesReporter.h"
      36             : #include "gfx2DGlue.h"
      37             : #include "gfxPrefs.h"
      38             : #include "mozilla/IntegerPrintfMacros.h"
      39             : #include "mozilla/gfx/Logging.h"
      40             : 
      41             : #include "OGLShaderProgram.h" // for ShaderProgramType
      42             : 
      43             : #include "mozilla/DebugOnly.h"
      44             : 
      45             : #ifdef XP_MACOSX
      46             : #include <CoreServices/CoreServices.h>
      47             : #endif
      48             : 
      49             : #if defined(MOZ_WIDGET_COCOA)
      50             : #include "nsCocoaFeatures.h"
      51             : #endif
      52             : 
      53             : #ifdef MOZ_WIDGET_ANDROID
      54             : #include "AndroidBridge.h"
      55             : #endif
      56             : 
      57             : namespace mozilla {
      58             : namespace gl {
      59             : 
      60             : using namespace mozilla::gfx;
      61             : using namespace mozilla::layers;
      62             : 
      63             : #ifdef MOZ_GL_DEBUG
      64             : unsigned GLContext::sCurrentGLContextTLS = -1;
      65             : #endif
      66             : 
      67             : MOZ_THREAD_LOCAL(GLContext*) GLContext::sCurrentContext;
      68             : 
      69             : // If adding defines, don't forget to undefine symbols. See #undef block below.
      70             : #define CORE_SYMBOL(x) { (PRFuncPtr*) &mSymbols.f##x, { #x, nullptr } }
      71             : #define CORE_EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x, #x #y, #x #z, nullptr } }
      72             : #define EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, nullptr } }
      73             : #define EXT_SYMBOL3(x,y,z,w) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, #x #w, nullptr } }
      74             : #define END_SYMBOLS { nullptr, { nullptr } }
      75             : 
      76             : // should match the order of GLExtensions, and be null-terminated.
      77             : static const char* const sExtensionNames[] = {
      78             :     "NO_EXTENSION",
      79             :     "GL_AMD_compressed_ATC_texture",
      80             :     "GL_ANGLE_depth_texture",
      81             :     "GL_ANGLE_framebuffer_blit",
      82             :     "GL_ANGLE_framebuffer_multisample",
      83             :     "GL_ANGLE_instanced_arrays",
      84             :     "GL_ANGLE_texture_compression_dxt3",
      85             :     "GL_ANGLE_texture_compression_dxt5",
      86             :     "GL_ANGLE_timer_query",
      87             :     "GL_APPLE_client_storage",
      88             :     "GL_APPLE_framebuffer_multisample",
      89             :     "GL_APPLE_sync",
      90             :     "GL_APPLE_texture_range",
      91             :     "GL_APPLE_vertex_array_object",
      92             :     "GL_ARB_ES2_compatibility",
      93             :     "GL_ARB_ES3_compatibility",
      94             :     "GL_ARB_color_buffer_float",
      95             :     "GL_ARB_compatibility",
      96             :     "GL_ARB_copy_buffer",
      97             :     "GL_ARB_depth_texture",
      98             :     "GL_ARB_draw_buffers",
      99             :     "GL_ARB_draw_instanced",
     100             :     "GL_ARB_framebuffer_object",
     101             :     "GL_ARB_framebuffer_sRGB",
     102             :     "GL_ARB_geometry_shader4",
     103             :     "GL_ARB_half_float_pixel",
     104             :     "GL_ARB_instanced_arrays",
     105             :     "GL_ARB_internalformat_query",
     106             :     "GL_ARB_invalidate_subdata",
     107             :     "GL_ARB_map_buffer_range",
     108             :     "GL_ARB_occlusion_query2",
     109             :     "GL_ARB_pixel_buffer_object",
     110             :     "GL_ARB_robust_buffer_access_behavior",
     111             :     "GL_ARB_robustness",
     112             :     "GL_ARB_sampler_objects",
     113             :     "GL_ARB_seamless_cube_map",
     114             :     "GL_ARB_shader_texture_lod",
     115             :     "GL_ARB_sync",
     116             :     "GL_ARB_texture_compression",
     117             :     "GL_ARB_texture_float",
     118             :     "GL_ARB_texture_non_power_of_two",
     119             :     "GL_ARB_texture_rectangle",
     120             :     "GL_ARB_texture_rg",
     121             :     "GL_ARB_texture_storage",
     122             :     "GL_ARB_texture_swizzle",
     123             :     "GL_ARB_timer_query",
     124             :     "GL_ARB_transform_feedback2",
     125             :     "GL_ARB_uniform_buffer_object",
     126             :     "GL_ARB_vertex_array_object",
     127             :     "GL_EXT_bgra",
     128             :     "GL_EXT_blend_minmax",
     129             :     "GL_EXT_color_buffer_float",
     130             :     "GL_EXT_color_buffer_half_float",
     131             :     "GL_EXT_copy_texture",
     132             :     "GL_EXT_disjoint_timer_query",
     133             :     "GL_EXT_draw_buffers",
     134             :     "GL_EXT_draw_buffers2",
     135             :     "GL_EXT_draw_instanced",
     136             :     "GL_EXT_draw_range_elements",
     137             :     "GL_EXT_frag_depth",
     138             :     "GL_EXT_framebuffer_blit",
     139             :     "GL_EXT_framebuffer_multisample",
     140             :     "GL_EXT_framebuffer_object",
     141             :     "GL_EXT_framebuffer_sRGB",
     142             :     "GL_EXT_gpu_shader4",
     143             :     "GL_EXT_multisampled_render_to_texture",
     144             :     "GL_EXT_occlusion_query_boolean",
     145             :     "GL_EXT_packed_depth_stencil",
     146             :     "GL_EXT_read_format_bgra",
     147             :     "GL_EXT_robustness",
     148             :     "GL_EXT_sRGB",
     149             :     "GL_EXT_sRGB_write_control",
     150             :     "GL_EXT_shader_texture_lod",
     151             :     "GL_EXT_texture3D",
     152             :     "GL_EXT_texture_compression_dxt1",
     153             :     "GL_EXT_texture_compression_s3tc",
     154             :     "GL_EXT_texture_filter_anisotropic",
     155             :     "GL_EXT_texture_format_BGRA8888",
     156             :     "GL_EXT_texture_sRGB",
     157             :     "GL_EXT_texture_storage",
     158             :     "GL_EXT_timer_query",
     159             :     "GL_EXT_transform_feedback",
     160             :     "GL_EXT_unpack_subimage",
     161             :     "GL_IMG_read_format",
     162             :     "GL_IMG_texture_compression_pvrtc",
     163             :     "GL_IMG_texture_npot",
     164             :     "GL_KHR_debug",
     165             :     "GL_KHR_robust_buffer_access_behavior",
     166             :     "GL_KHR_robustness",
     167             :     "GL_KHR_texture_compression_astc_hdr",
     168             :     "GL_KHR_texture_compression_astc_ldr",
     169             :     "GL_NV_draw_instanced",
     170             :     "GL_NV_fence",
     171             :     "GL_NV_framebuffer_blit",
     172             :     "GL_NV_geometry_program4",
     173             :     "GL_NV_half_float",
     174             :     "GL_NV_instanced_arrays",
     175             :     "GL_NV_primitive_restart",
     176             :     "GL_NV_texture_barrier",
     177             :     "GL_NV_transform_feedback",
     178             :     "GL_NV_transform_feedback2",
     179             :     "GL_OES_EGL_image",
     180             :     "GL_OES_EGL_image_external",
     181             :     "GL_OES_EGL_sync",
     182             :     "GL_OES_compressed_ETC1_RGB8_texture",
     183             :     "GL_OES_depth24",
     184             :     "GL_OES_depth32",
     185             :     "GL_OES_depth_texture",
     186             :     "GL_OES_element_index_uint",
     187             :     "GL_OES_framebuffer_object",
     188             :     "GL_OES_packed_depth_stencil",
     189             :     "GL_OES_rgb8_rgba8",
     190             :     "GL_OES_standard_derivatives",
     191             :     "GL_OES_stencil8",
     192             :     "GL_OES_texture_3D",
     193             :     "GL_OES_texture_float",
     194             :     "GL_OES_texture_float_linear",
     195             :     "GL_OES_texture_half_float",
     196             :     "GL_OES_texture_half_float_linear",
     197             :     "GL_OES_texture_npot",
     198             :     "GL_OES_vertex_array_object"
     199             : };
     200             : 
     201             : static bool
     202           0 : ShouldUseTLSIsCurrent(bool useTLSIsCurrent)
     203             : {
     204           0 :     if (gfxPrefs::UseTLSIsCurrent() == 0)
     205           0 :         return useTLSIsCurrent;
     206             : 
     207           0 :     return gfxPrefs::UseTLSIsCurrent() > 0;
     208             : }
     209             : 
     210             : static bool
     211           0 : ParseVersion(const std::string& versionStr, uint32_t* const out_major,
     212             :              uint32_t* const out_minor)
     213             : {
     214           0 :     static const std::regex kVersionRegex("([0-9]+)\\.([0-9]+)");
     215           0 :     std::smatch match;
     216           0 :     if (!std::regex_search(versionStr, match, kVersionRegex))
     217           0 :         return false;
     218             : 
     219           0 :     const auto& majorStr = match.str(1);
     220           0 :     const auto& minorStr = match.str(2);
     221           0 :     *out_major = atoi(majorStr.c_str());
     222           0 :     *out_minor = atoi(minorStr.c_str());
     223           0 :     return true;
     224             : }
     225             : 
     226             : static uint8_t
     227           0 : ChooseDebugFlags(CreateContextFlags createFlags)
     228             : {
     229           0 :     uint8_t debugFlags = 0;
     230             : 
     231             : #ifdef MOZ_GL_DEBUG
     232           0 :     if (gfxEnv::GlDebug()) {
     233           0 :         debugFlags |= GLContext::DebugFlagEnabled;
     234             :     }
     235             : 
     236             :     // Enables extra verbose output, informing of the start and finish of every GL call.
     237             :     // Useful e.g. to record information to investigate graphics system crashes/lockups
     238           0 :     if (gfxEnv::GlDebugVerbose()) {
     239           0 :         debugFlags |= GLContext::DebugFlagTrace;
     240             :     }
     241             : 
     242             :     // Aborts on GL error. Can be useful to debug quicker code that is known not to
     243             :     // generate any GL error in principle.
     244           0 :     bool abortOnError = false;
     245             : 
     246           0 :     if (createFlags & CreateContextFlags::NO_VALIDATION) {
     247           0 :         abortOnError = true;
     248             : 
     249           0 :         const auto fnStringsMatch = [](const char* a, const char* b) {
     250           0 :             return strcmp(a, b) == 0;
     251           0 :         };
     252             : 
     253           0 :         const char* envAbortOnError = PR_GetEnv("MOZ_GL_DEBUG_ABORT_ON_ERROR");
     254           0 :         if (envAbortOnError && fnStringsMatch(envAbortOnError, "0")) {
     255           0 :            abortOnError = false;
     256             :         }
     257             :     }
     258             : 
     259           0 :     if (abortOnError) {
     260           0 :         debugFlags |= GLContext::DebugFlagAbortOnError;
     261             :     }
     262             : #endif
     263             : 
     264           0 :     return debugFlags;
     265             : }
     266             : 
     267           0 : GLContext::GLContext(CreateContextFlags flags, const SurfaceCaps& caps,
     268           0 :                      GLContext* sharedContext, bool isOffscreen, bool useTLSIsCurrent)
     269             :   : mIsOffscreen(isOffscreen),
     270             :     mContextLost(false),
     271           0 :     mUseTLSIsCurrent(ShouldUseTLSIsCurrent(useTLSIsCurrent)),
     272             :     mVersion(0),
     273             :     mProfile(ContextProfile::Unknown),
     274             :     mShadingLanguageVersion(0),
     275             :     mVendor(GLVendor::Other),
     276             :     mRenderer(GLRenderer::Other),
     277             :     mTopError(LOCAL_GL_NO_ERROR),
     278           0 :     mDebugFlags(ChooseDebugFlags(flags)),
     279             :     mSharedContext(sharedContext),
     280             :     mCaps(caps),
     281             :     mScreen(nullptr),
     282             :     mLockedSurface(nullptr),
     283             :     mMaxTextureSize(0),
     284             :     mMaxCubeMapTextureSize(0),
     285             :     mMaxTextureImageSize(0),
     286             :     mMaxRenderbufferSize(0),
     287             :     mMaxSamples(0),
     288             :     mNeedsTextureSizeChecks(false),
     289             :     mNeedsFlushBeforeDeleteFB(false),
     290             :     mTextureAllocCrashesOnMapFailure(false),
     291             :     mNeedsCheckAfterAttachTextureToFb(false),
     292             :     mWorkAroundDriverBugs(true),
     293           0 :     mHeavyGLCallsSinceLastFlush(false)
     294             : {
     295           0 :     mMaxViewportDims[0] = 0;
     296           0 :     mMaxViewportDims[1] = 0;
     297           0 :     mOwningThreadId = PlatformThread::CurrentId();
     298           0 :     MOZ_ALWAYS_TRUE( sCurrentContext.init() );
     299           0 :     sCurrentContext.set(nullptr);
     300           0 : }
     301             : 
     302           0 : GLContext::~GLContext() {
     303           0 :     NS_ASSERTION(IsDestroyed(), "GLContext implementation must call MarkDestroyed in destructor!");
     304             : #ifdef MOZ_GL_DEBUG
     305           0 :     if (mSharedContext) {
     306           0 :         GLContext* tip = mSharedContext;
     307           0 :         while (tip->mSharedContext)
     308           0 :             tip = tip->mSharedContext;
     309           0 :         tip->SharedContextDestroyed(this);
     310           0 :         tip->ReportOutstandingNames();
     311             :     } else {
     312           0 :         ReportOutstandingNames();
     313             :     }
     314             : #endif
     315           0 : }
     316             : 
     317             : /*static*/ void
     318           0 : GLContext::StaticDebugCallback(GLenum source,
     319             :                                GLenum type,
     320             :                                GLuint id,
     321             :                                GLenum severity,
     322             :                                GLsizei length,
     323             :                                const GLchar* message,
     324             :                                const GLvoid* userParam)
     325             : {
     326           0 :     GLContext* gl = (GLContext*)userParam;
     327           0 :     gl->DebugCallback(source, type, id, severity, length, message);
     328           0 : }
     329             : 
     330             : static void
     331           0 : ClearSymbols(const GLLibraryLoader::SymLoadStruct* symbols)
     332             : {
     333           0 :     while (symbols->symPointer) {
     334           0 :         *symbols->symPointer = nullptr;
     335           0 :         symbols++;
     336             :     }
     337           0 : }
     338             : 
     339             : bool
     340           0 : GLContext::InitWithPrefix(const char* prefix, bool trygl)
     341             : {
     342           0 :     MOZ_RELEASE_ASSERT(!mSymbols.fBindFramebuffer,
     343             :                        "GFX: InitWithPrefix should only be called once.");
     344             : 
     345           0 :     ScopedGfxFeatureReporter reporter("GL Context");
     346             : 
     347           0 :     if (!InitWithPrefixImpl(prefix, trygl)) {
     348             :         // If initialization fails, zero the symbols to avoid hard-to-understand bugs.
     349           0 :         mSymbols.Zero();
     350           0 :         NS_WARNING("GLContext::InitWithPrefix failed!");
     351           0 :         return false;
     352             :     }
     353             : 
     354           0 :     reporter.SetSuccessful();
     355           0 :     return true;
     356             : }
     357             : 
     358             : static bool
     359           0 : LoadGLSymbols(GLContext* gl, const char* prefix, bool trygl,
     360             :               const GLLibraryLoader::SymLoadStruct* list, const char* desc)
     361             : {
     362           0 :     if (gl->LoadSymbols(list, trygl, prefix))
     363           0 :         return true;
     364             : 
     365           0 :     ClearSymbols(list);
     366             : 
     367           0 :     if (desc) {
     368           0 :         const nsPrintfCString err("Failed to load symbols for %s.", desc);
     369           0 :         NS_ERROR(err.BeginReading());
     370             :     }
     371           0 :     return false;
     372             : }
     373             : 
     374             : bool
     375           0 : GLContext::LoadExtSymbols(const char* prefix, bool trygl, const SymLoadStruct* list,
     376             :                           GLExtensions ext)
     377             : {
     378           0 :     const char* extName = sExtensionNames[size_t(ext)];
     379           0 :     if (!LoadGLSymbols(this, prefix, trygl, list, extName)) {
     380           0 :         MarkExtensionUnsupported(ext);
     381           0 :         return false;
     382             :     }
     383           0 :     return true;
     384             : };
     385             : 
     386             : bool
     387           0 : GLContext::LoadFeatureSymbols(const char* prefix, bool trygl, const SymLoadStruct* list,
     388             :                               GLFeature feature)
     389             : {
     390           0 :     const char* featureName = GetFeatureName(feature);
     391           0 :     if (!LoadGLSymbols(this, prefix, trygl, list, featureName)) {
     392           0 :         MarkUnsupported(feature);
     393           0 :         return false;
     394             :     }
     395           0 :     return true;
     396             : };
     397             : 
     398             : bool
     399           0 : GLContext::InitWithPrefixImpl(const char* prefix, bool trygl)
     400             : {
     401           0 :     mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs();
     402             : 
     403             :     const SymLoadStruct coreSymbols[] = {
     404           0 :         { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } },
     405           0 :         { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } },
     406           0 :         { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } },
     407           0 :         { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } },
     408           0 :         { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } },
     409           0 :         { (PRFuncPtr*) &mSymbols.fBlendColor, { "BlendColor", nullptr } },
     410           0 :         { (PRFuncPtr*) &mSymbols.fBlendEquation, { "BlendEquation", nullptr } },
     411           0 :         { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, { "BlendEquationSeparate", "BlendEquationSeparateEXT", nullptr } },
     412           0 :         { (PRFuncPtr*) &mSymbols.fBlendFunc, { "BlendFunc", nullptr } },
     413           0 :         { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, { "BlendFuncSeparate", "BlendFuncSeparateEXT", nullptr } },
     414           0 :         { (PRFuncPtr*) &mSymbols.fBufferData, { "BufferData", nullptr } },
     415           0 :         { (PRFuncPtr*) &mSymbols.fBufferSubData, { "BufferSubData", nullptr } },
     416           0 :         { (PRFuncPtr*) &mSymbols.fClear, { "Clear", nullptr } },
     417           0 :         { (PRFuncPtr*) &mSymbols.fClearColor, { "ClearColor", nullptr } },
     418           0 :         { (PRFuncPtr*) &mSymbols.fClearStencil, { "ClearStencil", nullptr } },
     419           0 :         { (PRFuncPtr*) &mSymbols.fColorMask, { "ColorMask", nullptr } },
     420           0 :         { (PRFuncPtr*) &mSymbols.fCompressedTexImage2D, {"CompressedTexImage2D", nullptr} },
     421           0 :         { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage2D, {"CompressedTexSubImage2D", nullptr} },
     422           0 :         { (PRFuncPtr*) &mSymbols.fCullFace, { "CullFace", nullptr } },
     423           0 :         { (PRFuncPtr*) &mSymbols.fDetachShader, { "DetachShader", "DetachShaderARB", nullptr } },
     424           0 :         { (PRFuncPtr*) &mSymbols.fDepthFunc, { "DepthFunc", nullptr } },
     425           0 :         { (PRFuncPtr*) &mSymbols.fDepthMask, { "DepthMask", nullptr } },
     426           0 :         { (PRFuncPtr*) &mSymbols.fDisable, { "Disable", nullptr } },
     427           0 :         { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, { "DisableVertexAttribArray", "DisableVertexAttribArrayARB", nullptr } },
     428           0 :         { (PRFuncPtr*) &mSymbols.fDrawArrays, { "DrawArrays", nullptr } },
     429           0 :         { (PRFuncPtr*) &mSymbols.fDrawElements, { "DrawElements", nullptr } },
     430           0 :         { (PRFuncPtr*) &mSymbols.fEnable, { "Enable", nullptr } },
     431           0 :         { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, { "EnableVertexAttribArray", "EnableVertexAttribArrayARB", nullptr } },
     432           0 :         { (PRFuncPtr*) &mSymbols.fFinish, { "Finish", nullptr } },
     433           0 :         { (PRFuncPtr*) &mSymbols.fFlush, { "Flush", nullptr } },
     434           0 :         { (PRFuncPtr*) &mSymbols.fFrontFace, { "FrontFace", nullptr } },
     435           0 :         { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, { "GetActiveAttrib", "GetActiveAttribARB", nullptr } },
     436           0 :         { (PRFuncPtr*) &mSymbols.fGetActiveUniform, { "GetActiveUniform", "GetActiveUniformARB", nullptr } },
     437           0 :         { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, { "GetAttachedShaders", "GetAttachedShadersARB", nullptr } },
     438           0 :         { (PRFuncPtr*) &mSymbols.fGetAttribLocation, { "GetAttribLocation", "GetAttribLocationARB", nullptr } },
     439           0 :         { (PRFuncPtr*) &mSymbols.fGetIntegerv, { "GetIntegerv", nullptr } },
     440           0 :         { (PRFuncPtr*) &mSymbols.fGetFloatv, { "GetFloatv", nullptr } },
     441           0 :         { (PRFuncPtr*) &mSymbols.fGetBooleanv, { "GetBooleanv", nullptr } },
     442           0 :         { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, { "GetBufferParameteriv", "GetBufferParameterivARB", nullptr } },
     443           0 :         { (PRFuncPtr*) &mSymbols.fGetError, { "GetError", nullptr } },
     444           0 :         { (PRFuncPtr*) &mSymbols.fGetProgramiv, { "GetProgramiv", "GetProgramivARB", nullptr } },
     445           0 :         { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, { "GetProgramInfoLog", "GetProgramInfoLogARB", nullptr } },
     446           0 :         { (PRFuncPtr*) &mSymbols.fTexParameteri, { "TexParameteri", nullptr } },
     447           0 :         { (PRFuncPtr*) &mSymbols.fTexParameteriv, { "TexParameteriv", nullptr } },
     448           0 :         { (PRFuncPtr*) &mSymbols.fTexParameterf, { "TexParameterf", nullptr } },
     449           0 :         { (PRFuncPtr*) &mSymbols.fGetString, { "GetString", nullptr } },
     450           0 :         { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, { "GetTexParameterfv", nullptr } },
     451           0 :         { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, { "GetTexParameteriv", nullptr } },
     452           0 :         { (PRFuncPtr*) &mSymbols.fGetUniformfv, { "GetUniformfv", "GetUniformfvARB", nullptr } },
     453           0 :         { (PRFuncPtr*) &mSymbols.fGetUniformiv, { "GetUniformiv", "GetUniformivARB", nullptr } },
     454           0 :         { (PRFuncPtr*) &mSymbols.fGetUniformLocation, { "GetUniformLocation", "GetUniformLocationARB", nullptr } },
     455           0 :         { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, { "GetVertexAttribfv", "GetVertexAttribfvARB", nullptr } },
     456           0 :         { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, { "GetVertexAttribiv", "GetVertexAttribivARB", nullptr } },
     457           0 :         { (PRFuncPtr*) &mSymbols.fGetVertexAttribPointerv, { "GetVertexAttribPointerv", nullptr } },
     458           0 :         { (PRFuncPtr*) &mSymbols.fHint, { "Hint", nullptr } },
     459           0 :         { (PRFuncPtr*) &mSymbols.fIsBuffer, { "IsBuffer", "IsBufferARB", nullptr } },
     460           0 :         { (PRFuncPtr*) &mSymbols.fIsEnabled, { "IsEnabled", nullptr } },
     461           0 :         { (PRFuncPtr*) &mSymbols.fIsProgram, { "IsProgram", "IsProgramARB", nullptr } },
     462           0 :         { (PRFuncPtr*) &mSymbols.fIsShader, { "IsShader", "IsShaderARB", nullptr } },
     463           0 :         { (PRFuncPtr*) &mSymbols.fIsTexture, { "IsTexture", "IsTextureARB", nullptr } },
     464           0 :         { (PRFuncPtr*) &mSymbols.fLineWidth, { "LineWidth", nullptr } },
     465           0 :         { (PRFuncPtr*) &mSymbols.fLinkProgram, { "LinkProgram", "LinkProgramARB", nullptr } },
     466           0 :         { (PRFuncPtr*) &mSymbols.fPixelStorei, { "PixelStorei", nullptr } },
     467           0 :         { (PRFuncPtr*) &mSymbols.fPolygonOffset, { "PolygonOffset", nullptr } },
     468           0 :         { (PRFuncPtr*) &mSymbols.fReadPixels, { "ReadPixels", nullptr } },
     469           0 :         { (PRFuncPtr*) &mSymbols.fSampleCoverage, { "SampleCoverage", nullptr } },
     470           0 :         { (PRFuncPtr*) &mSymbols.fScissor, { "Scissor", nullptr } },
     471           0 :         { (PRFuncPtr*) &mSymbols.fStencilFunc, { "StencilFunc", nullptr } },
     472           0 :         { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, { "StencilFuncSeparate", "StencilFuncSeparateEXT", nullptr } },
     473           0 :         { (PRFuncPtr*) &mSymbols.fStencilMask, { "StencilMask", nullptr } },
     474           0 :         { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, { "StencilMaskSeparate", "StencilMaskSeparateEXT", nullptr } },
     475           0 :         { (PRFuncPtr*) &mSymbols.fStencilOp, { "StencilOp", nullptr } },
     476           0 :         { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, { "StencilOpSeparate", "StencilOpSeparateEXT", nullptr } },
     477           0 :         { (PRFuncPtr*) &mSymbols.fTexImage2D, { "TexImage2D", nullptr } },
     478           0 :         { (PRFuncPtr*) &mSymbols.fTexSubImage2D, { "TexSubImage2D", nullptr } },
     479           0 :         { (PRFuncPtr*) &mSymbols.fUniform1f, { "Uniform1f", nullptr } },
     480           0 :         { (PRFuncPtr*) &mSymbols.fUniform1fv, { "Uniform1fv", nullptr } },
     481           0 :         { (PRFuncPtr*) &mSymbols.fUniform1i, { "Uniform1i", nullptr } },
     482           0 :         { (PRFuncPtr*) &mSymbols.fUniform1iv, { "Uniform1iv", nullptr } },
     483           0 :         { (PRFuncPtr*) &mSymbols.fUniform2f, { "Uniform2f", nullptr } },
     484           0 :         { (PRFuncPtr*) &mSymbols.fUniform2fv, { "Uniform2fv", nullptr } },
     485           0 :         { (PRFuncPtr*) &mSymbols.fUniform2i, { "Uniform2i", nullptr } },
     486           0 :         { (PRFuncPtr*) &mSymbols.fUniform2iv, { "Uniform2iv", nullptr } },
     487           0 :         { (PRFuncPtr*) &mSymbols.fUniform3f, { "Uniform3f", nullptr } },
     488           0 :         { (PRFuncPtr*) &mSymbols.fUniform3fv, { "Uniform3fv", nullptr } },
     489           0 :         { (PRFuncPtr*) &mSymbols.fUniform3i, { "Uniform3i", nullptr } },
     490           0 :         { (PRFuncPtr*) &mSymbols.fUniform3iv, { "Uniform3iv", nullptr } },
     491           0 :         { (PRFuncPtr*) &mSymbols.fUniform4f, { "Uniform4f", nullptr } },
     492           0 :         { (PRFuncPtr*) &mSymbols.fUniform4fv, { "Uniform4fv", nullptr } },
     493           0 :         { (PRFuncPtr*) &mSymbols.fUniform4i, { "Uniform4i", nullptr } },
     494           0 :         { (PRFuncPtr*) &mSymbols.fUniform4iv, { "Uniform4iv", nullptr } },
     495           0 :         { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, { "UniformMatrix2fv", nullptr } },
     496           0 :         { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, { "UniformMatrix3fv", nullptr } },
     497           0 :         { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, { "UniformMatrix4fv", nullptr } },
     498           0 :         { (PRFuncPtr*) &mSymbols.fUseProgram, { "UseProgram", nullptr } },
     499           0 :         { (PRFuncPtr*) &mSymbols.fValidateProgram, { "ValidateProgram", nullptr } },
     500           0 :         { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
     501           0 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, { "VertexAttrib1f", nullptr } },
     502           0 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, { "VertexAttrib2f", nullptr } },
     503           0 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, { "VertexAttrib3f", nullptr } },
     504           0 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, { "VertexAttrib4f", nullptr } },
     505           0 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, { "VertexAttrib1fv", nullptr } },
     506           0 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, { "VertexAttrib2fv", nullptr } },
     507           0 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, { "VertexAttrib3fv", nullptr } },
     508           0 :         { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, { "VertexAttrib4fv", nullptr } },
     509           0 :         { (PRFuncPtr*) &mSymbols.fViewport, { "Viewport", nullptr } },
     510           0 :         { (PRFuncPtr*) &mSymbols.fCompileShader, { "CompileShader", nullptr } },
     511           0 :         { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, { "CopyTexImage2D", nullptr } },
     512           0 :         { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, { "CopyTexSubImage2D", nullptr } },
     513           0 :         { (PRFuncPtr*) &mSymbols.fGetShaderiv, { "GetShaderiv", nullptr } },
     514           0 :         { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, { "GetShaderInfoLog", nullptr } },
     515           0 :         { (PRFuncPtr*) &mSymbols.fGetShaderSource, { "GetShaderSource", nullptr } },
     516           0 :         { (PRFuncPtr*) &mSymbols.fShaderSource, { "ShaderSource", nullptr } },
     517           0 :         { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
     518             : 
     519           0 :         { (PRFuncPtr*) &mSymbols.fGenBuffers, { "GenBuffers", "GenBuffersARB", nullptr } },
     520           0 :         { (PRFuncPtr*) &mSymbols.fGenTextures, { "GenTextures", nullptr } },
     521           0 :         { (PRFuncPtr*) &mSymbols.fCreateProgram, { "CreateProgram", "CreateProgramARB", nullptr } },
     522           0 :         { (PRFuncPtr*) &mSymbols.fCreateShader, { "CreateShader", "CreateShaderARB", nullptr } },
     523             : 
     524           0 :         { (PRFuncPtr*) &mSymbols.fDeleteBuffers, { "DeleteBuffers", "DeleteBuffersARB", nullptr } },
     525           0 :         { (PRFuncPtr*) &mSymbols.fDeleteTextures, { "DeleteTextures", "DeleteTexturesARB", nullptr } },
     526           0 :         { (PRFuncPtr*) &mSymbols.fDeleteProgram, { "DeleteProgram", "DeleteProgramARB", nullptr } },
     527           0 :         { (PRFuncPtr*) &mSymbols.fDeleteShader, { "DeleteShader", "DeleteShaderARB", nullptr } },
     528             : 
     529             :         END_SYMBOLS
     530           0 :     };
     531             : 
     532           0 :     if (!LoadGLSymbols(this, prefix, trygl, coreSymbols, "GL"))
     533           0 :         return false;
     534             : 
     535             :     ////////////////
     536             : 
     537           0 :     MakeCurrent();
     538             : 
     539           0 :     const std::string versionStr = (const char*)fGetString(LOCAL_GL_VERSION);
     540           0 :     if (versionStr.find("OpenGL ES") == 0) {
     541           0 :         mProfile = ContextProfile::OpenGLES;
     542             :     }
     543             : 
     544             :     uint32_t majorVer, minorVer;
     545           0 :     if (!ParseVersion(versionStr, &majorVer, &minorVer)) {
     546           0 :         MOZ_ASSERT(false, "Failed to parse GL_VERSION");
     547             :         return false;
     548             :     }
     549           0 :     MOZ_ASSERT(majorVer < 10);
     550           0 :     MOZ_ASSERT(minorVer < 10);
     551           0 :     mVersion = majorVer*100 + minorVer*10;
     552           0 :     if (mVersion < 200) {
     553             :         // Mac OSX 10.6/10.7 machines with Intel GPUs claim only OpenGL 1.4 but
     554             :         // have all the GL2+ extensions that we need.
     555           0 :         mVersion = 200;
     556             :     }
     557             : 
     558             :     ////
     559             : 
     560           0 :     const auto glslVersionStr = (const char*)fGetString(LOCAL_GL_SHADING_LANGUAGE_VERSION);
     561           0 :     if (!glslVersionStr) {
     562             :         // This happens on the Android emulators. We'll just return 100
     563           0 :         mShadingLanguageVersion = 100;
     564           0 :     } else if (ParseVersion(glslVersionStr, &majorVer, &minorVer)) {
     565           0 :         MOZ_ASSERT(majorVer < 10);
     566           0 :         MOZ_ASSERT(minorVer < 100);
     567           0 :         mShadingLanguageVersion = majorVer*100 + minorVer;
     568             :     } else {
     569           0 :         MOZ_ASSERT(false, "Failed to parse GL_SHADING_LANGUAGE_VERSION");
     570             :         return false;
     571             :     }
     572             : 
     573           0 :     if (ShouldSpew()) {
     574           0 :         printf_stderr("GL version detected: %u\n", mVersion);
     575           0 :         printf_stderr("GLSL version detected: %u\n", mShadingLanguageVersion);
     576           0 :         printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR));
     577           0 :         printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER));
     578             :     }
     579             : 
     580             :     ////////////////
     581             : 
     582             :     // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
     583           0 :     if (mProfile == ContextProfile::OpenGLES) {
     584             :         const SymLoadStruct symbols[] = {
     585           0 :             { (PRFuncPtr*) &mSymbols.fGetShaderPrecisionFormat, { "GetShaderPrecisionFormat", nullptr } },
     586           0 :             { (PRFuncPtr*) &mSymbols.fClearDepthf, { "ClearDepthf", nullptr } },
     587           0 :             { (PRFuncPtr*) &mSymbols.fDepthRangef, { "DepthRangef", nullptr } },
     588             :             END_SYMBOLS
     589           0 :         };
     590             : 
     591           0 :         if (!LoadGLSymbols(this, prefix, trygl, symbols, "OpenGL ES"))
     592           0 :             return false;
     593             :     } else {
     594             :         const SymLoadStruct symbols[] = {
     595           0 :             { (PRFuncPtr*) &mSymbols.fClearDepth, { "ClearDepth", nullptr } },
     596           0 :             { (PRFuncPtr*) &mSymbols.fDepthRange, { "DepthRange", nullptr } },
     597           0 :             { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } },
     598           0 :             { (PRFuncPtr*) &mSymbols.fMapBuffer, { "MapBuffer", nullptr } },
     599           0 :             { (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", nullptr } },
     600           0 :             { (PRFuncPtr*) &mSymbols.fPointParameterf, { "PointParameterf", nullptr } },
     601           0 :             { (PRFuncPtr*) &mSymbols.fDrawBuffer, { "DrawBuffer", nullptr } },
     602             :             // The following functions are only used by Skia/GL in desktop mode.
     603             :             // Other parts of Gecko should avoid using these
     604           0 :             { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
     605           0 :             { (PRFuncPtr*) &mSymbols.fClientActiveTexture, { "ClientActiveTexture", nullptr } },
     606           0 :             { (PRFuncPtr*) &mSymbols.fDisableClientState, { "DisableClientState", nullptr } },
     607           0 :             { (PRFuncPtr*) &mSymbols.fEnableClientState, { "EnableClientState", nullptr } },
     608           0 :             { (PRFuncPtr*) &mSymbols.fLoadIdentity, { "LoadIdentity", nullptr } },
     609           0 :             { (PRFuncPtr*) &mSymbols.fLoadMatrixf, { "LoadMatrixf", nullptr } },
     610           0 :             { (PRFuncPtr*) &mSymbols.fMatrixMode, { "MatrixMode", nullptr } },
     611           0 :             { (PRFuncPtr*) &mSymbols.fPolygonMode, { "PolygonMode", nullptr } },
     612           0 :             { (PRFuncPtr*) &mSymbols.fTexGeni, { "TexGeni", nullptr } },
     613           0 :             { (PRFuncPtr*) &mSymbols.fTexGenf, { "TexGenf", nullptr } },
     614           0 :             { (PRFuncPtr*) &mSymbols.fTexGenfv, { "TexGenfv", nullptr } },
     615           0 :             { (PRFuncPtr*) &mSymbols.fVertexPointer, { "VertexPointer", nullptr } },
     616             :             END_SYMBOLS
     617           0 :         };
     618             : 
     619           0 :         if (!LoadGLSymbols(this, prefix, trygl, symbols, "Desktop OpenGL"))
     620           0 :             return false;
     621             :     }
     622             : 
     623             :     ////////////////
     624             : 
     625           0 :     const char* glVendorString = (const char*)fGetString(LOCAL_GL_VENDOR);
     626           0 :     const char* glRendererString = (const char*)fGetString(LOCAL_GL_RENDERER);
     627           0 :     if (!glVendorString || !glRendererString)
     628           0 :         return false;
     629             : 
     630             :     // The order of these strings must match up with the order of the enum
     631             :     // defined in GLContext.h for vendor IDs.
     632             :     const char* vendorMatchStrings[size_t(GLVendor::Other) + 1] = {
     633             :         "Intel",
     634             :         "NVIDIA",
     635             :         "ATI",
     636             :         "Qualcomm",
     637             :         "Imagination",
     638             :         "nouveau",
     639             :         "Vivante",
     640             :         "VMware, Inc.",
     641             :         "ARM",
     642             :         "Unknown"
     643           0 :     };
     644             : 
     645           0 :     mVendor = GLVendor::Other;
     646           0 :     for (size_t i = 0; i < size_t(GLVendor::Other); ++i) {
     647           0 :         if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
     648           0 :             mVendor = GLVendor(i);
     649           0 :             break;
     650             :         }
     651             :     }
     652             : 
     653             :     // The order of these strings must match up with the order of the enum
     654             :     // defined in GLContext.h for renderer IDs.
     655             :     const char* rendererMatchStrings[size_t(GLRenderer::Other) + 1] = {
     656             :         "Adreno 200",
     657             :         "Adreno 205",
     658             :         "Adreno (TM) 200",
     659             :         "Adreno (TM) 205",
     660             :         "Adreno (TM) 305",
     661             :         "Adreno (TM) 320",
     662             :         "Adreno (TM) 330",
     663             :         "Adreno (TM) 420",
     664             :         "Mali-400 MP",
     665             :         "Mali-450 MP",
     666             :         "PowerVR SGX 530",
     667             :         "PowerVR SGX 540",
     668             :         "PowerVR SGX 544MP",
     669             :         "NVIDIA Tegra",
     670             :         "Android Emulator",
     671             :         "Gallium 0.4 on llvmpipe",
     672             :         "Intel HD Graphics 3000 OpenGL Engine",
     673             :         "Microsoft Basic Render Driver",
     674             :         "Unknown"
     675           0 :     };
     676             : 
     677           0 :     mRenderer = GLRenderer::Other;
     678           0 :     for (size_t i = 0; i < size_t(GLRenderer::Other); ++i) {
     679           0 :         if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) {
     680           0 :             mRenderer = GLRenderer(i);
     681           0 :             break;
     682             :         }
     683             :     }
     684             : 
     685           0 :     if (ShouldSpew()) {
     686           0 :         printf_stderr("GL_VENDOR: %s\n", glVendorString);
     687           0 :         printf_stderr("mVendor: %s\n", vendorMatchStrings[size_t(mVendor)]);
     688           0 :         printf_stderr("GL_RENDERER: %s\n", glRendererString);
     689           0 :         printf_stderr("mRenderer: %s\n", rendererMatchStrings[size_t(mRenderer)]);
     690             :     }
     691             : 
     692             :     ////////////////
     693             : 
     694           0 :     if (mVersion >= 300) { // Both GL3 and ES3.
     695             :         const SymLoadStruct symbols[] = {
     696           0 :             { (PRFuncPtr*) &mSymbols.fGetStringi, { "GetStringi", nullptr } },
     697             :             END_SYMBOLS
     698           0 :         };
     699             : 
     700           0 :         if (!LoadGLSymbols(this, prefix, trygl, symbols, "GetStringi")) {
     701           0 :             MOZ_RELEASE_ASSERT(false, "GFX: GetStringi is required!");
     702             :             return false;
     703             :         }
     704             :     }
     705             : 
     706           0 :     InitExtensions();
     707           0 :     if (mProfile != ContextProfile::OpenGLES) {
     708           0 :         if (mVersion >= 310 && !IsExtensionSupported(ARB_compatibility)) {
     709           0 :             mProfile = ContextProfile::OpenGLCore;
     710             :         } else {
     711           0 :             mProfile = ContextProfile::OpenGLCompatibility;
     712             :         }
     713             :     }
     714           0 :     MOZ_ASSERT(mProfile != ContextProfile::Unknown);
     715             : 
     716           0 :     if (ShouldSpew()) {
     717           0 :         const char* profileStr = "";
     718           0 :         if (mProfile == ContextProfile::OpenGLES) {
     719           0 :             profileStr = " es";
     720           0 :         } else if (mProfile == ContextProfile::OpenGLCore) {
     721           0 :             profileStr = " core";
     722             :         }
     723           0 :         printf_stderr("Detected profile: %u%s\n", mVersion, profileStr);
     724             :     }
     725             : 
     726           0 :     InitFeatures();
     727             : 
     728             :     ////
     729             : 
     730             :     // Disable extensions with partial or incorrect support.
     731           0 :     if (WorkAroundDriverBugs()) {
     732           0 :         if (Renderer() == GLRenderer::AdrenoTM320) {
     733           0 :             MarkUnsupported(GLFeature::standard_derivatives);
     734             :         }
     735             : 
     736           0 :         if (Vendor() == GLVendor::Vivante) {
     737             :             // bug 958256
     738           0 :             MarkUnsupported(GLFeature::standard_derivatives);
     739             :         }
     740             : 
     741           0 :         if (Renderer() == GLRenderer::MicrosoftBasicRenderDriver) {
     742             :             // Bug 978966: on Microsoft's "Basic Render Driver" (software renderer)
     743             :             // multisampling hardcodes blending with the default blendfunc, which breaks WebGL.
     744           0 :             MarkUnsupported(GLFeature::framebuffer_multisample);
     745             :         }
     746             : 
     747             : #ifdef XP_MACOSX
     748             :         // The Mac Nvidia driver, for versions up to and including 10.8,
     749             :         // don't seem to properly support this.  See 814839
     750             :         // this has been fixed in Mac OS X 10.9. See 907946
     751             :         // and it also works in 10.8.3 and higher.  See 1094338.
     752             :         if (Vendor() == gl::GLVendor::NVIDIA &&
     753             :             !nsCocoaFeatures::IsAtLeastVersion(10,8,3))
     754             :         {
     755             :             MarkUnsupported(GLFeature::depth_texture);
     756             :         }
     757             : #endif
     758             :     }
     759             : 
     760           0 :     if (IsExtensionSupported(GLContext::ARB_pixel_buffer_object)) {
     761           0 :         MOZ_ASSERT((mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
     762             :                    "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer"
     763             :                    " being available!");
     764             :     }
     765             : 
     766             :     ////////////////////////////////////////////////////////////////////////////
     767             : 
     768             :     const auto fnLoadForFeature = [this, prefix, trygl](const SymLoadStruct* list,
     769           0 :                                                         GLFeature feature)
     770           0 :     {
     771           0 :         return this->LoadFeatureSymbols(prefix, trygl, list, feature);
     772           0 :     };
     773             : 
     774             :     // Check for ARB_framebuffer_objects
     775           0 :     if (IsSupported(GLFeature::framebuffer_object)) {
     776             :         // https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
     777             :         const SymLoadStruct symbols[] = {
     778           0 :             CORE_SYMBOL(IsRenderbuffer),
     779           0 :             CORE_SYMBOL(BindRenderbuffer),
     780           0 :             CORE_SYMBOL(DeleteRenderbuffers),
     781           0 :             CORE_SYMBOL(GenRenderbuffers),
     782           0 :             CORE_SYMBOL(RenderbufferStorage),
     783           0 :             CORE_SYMBOL(RenderbufferStorageMultisample),
     784           0 :             CORE_SYMBOL(GetRenderbufferParameteriv),
     785           0 :             CORE_SYMBOL(IsFramebuffer),
     786           0 :             CORE_SYMBOL(BindFramebuffer),
     787           0 :             CORE_SYMBOL(DeleteFramebuffers),
     788           0 :             CORE_SYMBOL(GenFramebuffers),
     789           0 :             CORE_SYMBOL(CheckFramebufferStatus),
     790           0 :             CORE_SYMBOL(FramebufferTexture2D),
     791           0 :             CORE_SYMBOL(FramebufferTextureLayer),
     792           0 :             CORE_SYMBOL(FramebufferRenderbuffer),
     793           0 :             CORE_SYMBOL(GetFramebufferAttachmentParameteriv),
     794           0 :             CORE_SYMBOL(BlitFramebuffer),
     795           0 :             CORE_SYMBOL(GenerateMipmap),
     796             :             END_SYMBOLS
     797           0 :         };
     798           0 :         fnLoadForFeature(symbols, GLFeature::framebuffer_object);
     799             :     }
     800             : 
     801           0 :     if (!IsSupported(GLFeature::framebuffer_object)) {
     802             :         // Check for aux symbols based on extensions
     803           0 :         if (IsSupported(GLFeature::framebuffer_object_EXT_OES)) {
     804             :             const SymLoadStruct symbols[] = {
     805           0 :                 CORE_EXT_SYMBOL2(IsRenderbuffer, EXT, OES),
     806           0 :                 CORE_EXT_SYMBOL2(BindRenderbuffer, EXT, OES),
     807           0 :                 CORE_EXT_SYMBOL2(DeleteRenderbuffers, EXT, OES),
     808           0 :                 CORE_EXT_SYMBOL2(GenRenderbuffers, EXT, OES),
     809           0 :                 CORE_EXT_SYMBOL2(RenderbufferStorage, EXT, OES),
     810           0 :                 CORE_EXT_SYMBOL2(GetRenderbufferParameteriv, EXT, OES),
     811           0 :                 CORE_EXT_SYMBOL2(IsFramebuffer, EXT, OES),
     812           0 :                 CORE_EXT_SYMBOL2(BindFramebuffer, EXT, OES),
     813           0 :                 CORE_EXT_SYMBOL2(DeleteFramebuffers, EXT, OES),
     814           0 :                 CORE_EXT_SYMBOL2(GenFramebuffers, EXT, OES),
     815           0 :                 CORE_EXT_SYMBOL2(CheckFramebufferStatus, EXT, OES),
     816           0 :                 CORE_EXT_SYMBOL2(FramebufferTexture2D, EXT, OES),
     817           0 :                 CORE_EXT_SYMBOL2(FramebufferRenderbuffer, EXT, OES),
     818           0 :                 CORE_EXT_SYMBOL2(GetFramebufferAttachmentParameteriv, EXT, OES),
     819           0 :                 CORE_EXT_SYMBOL2(GenerateMipmap, EXT, OES),
     820             :                 END_SYMBOLS
     821           0 :             };
     822           0 :             fnLoadForFeature(symbols, GLFeature::framebuffer_object_EXT_OES);
     823             :         }
     824             : 
     825           0 :         if (IsSupported(GLFeature::framebuffer_blit)) {
     826             :             const SymLoadStruct symbols[] = {
     827           0 :                 EXT_SYMBOL3(BlitFramebuffer, ANGLE, EXT, NV),
     828             :                 END_SYMBOLS
     829           0 :             };
     830           0 :             fnLoadForFeature(symbols, GLFeature::framebuffer_blit);
     831             :         }
     832             : 
     833           0 :         if (IsSupported(GLFeature::framebuffer_multisample)) {
     834             :             const SymLoadStruct symbols[] = {
     835           0 :                 EXT_SYMBOL3(RenderbufferStorageMultisample, ANGLE, APPLE, EXT),
     836             :                 END_SYMBOLS
     837           0 :             };
     838           0 :             fnLoadForFeature(symbols, GLFeature::framebuffer_multisample);
     839             :         }
     840             : 
     841           0 :         if (IsExtensionSupported(GLContext::ARB_geometry_shader4) ||
     842           0 :             IsExtensionSupported(GLContext::NV_geometry_program4))
     843             :         {
     844             :             const SymLoadStruct symbols[] = {
     845           0 :                 EXT_SYMBOL2(FramebufferTextureLayer, ARB, EXT),
     846             :                 END_SYMBOLS
     847           0 :             };
     848           0 :             if (!LoadGLSymbols(this, prefix, trygl, symbols,
     849             :                                "ARB_geometry_shader4/NV_geometry_program4"))
     850             :             {
     851           0 :                 MarkExtensionUnsupported(GLContext::ARB_geometry_shader4);
     852           0 :                 MarkExtensionUnsupported(GLContext::NV_geometry_program4);
     853             :             }
     854             :         }
     855             :     }
     856             : 
     857           0 :     if (!IsSupported(GLFeature::framebuffer_object) &&
     858           0 :         !IsSupported(GLFeature::framebuffer_object_EXT_OES))
     859             :     {
     860           0 :         NS_ERROR("GLContext requires support for framebuffer objects.");
     861           0 :         return false;
     862             :     }
     863           0 :     MOZ_RELEASE_ASSERT(mSymbols.fBindFramebuffer, "GFX: mSymbols.fBindFramebuffer zero or not set.");
     864             : 
     865             :     ////////////////
     866             : 
     867           0 :     const auto err = mSymbols.fGetError();
     868           0 :     MOZ_RELEASE_ASSERT(!err);
     869           0 :     if (err)
     870           0 :         return false;
     871             : 
     872           0 :     LoadMoreSymbols(prefix, trygl);
     873             : 
     874             :     ////////////////////////////////////////////////////////////////////////////
     875             : 
     876           0 :     raw_fGetIntegerv(LOCAL_GL_VIEWPORT, mViewportRect);
     877           0 :     raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mScissorRect);
     878           0 :     raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
     879           0 :     raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
     880           0 :     raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
     881           0 :     raw_fGetIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
     882             : 
     883             : #ifdef XP_MACOSX
     884             :     if (mWorkAroundDriverBugs &&
     885             :         nsCocoaFeatures::OSXVersionMajor() == 10 &&
     886             :         nsCocoaFeatures::OSXVersionMinor() < 12)
     887             :     {
     888             :         if (mVendor == GLVendor::Intel) {
     889             :             // see bug 737182 for 2D textures, bug 684882 for cube map textures.
     890             :             mMaxTextureSize        = std::min(mMaxTextureSize,        4096);
     891             :             mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 512);
     892             :             // for good measure, we align renderbuffers on what we do for 2D textures
     893             :             mMaxRenderbufferSize   = std::min(mMaxRenderbufferSize,   4096);
     894             :             mNeedsTextureSizeChecks = true;
     895             :         } else if (mVendor == GLVendor::NVIDIA) {
     896             :             // See bug 879656.  8192 fails, 8191 works.
     897             :             mMaxTextureSize = std::min(mMaxTextureSize, 8191);
     898             :             mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 8191);
     899             : 
     900             :             // Part of the bug 879656, but it also doesn't hurt the 877949
     901             :             mNeedsTextureSizeChecks = true;
     902             :         }
     903             :     }
     904             : #endif
     905             : #ifdef MOZ_X11
     906           0 :     if (mWorkAroundDriverBugs) {
     907           0 :         if (mVendor == GLVendor::Nouveau) {
     908             :             // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau.
     909           0 :             mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 2048);
     910           0 :             mNeedsTextureSizeChecks = true;
     911           0 :         } else if (mVendor == GLVendor::Intel) {
     912             :             // Bug 1199923. Driver seems to report a larger max size than
     913             :             // actually supported.
     914           0 :             mMaxTextureSize /= 2;
     915           0 :             mMaxRenderbufferSize /= 2;
     916           0 :             mNeedsTextureSizeChecks = true;
     917             :         }
     918             :         // Bug 1367570. Explicitly set vertex attributes [1,3] to opaque
     919             :         // black because Nvidia doesn't do it for us.
     920           0 :         if (mVendor == GLVendor::NVIDIA) {
     921           0 :             for (size_t i = 1; i <= 3; ++i) {
     922           0 :                 mSymbols.fVertexAttrib4f(i, 0, 0, 0, 1);
     923             :             }
     924             :         }
     925             :     }
     926             : #endif
     927           0 :     if (mWorkAroundDriverBugs &&
     928           0 :         Renderer() == GLRenderer::AdrenoTM420) {
     929             :         // see bug 1194923. Calling glFlush before glDeleteFramebuffers
     930             :         // prevents occasional driver crash.
     931           0 :         mNeedsFlushBeforeDeleteFB = true;
     932             :     }
     933             : #ifdef MOZ_WIDGET_ANDROID
     934             :     if (mWorkAroundDriverBugs &&
     935             :         (Renderer() == GLRenderer::AdrenoTM305 ||
     936             :          Renderer() == GLRenderer::AdrenoTM320 ||
     937             :          Renderer() == GLRenderer::AdrenoTM330) &&
     938             :         AndroidBridge::Bridge()->GetAPIVersion() < 21) {
     939             :         // Bug 1164027. Driver crashes when functions such as
     940             :         // glTexImage2D fail due to virtual memory exhaustion.
     941             :         mTextureAllocCrashesOnMapFailure = true;
     942             :     }
     943             : #endif
     944             : #if MOZ_WIDGET_ANDROID
     945             :     if (mWorkAroundDriverBugs &&
     946             :         Renderer() == GLRenderer::SGX540 &&
     947             :         AndroidBridge::Bridge()->GetAPIVersion() <= 15) {
     948             :         // Bug 1288446. Driver sometimes crashes when uploading data to a
     949             :         // texture if the render target has changed since the texture was
     950             :         // rendered from. Calling glCheckFramebufferStatus after
     951             :         // glFramebufferTexture2D prevents the crash.
     952             :         mNeedsCheckAfterAttachTextureToFb = true;
     953             :     }
     954             : #endif
     955             : 
     956           0 :     mMaxTextureImageSize = mMaxTextureSize;
     957             : 
     958           0 :     if (IsSupported(GLFeature::framebuffer_multisample)) {
     959           0 :         fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples);
     960             :     }
     961             : 
     962             :     ////////////////////////////////////////////////////////////////////////////
     963             : 
     964             :     // We're ready for final setup.
     965           0 :     fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
     966             : 
     967             :     // TODO: Remove SurfaceCaps::any.
     968           0 :     if (mCaps.any) {
     969           0 :         mCaps.any = false;
     970           0 :         mCaps.color = true;
     971           0 :         mCaps.alpha = false;
     972             :     }
     973             : 
     974           0 :     MOZ_ASSERT(IsCurrent());
     975             : 
     976           0 :     if (ShouldSpew() && IsExtensionSupported(KHR_debug)) {
     977           0 :         fEnable(LOCAL_GL_DEBUG_OUTPUT);
     978           0 :         fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS);
     979           0 :         fDebugMessageCallback(&StaticDebugCallback, (void*)this);
     980             :         fDebugMessageControl(LOCAL_GL_DONT_CARE,
     981             :                              LOCAL_GL_DONT_CARE,
     982             :                              LOCAL_GL_DONT_CARE,
     983             :                              0, nullptr,
     984           0 :                              true);
     985             :     }
     986             : 
     987           0 :     return true;
     988             : }
     989             : 
     990             : void
     991           0 : GLContext::LoadMoreSymbols(const char* prefix, bool trygl)
     992             : {
     993             :     const auto fnLoadForExt = [this, prefix, trygl](const SymLoadStruct* list,
     994           0 :                                                     GLExtensions ext)
     995           0 :     {
     996           0 :         return this->LoadExtSymbols(prefix, trygl, list, ext);
     997           0 :     };
     998             : 
     999             :     const auto fnLoadForFeature = [this, prefix, trygl](const SymLoadStruct* list,
    1000           0 :                                                         GLFeature feature)
    1001           0 :     {
    1002           0 :         return this->LoadFeatureSymbols(prefix, trygl, list, feature);
    1003           0 :     };
    1004             : 
    1005             :     const auto fnLoadFeatureByCore = [this, fnLoadForFeature](const SymLoadStruct* coreList,
    1006             :                                                               const SymLoadStruct* extList,
    1007           0 :                                                               GLFeature feature)
    1008           0 :     {
    1009           0 :         const bool useCore = this->IsFeatureProvidedByCoreSymbols(feature);
    1010           0 :         const auto list = useCore ? coreList : extList;
    1011           0 :         return fnLoadForFeature(list, feature);
    1012           0 :     };
    1013             : 
    1014           0 :     if (IsSupported(GLFeature::robustness)) {
    1015           0 :         const auto resetStrategy = GetIntAs<GLuint>(LOCAL_GL_RESET_NOTIFICATION_STRATEGY);
    1016           0 :         if (resetStrategy != LOCAL_GL_LOSE_CONTEXT_ON_RESET) {
    1017           0 :             NS_WARNING("Robustness supported, strategy is not LOSE_CONTEXT_ON_RESET!");
    1018           0 :             if (ShouldSpew()) {
    1019           0 :                 const bool isDisabled = (resetStrategy == LOCAL_GL_NO_RESET_NOTIFICATION);
    1020           0 :                 printf_stderr("Strategy: %s (0x%04x)",
    1021             :                               (isDisabled ? "disabled" : "unrecognized"),
    1022           0 :                               resetStrategy);
    1023             :             }
    1024           0 :             MarkUnsupported(GLFeature::robustness);
    1025             :         }
    1026             :     }
    1027           0 :     if (IsSupported(GLFeature::robustness)) {
    1028             :         const SymLoadStruct symbols[] = {
    1029           0 :             { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatus",
    1030             :                                                                 "GetGraphicsResetStatusARB",
    1031             :                                                                 "GetGraphicsResetStatusKHR",
    1032             :                                                                 "GetGraphicsResetStatusEXT",
    1033             :                                                                 nullptr } },
    1034             :             END_SYMBOLS
    1035           0 :         };
    1036           0 :         if (fnLoadForFeature(symbols, GLFeature::robustness)) {
    1037           0 :             const auto status = mSymbols.fGetGraphicsResetStatus();
    1038           0 :             MOZ_ALWAYS_TRUE(!status);
    1039             : 
    1040           0 :             const auto err = mSymbols.fGetError();
    1041           0 :             MOZ_ALWAYS_TRUE(!err);
    1042             :         }
    1043             :     }
    1044             : 
    1045           0 :     if (IsSupported(GLFeature::sync)) {
    1046             :         const SymLoadStruct symbols[] = {
    1047           0 :             { (PRFuncPtr*) &mSymbols.fFenceSync,      { "FenceSync",      nullptr } },
    1048           0 :             { (PRFuncPtr*) &mSymbols.fIsSync,         { "IsSync",         nullptr } },
    1049           0 :             { (PRFuncPtr*) &mSymbols.fDeleteSync,     { "DeleteSync",     nullptr } },
    1050           0 :             { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "ClientWaitSync", nullptr } },
    1051           0 :             { (PRFuncPtr*) &mSymbols.fWaitSync,       { "WaitSync",       nullptr } },
    1052           0 :             { (PRFuncPtr*) &mSymbols.fGetInteger64v,  { "GetInteger64v",  nullptr } },
    1053           0 :             { (PRFuncPtr*) &mSymbols.fGetSynciv,      { "GetSynciv",      nullptr } },
    1054             :             END_SYMBOLS
    1055           0 :         };
    1056           0 :         fnLoadForFeature(symbols, GLFeature::sync);
    1057             :     }
    1058             : 
    1059           0 :     if (IsExtensionSupported(OES_EGL_image)) {
    1060             :         const SymLoadStruct symbols[] = {
    1061           0 :             { (PRFuncPtr*) &mSymbols.fEGLImageTargetTexture2D, { "EGLImageTargetTexture2DOES", nullptr } },
    1062           0 :             { (PRFuncPtr*) &mSymbols.fEGLImageTargetRenderbufferStorage, { "EGLImageTargetRenderbufferStorageOES", nullptr } },
    1063             :             END_SYMBOLS
    1064           0 :         };
    1065           0 :         fnLoadForExt(symbols, OES_EGL_image);
    1066             :     }
    1067             : 
    1068           0 :     if (IsExtensionSupported(APPLE_texture_range)) {
    1069             :         const SymLoadStruct symbols[] = {
    1070           0 :             { (PRFuncPtr*) &mSymbols.fTextureRangeAPPLE, { "TextureRangeAPPLE", nullptr } },
    1071             :             END_SYMBOLS
    1072           0 :         };
    1073           0 :         fnLoadForExt(symbols, APPLE_texture_range);
    1074             :     }
    1075             : 
    1076           0 :     if (IsSupported(GLFeature::vertex_array_object)) {
    1077             :         const SymLoadStruct coreSymbols[] = {
    1078           0 :             { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", nullptr } },
    1079           0 :             { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", nullptr } },
    1080           0 :             { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", nullptr } },
    1081           0 :             { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", nullptr } },
    1082             :             END_SYMBOLS
    1083           0 :         };
    1084             :         const SymLoadStruct extSymbols[] = {
    1085           0 :             { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArrayARB", "IsVertexArrayOES", "IsVertexArrayAPPLE", nullptr } },
    1086           0 :             { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArraysARB", "GenVertexArraysOES", "GenVertexArraysAPPLE", nullptr } },
    1087           0 :             { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrayARB", "BindVertexArrayOES", "BindVertexArrayAPPLE", nullptr } },
    1088           0 :             { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArraysARB", "DeleteVertexArraysOES", "DeleteVertexArraysAPPLE", nullptr } },
    1089             :             END_SYMBOLS
    1090           0 :         };
    1091           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::vertex_array_object);
    1092             :     }
    1093             : 
    1094           0 :     if (IsSupported(GLFeature::draw_instanced)) {
    1095             :         const SymLoadStruct coreSymbols[] = {
    1096           0 :             { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, { "DrawArraysInstanced", nullptr } },
    1097           0 :             { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, { "DrawElementsInstanced", nullptr } },
    1098             :             END_SYMBOLS
    1099           0 :         };
    1100             :         const SymLoadStruct extSymbols[] = {
    1101           0 :             { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, { "DrawArraysInstancedARB", "DrawArraysInstancedEXT", "DrawArraysInstancedNV", "DrawArraysInstancedANGLE", nullptr } },
    1102           0 :             { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, { "DrawElementsInstancedARB", "DrawElementsInstancedEXT", "DrawElementsInstancedNV", "DrawElementsInstancedANGLE", nullptr }
    1103             :             },
    1104             :             END_SYMBOLS
    1105           0 :         };
    1106           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_instanced);
    1107             :     }
    1108             : 
    1109           0 :     if (IsSupported(GLFeature::instanced_arrays)) {
    1110             :         const SymLoadStruct coreSymbols[] = {
    1111           0 :             { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, { "VertexAttribDivisor", nullptr } },
    1112             :             END_SYMBOLS
    1113           0 :         };
    1114             :         const SymLoadStruct extSymbols[] = {
    1115           0 :             { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, { "VertexAttribDivisorARB", "VertexAttribDivisorNV", "VertexAttribDivisorANGLE", nullptr } },
    1116             :             END_SYMBOLS
    1117           0 :         };
    1118           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::instanced_arrays);
    1119             :     }
    1120             : 
    1121           0 :     if (IsSupported(GLFeature::texture_storage)) {
    1122             :         const SymLoadStruct coreSymbols[] = {
    1123           0 :             { (PRFuncPtr*) &mSymbols.fTexStorage2D, { "TexStorage2D", nullptr } },
    1124           0 :             { (PRFuncPtr*) &mSymbols.fTexStorage3D, { "TexStorage3D", nullptr } },
    1125             :             END_SYMBOLS
    1126           0 :         };
    1127             :         const SymLoadStruct extSymbols[] = {
    1128           0 :             { (PRFuncPtr*) &mSymbols.fTexStorage2D, { "TexStorage2DEXT", nullptr } },
    1129           0 :             { (PRFuncPtr*) &mSymbols.fTexStorage3D, { "TexStorage3DEXT", nullptr } },
    1130             :             END_SYMBOLS
    1131           0 :         };
    1132           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_storage);
    1133             :     }
    1134             : 
    1135           0 :     if (IsSupported(GLFeature::sampler_objects)) {
    1136             :         const SymLoadStruct symbols[] = {
    1137           0 :             { (PRFuncPtr*) &mSymbols.fGenSamplers, { "GenSamplers", nullptr } },
    1138           0 :             { (PRFuncPtr*) &mSymbols.fDeleteSamplers, { "DeleteSamplers", nullptr } },
    1139           0 :             { (PRFuncPtr*) &mSymbols.fIsSampler, { "IsSampler", nullptr } },
    1140           0 :             { (PRFuncPtr*) &mSymbols.fBindSampler, { "BindSampler", nullptr } },
    1141           0 :             { (PRFuncPtr*) &mSymbols.fSamplerParameteri, { "SamplerParameteri", nullptr } },
    1142           0 :             { (PRFuncPtr*) &mSymbols.fSamplerParameteriv, { "SamplerParameteriv", nullptr } },
    1143           0 :             { (PRFuncPtr*) &mSymbols.fSamplerParameterf, { "SamplerParameterf", nullptr } },
    1144           0 :             { (PRFuncPtr*) &mSymbols.fSamplerParameterfv, { "SamplerParameterfv", nullptr } },
    1145           0 :             { (PRFuncPtr*) &mSymbols.fGetSamplerParameteriv, { "GetSamplerParameteriv", nullptr } },
    1146           0 :             { (PRFuncPtr*) &mSymbols.fGetSamplerParameterfv, { "GetSamplerParameterfv", nullptr } },
    1147             :             END_SYMBOLS
    1148           0 :         };
    1149           0 :         fnLoadForFeature(symbols, GLFeature::sampler_objects);
    1150             :     }
    1151             : 
    1152             :     // ARB_transform_feedback2/NV_transform_feedback2 is a
    1153             :     // superset of EXT_transform_feedback/NV_transform_feedback
    1154             :     // and adds glPauseTransformFeedback &
    1155             :     // glResumeTransformFeedback, which are required for WebGL2.
    1156           0 :     if (IsSupported(GLFeature::transform_feedback2)) {
    1157             :         const SymLoadStruct coreSymbols[] = {
    1158           0 :             { (PRFuncPtr*) &mSymbols.fBindBufferBase, { "BindBufferBase", nullptr } },
    1159           0 :             { (PRFuncPtr*) &mSymbols.fBindBufferRange, { "BindBufferRange", nullptr } },
    1160           0 :             { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, { "GenTransformFeedbacks", nullptr } },
    1161           0 :             { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, { "BindTransformFeedback", nullptr } },
    1162           0 :             { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, { "DeleteTransformFeedbacks", nullptr } },
    1163           0 :             { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, { "IsTransformFeedback", nullptr } },
    1164           0 :             { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, { "BeginTransformFeedback", nullptr } },
    1165           0 :             { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, { "EndTransformFeedback", nullptr } },
    1166           0 :             { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, { "TransformFeedbackVaryings", nullptr } },
    1167           0 :             { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, { "GetTransformFeedbackVarying", nullptr } },
    1168           0 :             { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, { "PauseTransformFeedback", nullptr } },
    1169           0 :             { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, { "ResumeTransformFeedback", nullptr } },
    1170             :             END_SYMBOLS
    1171           0 :         };
    1172             :         const SymLoadStruct extSymbols[] = {
    1173           0 :             { (PRFuncPtr*) &mSymbols.fBindBufferBase, { "BindBufferBaseEXT", "BindBufferBaseNV", nullptr } },
    1174           0 :             { (PRFuncPtr*) &mSymbols.fBindBufferRange, { "BindBufferRangeEXT", "BindBufferRangeNV", nullptr } },
    1175           0 :             { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, { "GenTransformFeedbacksNV", nullptr } },
    1176           0 :             { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, { "BindTransformFeedbackNV", nullptr } },
    1177           0 :             { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, { "DeleteTransformFeedbacksNV", nullptr } },
    1178           0 :             { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, { "IsTransformFeedbackNV", nullptr } },
    1179           0 :             { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, { "BeginTransformFeedbackEXT", "BeginTransformFeedbackNV", nullptr } },
    1180           0 :             { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, { "EndTransformFeedbackEXT", "EndTransformFeedbackNV", nullptr } },
    1181           0 :             { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, { "TransformFeedbackVaryingsEXT", "TransformFeedbackVaryingsNV", nullptr } },
    1182           0 :             { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, { "GetTransformFeedbackVaryingEXT", "GetTransformFeedbackVaryingNV", nullptr } },
    1183           0 :             { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, { "PauseTransformFeedbackNV", nullptr } },
    1184           0 :             { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, { "ResumeTransformFeedbackNV", nullptr } },
    1185             :             END_SYMBOLS
    1186           0 :         };
    1187           0 :         if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_storage)) {
    1188             :             // Also mark bind_buffer_offset as unsupported.
    1189           0 :             MarkUnsupported(GLFeature::bind_buffer_offset);
    1190             :         }
    1191             :     }
    1192             : 
    1193           0 :     if (IsSupported(GLFeature::bind_buffer_offset)) {
    1194             :         const SymLoadStruct coreSymbols[] = {
    1195           0 :             { (PRFuncPtr*) &mSymbols.fBindBufferOffset, { "BindBufferOffset", nullptr } },
    1196             :             END_SYMBOLS
    1197           0 :         };
    1198             :         const SymLoadStruct extSymbols[] = {
    1199           0 :             { (PRFuncPtr*) &mSymbols.fBindBufferOffset,
    1200             :               { "BindBufferOffsetEXT", "BindBufferOffsetNV", nullptr }
    1201             :             },
    1202             :             END_SYMBOLS
    1203           0 :         };
    1204           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::bind_buffer_offset);
    1205             :     }
    1206             : 
    1207           0 :     if (IsSupported(GLFeature::query_counter)) {
    1208             :         const SymLoadStruct coreSymbols[] = {
    1209           0 :             { (PRFuncPtr*) &mSymbols.fQueryCounter, { "QueryCounter", nullptr } },
    1210             :             END_SYMBOLS
    1211           0 :         };
    1212             :         const SymLoadStruct extSymbols[] = {
    1213           0 :             { (PRFuncPtr*) &mSymbols.fQueryCounter, { "QueryCounterEXT", "QueryCounterANGLE", nullptr } },
    1214             :             END_SYMBOLS
    1215           0 :         };
    1216           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_counter);
    1217             :     }
    1218             : 
    1219           0 :     if (IsSupported(GLFeature::query_objects)) {
    1220             :         const SymLoadStruct coreSymbols[] = {
    1221           0 :             { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQuery", nullptr } },
    1222           0 :             { (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueries", nullptr } },
    1223           0 :             { (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueries", nullptr } },
    1224           0 :             { (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQuery", nullptr } },
    1225           0 :             { (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryiv", nullptr } },
    1226           0 :             { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuiv", nullptr } },
    1227           0 :             { (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQuery", nullptr } },
    1228             :             END_SYMBOLS
    1229           0 :         };
    1230             :         const SymLoadStruct extSymbols[] = {
    1231           0 :             { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQueryEXT", "BeginQueryANGLE", nullptr } },
    1232           0 :             { (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueriesEXT", "GenQueriesANGLE", nullptr } },
    1233           0 :             { (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueriesEXT", "DeleteQueriesANGLE", nullptr } },
    1234           0 :             { (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQueryEXT", "EndQueryANGLE", nullptr } },
    1235           0 :             { (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryivEXT", "GetQueryivANGLE", nullptr } },
    1236           0 :             { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuivEXT", "GetQueryObjectuivANGLE", nullptr } },
    1237           0 :             { (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQueryEXT", "IsQueryANGLE", nullptr } },
    1238             :             END_SYMBOLS
    1239           0 :         };
    1240           0 :         if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_objects)) {
    1241           0 :             MarkUnsupported(GLFeature::get_query_object_i64v);
    1242           0 :             MarkUnsupported(GLFeature::get_query_object_iv);
    1243           0 :             MarkUnsupported(GLFeature::occlusion_query);
    1244           0 :             MarkUnsupported(GLFeature::occlusion_query_boolean);
    1245           0 :             MarkUnsupported(GLFeature::occlusion_query2);
    1246             :         }
    1247             :     }
    1248             : 
    1249           0 :     if (IsSupported(GLFeature::get_query_object_i64v)) {
    1250             :         const SymLoadStruct coreSymbols[] = {
    1251           0 :             { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, { "GetQueryObjecti64v", nullptr } },
    1252           0 :             { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, { "GetQueryObjectui64v", nullptr } },
    1253             :             END_SYMBOLS
    1254           0 :         };
    1255             :         const SymLoadStruct extSymbols[] = {
    1256           0 :             { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, { "GetQueryObjecti64vEXT", "GetQueryObjecti64vANGLE", nullptr } },
    1257           0 :             { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, { "GetQueryObjectui64vEXT", "GetQueryObjectui64vANGLE", nullptr } },
    1258             :             END_SYMBOLS
    1259           0 :         };
    1260           0 :         if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_i64v)) {
    1261           0 :             MarkUnsupported(GLFeature::query_counter);
    1262             :         }
    1263             :     }
    1264             : 
    1265           0 :     if (IsSupported(GLFeature::get_query_object_iv)) {
    1266             :         const SymLoadStruct coreSymbols[] = {
    1267           0 :             { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectiv", nullptr } },
    1268             :             END_SYMBOLS
    1269           0 :         };
    1270             :         const SymLoadStruct extSymbols[] = {
    1271           0 :             { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectivEXT", "GetQueryObjectivANGLE", nullptr } },
    1272             :             END_SYMBOLS
    1273           0 :         };
    1274           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_iv);
    1275             :     }
    1276             : 
    1277           0 :     if (IsSupported(GLFeature::clear_buffers)) {
    1278             :         const SymLoadStruct symbols[] = {
    1279           0 :             { (PRFuncPtr*) &mSymbols.fClearBufferfi,  { "ClearBufferfi",  nullptr } },
    1280           0 :             { (PRFuncPtr*) &mSymbols.fClearBufferfv,  { "ClearBufferfv",  nullptr } },
    1281           0 :             { (PRFuncPtr*) &mSymbols.fClearBufferiv,  { "ClearBufferiv",  nullptr } },
    1282           0 :             { (PRFuncPtr*) &mSymbols.fClearBufferuiv, { "ClearBufferuiv", nullptr } },
    1283             :             END_SYMBOLS
    1284           0 :         };
    1285           0 :         fnLoadForFeature(symbols, GLFeature::clear_buffers);
    1286             :     }
    1287             : 
    1288           0 :     if (IsSupported(GLFeature::copy_buffer)) {
    1289             :         const SymLoadStruct symbols[] = {
    1290           0 :             { (PRFuncPtr*) &mSymbols.fCopyBufferSubData, { "CopyBufferSubData", nullptr } },
    1291             :             END_SYMBOLS
    1292           0 :         };
    1293           0 :         fnLoadForFeature(symbols, GLFeature::copy_buffer);
    1294             :     }
    1295             : 
    1296           0 :     if (IsSupported(GLFeature::draw_buffers)) {
    1297             :         const SymLoadStruct coreSymbols[] = {
    1298           0 :             { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
    1299             :             END_SYMBOLS
    1300           0 :         };
    1301             :         const SymLoadStruct extSymbols[] = {
    1302           0 :             { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffersARB", "DrawBuffersEXT", nullptr } },
    1303             :             END_SYMBOLS
    1304           0 :         };
    1305           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers);
    1306             :     }
    1307             : 
    1308           0 :     if (IsSupported(GLFeature::draw_range_elements)) {
    1309             :         const SymLoadStruct coreSymbols[] = {
    1310           0 :             { (PRFuncPtr*) &mSymbols.fDrawRangeElements, { "DrawRangeElements", nullptr } },
    1311             :             END_SYMBOLS
    1312           0 :         };
    1313             :         const SymLoadStruct extSymbols[] = {
    1314           0 :             { (PRFuncPtr*) &mSymbols.fDrawRangeElements, { "DrawRangeElementsEXT", nullptr } },
    1315             :             END_SYMBOLS
    1316           0 :         };
    1317           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_range_elements);
    1318             :     }
    1319             : 
    1320           0 :     if (IsSupported(GLFeature::get_integer_indexed)) {
    1321             :         const SymLoadStruct coreSymbols[] = {
    1322           0 :             { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, { "GetIntegeri_v", nullptr } },
    1323             :             END_SYMBOLS
    1324           0 :         };
    1325             :         const SymLoadStruct extSymbols[] ={
    1326           0 :             { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, { "GetIntegerIndexedvEXT", nullptr } },
    1327             :             END_SYMBOLS
    1328           0 :         };
    1329           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_integer_indexed);
    1330             :     }
    1331             : 
    1332           0 :     if (IsSupported(GLFeature::get_integer64_indexed)) {
    1333             :         const SymLoadStruct symbols[] = {
    1334           0 :             { (PRFuncPtr*) &mSymbols.fGetInteger64i_v, { "GetInteger64i_v", nullptr } },
    1335             :             END_SYMBOLS
    1336           0 :         };
    1337           0 :         fnLoadForFeature(symbols, GLFeature::get_integer64_indexed);
    1338             :     }
    1339             : 
    1340           0 :     if (IsSupported(GLFeature::gpu_shader4)) {
    1341             :         const SymLoadStruct symbols[] = {
    1342           0 :             { (PRFuncPtr*) &mSymbols.fGetVertexAttribIiv, { "GetVertexAttribIiv", "GetVertexAttribIivEXT", nullptr } },
    1343           0 :             { (PRFuncPtr*) &mSymbols.fGetVertexAttribIuiv, { "GetVertexAttribIuiv", "GetVertexAttribIuivEXT", nullptr } },
    1344           0 :             { (PRFuncPtr*) &mSymbols.fVertexAttribI4i, { "VertexAttribI4i", "VertexAttribI4iEXT", nullptr } },
    1345           0 :             { (PRFuncPtr*) &mSymbols.fVertexAttribI4iv, { "VertexAttribI4iv","VertexAttribI4ivEXT", nullptr } },
    1346           0 :             { (PRFuncPtr*) &mSymbols.fVertexAttribI4ui, { "VertexAttribI4ui", "VertexAttribI4uiEXT", nullptr } },
    1347           0 :             { (PRFuncPtr*) &mSymbols.fVertexAttribI4uiv, { "VertexAttribI4uiv", "VertexAttribI4uivEXT", nullptr } },
    1348           0 :             { (PRFuncPtr*) &mSymbols.fVertexAttribIPointer, { "VertexAttribIPointer", "VertexAttribIPointerEXT", nullptr } },
    1349           0 :             { (PRFuncPtr*) &mSymbols.fUniform1ui,  { "Uniform1ui", "Uniform1uiEXT", nullptr } },
    1350           0 :             { (PRFuncPtr*) &mSymbols.fUniform2ui,  { "Uniform2ui", "Uniform2uiEXT", nullptr } },
    1351           0 :             { (PRFuncPtr*) &mSymbols.fUniform3ui,  { "Uniform3ui", "Uniform3uiEXT", nullptr } },
    1352           0 :             { (PRFuncPtr*) &mSymbols.fUniform4ui,  { "Uniform4ui", "Uniform4uiEXT", nullptr } },
    1353           0 :             { (PRFuncPtr*) &mSymbols.fUniform1uiv, { "Uniform1uiv", "Uniform1uivEXT", nullptr } },
    1354           0 :             { (PRFuncPtr*) &mSymbols.fUniform2uiv, { "Uniform2uiv", "Uniform2uivEXT", nullptr } },
    1355           0 :             { (PRFuncPtr*) &mSymbols.fUniform3uiv, { "Uniform3uiv", "Uniform3uivEXT", nullptr } },
    1356           0 :             { (PRFuncPtr*) &mSymbols.fUniform4uiv, { "Uniform4uiv", "Uniform4uivEXT", nullptr } },
    1357           0 :             { (PRFuncPtr*) &mSymbols.fGetFragDataLocation, { "GetFragDataLocation", "GetFragDataLocationEXT", nullptr } },
    1358           0 :             { (PRFuncPtr*) &mSymbols.fGetUniformuiv, { "GetUniformuiv", "GetUniformuivEXT", nullptr } },
    1359             :             END_SYMBOLS
    1360           0 :         };
    1361           0 :         fnLoadForFeature(symbols, GLFeature::gpu_shader4);
    1362             :     }
    1363             : 
    1364           0 :     if (IsSupported(GLFeature::map_buffer_range)) {
    1365             :         const SymLoadStruct symbols[] = {
    1366           0 :             { (PRFuncPtr*) &mSymbols.fMapBufferRange, { "MapBufferRange", nullptr } },
    1367           0 :             { (PRFuncPtr*) &mSymbols.fFlushMappedBufferRange, { "FlushMappedBufferRange", nullptr } },
    1368           0 :             { (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", nullptr } },
    1369             :             END_SYMBOLS
    1370           0 :         };
    1371           0 :         fnLoadForFeature(symbols, GLFeature::map_buffer_range);
    1372             :     }
    1373             : 
    1374           0 :     if (IsSupported(GLFeature::texture_3D)) {
    1375             :         const SymLoadStruct coreSymbols[] = {
    1376           0 :             { (PRFuncPtr*) &mSymbols.fTexImage3D, { "TexImage3D", nullptr } },
    1377           0 :             { (PRFuncPtr*) &mSymbols.fTexSubImage3D, { "TexSubImage3D", nullptr } },
    1378             :             END_SYMBOLS
    1379           0 :         };
    1380             :         const SymLoadStruct extSymbols[] = {
    1381           0 :             { (PRFuncPtr*) &mSymbols.fTexSubImage3D, { "TexSubImage3DEXT", "TexSubImage3DOES", nullptr } },
    1382             :             END_SYMBOLS
    1383           0 :         };
    1384           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D);
    1385             :     }
    1386             : 
    1387           0 :     if (IsSupported(GLFeature::texture_3D_compressed)) {
    1388             :         const SymLoadStruct coreSymbols[] = {
    1389           0 :             { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, { "CompressedTexImage3D", nullptr } },
    1390           0 :             { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, { "CompressedTexSubImage3D", nullptr } },
    1391             :             END_SYMBOLS
    1392           0 :         };
    1393             :         const SymLoadStruct extSymbols[] = {
    1394           0 :             { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, { "CompressedTexImage3DARB", "CompressedTexImage3DOES", nullptr } },
    1395           0 :             { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, { "CompressedTexSubImage3DARB", "CompressedTexSubImage3DOES", nullptr } },
    1396             :             END_SYMBOLS
    1397           0 :         };
    1398           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_compressed);
    1399             :     }
    1400             : 
    1401           0 :     if (IsSupported(GLFeature::texture_3D_copy)) {
    1402             :         const SymLoadStruct coreSymbols[] = {
    1403           0 :             { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, { "CopyTexSubImage3D", nullptr } },
    1404             :             END_SYMBOLS
    1405           0 :         };
    1406             :         const SymLoadStruct extSymbols[] = {
    1407           0 :             { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, { "CopyTexSubImage3DEXT", "CopyTexSubImage3DOES", nullptr } },
    1408             :             END_SYMBOLS
    1409           0 :         };
    1410           0 :         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_copy);
    1411             :     }
    1412             : 
    1413           0 :     if (IsSupported(GLFeature::uniform_buffer_object)) {
    1414             :         // Note: Don't query for glGetActiveUniformName because it is not
    1415             :         // supported by GL ES 3.
    1416             :         const SymLoadStruct symbols[] = {
    1417           0 :             { (PRFuncPtr*) &mSymbols.fGetUniformIndices, { "GetUniformIndices", nullptr } },
    1418           0 :             { (PRFuncPtr*) &mSymbols.fGetActiveUniformsiv, { "GetActiveUniformsiv", nullptr } },
    1419           0 :             { (PRFuncPtr*) &mSymbols.fGetUniformBlockIndex, { "GetUniformBlockIndex", nullptr } },
    1420           0 :             { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockiv, { "GetActiveUniformBlockiv", nullptr } },
    1421           0 :             { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockName, { "GetActiveUniformBlockName", nullptr } },
    1422           0 :             { (PRFuncPtr*) &mSymbols.fUniformBlockBinding, { "UniformBlockBinding", nullptr } },
    1423             :             END_SYMBOLS
    1424           0 :         };
    1425           0 :         fnLoadForFeature(symbols, GLFeature::uniform_buffer_object);
    1426             :     }
    1427             : 
    1428           0 :     if (IsSupported(GLFeature::uniform_matrix_nonsquare)) {
    1429             :         const SymLoadStruct symbols[] = {
    1430           0 :             { (PRFuncPtr*) &mSymbols.fUniformMatrix2x3fv, { "UniformMatrix2x3fv", nullptr } },
    1431           0 :             { (PRFuncPtr*) &mSymbols.fUniformMatrix2x4fv, { "UniformMatrix2x4fv", nullptr } },
    1432           0 :             { (PRFuncPtr*) &mSymbols.fUniformMatrix3x2fv, { "UniformMatrix3x2fv", nullptr } },
    1433           0 :             { (PRFuncPtr*) &mSymbols.fUniformMatrix3x4fv, { "UniformMatrix3x4fv", nullptr } },
    1434           0 :             { (PRFuncPtr*) &mSymbols.fUniformMatrix4x2fv, { "UniformMatrix4x2fv", nullptr } },
    1435           0 :             { (PRFuncPtr*) &mSymbols.fUniformMatrix4x3fv, { "UniformMatrix4x3fv", nullptr } },
    1436             :             END_SYMBOLS
    1437           0 :         };
    1438           0 :         fnLoadForFeature(symbols, GLFeature::uniform_matrix_nonsquare);
    1439             :     }
    1440             : 
    1441           0 :     if (IsSupported(GLFeature::internalformat_query)) {
    1442             :         const SymLoadStruct symbols[] = {
    1443           0 :             CORE_SYMBOL(GetInternalformativ),
    1444             :             END_SYMBOLS
    1445           0 :         };
    1446           0 :         fnLoadForFeature(symbols, GLFeature::internalformat_query);
    1447             :     }
    1448             : 
    1449           0 :     if (IsSupported(GLFeature::invalidate_framebuffer)) {
    1450             :         const SymLoadStruct symbols[] = {
    1451           0 :             { (PRFuncPtr*) &mSymbols.fInvalidateFramebuffer,    { "InvalidateFramebuffer", nullptr } },
    1452           0 :             { (PRFuncPtr*) &mSymbols.fInvalidateSubFramebuffer, { "InvalidateSubFramebuffer", nullptr } },
    1453             :             END_SYMBOLS
    1454           0 :         };
    1455           0 :         fnLoadForFeature(symbols, GLFeature::invalidate_framebuffer);
    1456             :     }
    1457             : 
    1458           0 :     if (IsSupported(GLFeature::prim_restart)) {
    1459             :         const SymLoadStruct symbols[] = {
    1460           0 :             { (PRFuncPtr*) &mSymbols.fPrimitiveRestartIndex,    { "PrimitiveRestartIndex", "PrimitiveRestartIndexNV", nullptr } },
    1461             :             END_SYMBOLS
    1462           0 :         };
    1463           0 :         fnLoadForFeature(symbols, GLFeature::prim_restart);
    1464             :     }
    1465             : 
    1466           0 :     if (IsExtensionSupported(KHR_debug)) {
    1467             :         const SymLoadStruct symbols[] = {
    1468           0 :             { (PRFuncPtr*) &mSymbols.fDebugMessageControl,  { "DebugMessageControl",  "DebugMessageControlKHR",  nullptr } },
    1469           0 :             { (PRFuncPtr*) &mSymbols.fDebugMessageInsert,   { "DebugMessageInsert",   "DebugMessageInsertKHR",   nullptr } },
    1470           0 :             { (PRFuncPtr*) &mSymbols.fDebugMessageCallback, { "DebugMessageCallback", "DebugMessageCallbackKHR", nullptr } },
    1471           0 :             { (PRFuncPtr*) &mSymbols.fGetDebugMessageLog,   { "GetDebugMessageLog",   "GetDebugMessageLogKHR",   nullptr } },
    1472           0 :             { (PRFuncPtr*) &mSymbols.fGetPointerv,          { "GetPointerv",          "GetPointervKHR",          nullptr } },
    1473           0 :             { (PRFuncPtr*) &mSymbols.fPushDebugGroup,       { "PushDebugGroup",       "PushDebugGroupKHR",       nullptr } },
    1474           0 :             { (PRFuncPtr*) &mSymbols.fPopDebugGroup,        { "PopDebugGroup",        "PopDebugGroupKHR",        nullptr } },
    1475           0 :             { (PRFuncPtr*) &mSymbols.fObjectLabel,          { "ObjectLabel",          "ObjectLabelKHR",          nullptr } },
    1476           0 :             { (PRFuncPtr*) &mSymbols.fGetObjectLabel,       { "GetObjectLabel",       "GetObjectLabelKHR",       nullptr } },
    1477           0 :             { (PRFuncPtr*) &mSymbols.fObjectPtrLabel,       { "ObjectPtrLabel",       "ObjectPtrLabelKHR",       nullptr } },
    1478           0 :             { (PRFuncPtr*) &mSymbols.fGetObjectPtrLabel,    { "GetObjectPtrLabel",    "GetObjectPtrLabelKHR",    nullptr } },
    1479             :             END_SYMBOLS
    1480           0 :         };
    1481           0 :         fnLoadForExt(symbols, KHR_debug);
    1482             :     }
    1483             : 
    1484           0 :     if (IsExtensionSupported(NV_fence)) {
    1485             :         const SymLoadStruct symbols[] = {
    1486           0 :             { (PRFuncPtr*) &mSymbols.fGenFences,    { "GenFencesNV",    nullptr } },
    1487           0 :             { (PRFuncPtr*) &mSymbols.fDeleteFences, { "DeleteFencesNV", nullptr } },
    1488           0 :             { (PRFuncPtr*) &mSymbols.fSetFence,     { "SetFenceNV",     nullptr } },
    1489           0 :             { (PRFuncPtr*) &mSymbols.fTestFence,    { "TestFenceNV",    nullptr } },
    1490           0 :             { (PRFuncPtr*) &mSymbols.fFinishFence,  { "FinishFenceNV",  nullptr } },
    1491           0 :             { (PRFuncPtr*) &mSymbols.fIsFence,      { "IsFenceNV",      nullptr } },
    1492           0 :             { (PRFuncPtr*) &mSymbols.fGetFenceiv,   { "GetFenceivNV",   nullptr } },
    1493             :             END_SYMBOLS
    1494           0 :         };
    1495           0 :         fnLoadForExt(symbols, NV_fence);
    1496             :     }
    1497             : 
    1498           0 :     if (IsExtensionSupported(NV_texture_barrier)) {
    1499             :         const SymLoadStruct symbols[] = {
    1500           0 :             { (PRFuncPtr*) &mSymbols.fTextureBarrier, { "TextureBarrierNV", nullptr } },
    1501             :             END_SYMBOLS
    1502           0 :         };
    1503           0 :         fnLoadForExt(symbols, NV_texture_barrier);
    1504             :     }
    1505             : 
    1506           0 :     if (IsSupported(GLFeature::read_buffer)) {
    1507             :         const SymLoadStruct symbols[] = {
    1508           0 :             { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } },
    1509             :             END_SYMBOLS
    1510           0 :         };
    1511           0 :         fnLoadForFeature(symbols, GLFeature::read_buffer);
    1512             :     }
    1513             : 
    1514           0 :     if (IsExtensionSupported(APPLE_framebuffer_multisample)) {
    1515             :         const SymLoadStruct symbols[] = {
    1516           0 :             { (PRFuncPtr*) &mSymbols.fResolveMultisampleFramebufferAPPLE, { "ResolveMultisampleFramebufferAPPLE", nullptr } },
    1517             :             END_SYMBOLS
    1518           0 :         };
    1519           0 :         fnLoadForExt(symbols, APPLE_framebuffer_multisample);
    1520             :     }
    1521             : 
    1522             :     // Load developer symbols, don't fail if we can't find them.
    1523             :     const SymLoadStruct devSymbols[] = {
    1524           0 :             { (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", nullptr } },
    1525           0 :             { (PRFuncPtr*) &mSymbols.fGetTexLevelParameteriv, { "GetTexLevelParameteriv", nullptr } },
    1526             :             END_SYMBOLS
    1527           0 :     };
    1528           0 :     const bool warnOnFailures = ShouldSpew();
    1529           0 :     LoadSymbols(devSymbols, trygl, prefix, warnOnFailures);
    1530           0 : }
    1531             : 
    1532             : #undef CORE_SYMBOL
    1533             : #undef CORE_EXT_SYMBOL2
    1534             : #undef EXT_SYMBOL2
    1535             : #undef EXT_SYMBOL3
    1536             : #undef END_SYMBOLS
    1537             : 
    1538             : void
    1539           0 : GLContext::DebugCallback(GLenum source,
    1540             :                          GLenum type,
    1541             :                          GLuint id,
    1542             :                          GLenum severity,
    1543             :                          GLsizei length,
    1544             :                          const GLchar* message)
    1545             : {
    1546           0 :     nsAutoCString sourceStr;
    1547           0 :     switch (source) {
    1548             :     case LOCAL_GL_DEBUG_SOURCE_API:
    1549           0 :         sourceStr = NS_LITERAL_CSTRING("SOURCE_API");
    1550           0 :         break;
    1551             :     case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM:
    1552           0 :         sourceStr = NS_LITERAL_CSTRING("SOURCE_WINDOW_SYSTEM");
    1553           0 :         break;
    1554             :     case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER:
    1555           0 :         sourceStr = NS_LITERAL_CSTRING("SOURCE_SHADER_COMPILER");
    1556           0 :         break;
    1557             :     case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY:
    1558           0 :         sourceStr = NS_LITERAL_CSTRING("SOURCE_THIRD_PARTY");
    1559           0 :         break;
    1560             :     case LOCAL_GL_DEBUG_SOURCE_APPLICATION:
    1561           0 :         sourceStr = NS_LITERAL_CSTRING("SOURCE_APPLICATION");
    1562           0 :         break;
    1563             :     case LOCAL_GL_DEBUG_SOURCE_OTHER:
    1564           0 :         sourceStr = NS_LITERAL_CSTRING("SOURCE_OTHER");
    1565           0 :         break;
    1566             :     default:
    1567           0 :         sourceStr = nsPrintfCString("<source 0x%04x>", source);
    1568           0 :         break;
    1569             :     }
    1570             : 
    1571           0 :     nsAutoCString typeStr;
    1572           0 :     switch (type) {
    1573             :     case LOCAL_GL_DEBUG_TYPE_ERROR:
    1574           0 :         typeStr = NS_LITERAL_CSTRING("TYPE_ERROR");
    1575           0 :         break;
    1576             :     case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
    1577           0 :         typeStr = NS_LITERAL_CSTRING("TYPE_DEPRECATED_BEHAVIOR");
    1578           0 :         break;
    1579             :     case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
    1580           0 :         typeStr = NS_LITERAL_CSTRING("TYPE_UNDEFINED_BEHAVIOR");
    1581           0 :         break;
    1582             :     case LOCAL_GL_DEBUG_TYPE_PORTABILITY:
    1583           0 :         typeStr = NS_LITERAL_CSTRING("TYPE_PORTABILITY");
    1584           0 :         break;
    1585             :     case LOCAL_GL_DEBUG_TYPE_PERFORMANCE:
    1586           0 :         typeStr = NS_LITERAL_CSTRING("TYPE_PERFORMANCE");
    1587           0 :         break;
    1588             :     case LOCAL_GL_DEBUG_TYPE_OTHER:
    1589           0 :         typeStr = NS_LITERAL_CSTRING("TYPE_OTHER");
    1590           0 :         break;
    1591             :     case LOCAL_GL_DEBUG_TYPE_MARKER:
    1592           0 :         typeStr = NS_LITERAL_CSTRING("TYPE_MARKER");
    1593           0 :         break;
    1594             :     default:
    1595           0 :         typeStr = nsPrintfCString("<type 0x%04x>", type);
    1596           0 :         break;
    1597             :     }
    1598             : 
    1599           0 :     nsAutoCString sevStr;
    1600           0 :     switch (severity) {
    1601             :     case LOCAL_GL_DEBUG_SEVERITY_HIGH:
    1602           0 :         sevStr = NS_LITERAL_CSTRING("SEVERITY_HIGH");
    1603           0 :         break;
    1604             :     case LOCAL_GL_DEBUG_SEVERITY_MEDIUM:
    1605           0 :         sevStr = NS_LITERAL_CSTRING("SEVERITY_MEDIUM");
    1606           0 :         break;
    1607             :     case LOCAL_GL_DEBUG_SEVERITY_LOW:
    1608           0 :         sevStr = NS_LITERAL_CSTRING("SEVERITY_LOW");
    1609           0 :         break;
    1610             :     case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION:
    1611           0 :         sevStr = NS_LITERAL_CSTRING("SEVERITY_NOTIFICATION");
    1612           0 :         break;
    1613             :     default:
    1614           0 :         sevStr = nsPrintfCString("<severity 0x%04x>", severity);
    1615           0 :         break;
    1616             :     }
    1617             : 
    1618           0 :     printf_stderr("[KHR_debug: 0x%" PRIxPTR "] ID %u: %s, %s, %s:\n    %s\n",
    1619             :                   (uintptr_t)this,
    1620             :                   id,
    1621             :                   sourceStr.BeginReading(),
    1622             :                   typeStr.BeginReading(),
    1623             :                   sevStr.BeginReading(),
    1624           0 :                   message);
    1625           0 : }
    1626             : 
    1627             : void
    1628           0 : GLContext::InitExtensions()
    1629             : {
    1630           0 :     MOZ_ASSERT(IsCurrent());
    1631             : 
    1632           0 :     std::vector<nsCString> driverExtensionList;
    1633             : 
    1634           0 :     if (mSymbols.fGetStringi) {
    1635           0 :         GLuint count = 0;
    1636           0 :         GetUIntegerv(LOCAL_GL_NUM_EXTENSIONS, &count);
    1637           0 :         for (GLuint i = 0; i < count; i++) {
    1638             :             // This is UTF-8.
    1639           0 :             const char* rawExt = (const char*)fGetStringi(LOCAL_GL_EXTENSIONS, i);
    1640             : 
    1641             :             // We CANNOT use nsDependentCString here, because the spec doesn't guarantee
    1642             :             // that the pointers returned are different, only that their contents are.
    1643             :             // On Flame, each of these index string queries returns the same address.
    1644           0 :             driverExtensionList.push_back(nsCString(rawExt));
    1645             :         }
    1646             :     } else {
    1647           0 :         MOZ_ALWAYS_TRUE(!fGetError());
    1648           0 :         const char* rawExts = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
    1649           0 :         MOZ_ALWAYS_TRUE(!fGetError());
    1650             : 
    1651           0 :         if (rawExts) {
    1652           0 :             nsDependentCString exts(rawExts);
    1653           0 :             SplitByChar(exts, ' ', &driverExtensionList);
    1654             :         }
    1655             :     }
    1656             : 
    1657           0 :     const bool shouldDumpExts = ShouldDumpExts();
    1658           0 :     if (shouldDumpExts) {
    1659           0 :         printf_stderr("%i GL driver extensions: (*: recognized)\n",
    1660           0 :                       (uint32_t)driverExtensionList.size());
    1661             :     }
    1662             : 
    1663           0 :     MarkBitfieldByStrings(driverExtensionList, shouldDumpExts, sExtensionNames,
    1664           0 :                           &mAvailableExtensions);
    1665             : 
    1666           0 :     if (WorkAroundDriverBugs()) {
    1667           0 :         if (Vendor() == GLVendor::Qualcomm) {
    1668             :             // Some Adreno drivers do not report GL_OES_EGL_sync, but they really do support it.
    1669           0 :             MarkExtensionSupported(OES_EGL_sync);
    1670             :         }
    1671             : 
    1672           0 :         if (Vendor() == GLVendor::ATI) {
    1673             :             // ATI drivers say this extension exists, but we can't
    1674             :             // actually find the EGLImageTargetRenderbufferStorageOES
    1675             :             // extension function pointer in the drivers.
    1676           0 :             MarkExtensionUnsupported(OES_EGL_image);
    1677             :         }
    1678             : 
    1679           0 :         if (Vendor() == GLVendor::Imagination &&
    1680           0 :             Renderer() == GLRenderer::SGX540)
    1681             :         {
    1682             :             // Bug 980048
    1683           0 :             MarkExtensionUnsupported(OES_EGL_sync);
    1684             :         }
    1685             : 
    1686             : #ifdef MOZ_WIDGET_ANDROID
    1687             :         if (Vendor() == GLVendor::Imagination &&
    1688             :             Renderer() == GLRenderer::SGX544MP &&
    1689             :             AndroidBridge::Bridge()->GetAPIVersion() < 21)
    1690             :         {
    1691             :             // Bug 1026404
    1692             :             MarkExtensionUnsupported(OES_EGL_image);
    1693             :             MarkExtensionUnsupported(OES_EGL_image_external);
    1694             :         }
    1695             : #endif
    1696             : 
    1697           0 :         if (Vendor() == GLVendor::ARM &&
    1698           0 :             (Renderer() == GLRenderer::Mali400MP ||
    1699           0 :              Renderer() == GLRenderer::Mali450MP))
    1700             :         {
    1701             :             // Bug 1264505
    1702           0 :             MarkExtensionUnsupported(OES_EGL_image_external);
    1703             :         }
    1704             : 
    1705           0 :         if (Renderer() == GLRenderer::AndroidEmulator) {
    1706             :             // the Android emulator, which we use to run B2G reftests on,
    1707             :             // doesn't expose the OES_rgb8_rgba8 extension, but it seems to
    1708             :             // support it (tautologically, as it only runs on desktop GL).
    1709           0 :             MarkExtensionSupported(OES_rgb8_rgba8);
    1710             :             // there seems to be a similar issue for EXT_texture_format_BGRA8888
    1711             :             // on the Android 4.3 emulator
    1712           0 :             MarkExtensionSupported(EXT_texture_format_BGRA8888);
    1713             :         }
    1714             : 
    1715           0 :         if (Vendor() == GLVendor::VMware &&
    1716           0 :             Renderer() == GLRenderer::GalliumLlvmpipe)
    1717             :         {
    1718             :             // The llvmpipe driver that is used on linux try servers appears to have
    1719             :             // buggy support for s3tc/dxt1 compressed textures.
    1720             :             // See Bug 975824.
    1721           0 :             MarkExtensionUnsupported(EXT_texture_compression_s3tc);
    1722           0 :             MarkExtensionUnsupported(EXT_texture_compression_dxt1);
    1723           0 :             MarkExtensionUnsupported(ANGLE_texture_compression_dxt3);
    1724           0 :             MarkExtensionUnsupported(ANGLE_texture_compression_dxt5);
    1725             :         }
    1726             : 
    1727             : #ifdef XP_MACOSX
    1728             :         // Bug 1009642: On OSX Mavericks (10.9), the driver for Intel HD
    1729             :         // 3000 appears to be buggy WRT updating sub-images of S3TC
    1730             :         // textures with glCompressedTexSubImage2D. Works on Intel HD 4000
    1731             :         // and Intel HD 5000/Iris that I tested.
    1732             :         // Bug 1124996: Appears to be the same on OSX Yosemite (10.10)
    1733             :         if (nsCocoaFeatures::OSXVersionMajor() == 10 &&
    1734             :             nsCocoaFeatures::OSXVersionMinor() >= 9 &&
    1735             :             Renderer() == GLRenderer::IntelHD3000)
    1736             :         {
    1737             :             MarkExtensionUnsupported(EXT_texture_compression_s3tc);
    1738             :         }
    1739             : #endif
    1740             :     }
    1741             : 
    1742           0 :     if (shouldDumpExts) {
    1743           0 :         printf_stderr("\nActivated extensions:\n");
    1744             : 
    1745           0 :         for (size_t i = 0; i < mAvailableExtensions.size(); i++) {
    1746           0 :             if (!mAvailableExtensions[i])
    1747           0 :                 continue;
    1748             : 
    1749           0 :             const char* ext = sExtensionNames[i];
    1750           0 :             printf_stderr("[%i] %s\n", (uint32_t)i, ext);
    1751             :         }
    1752             :     }
    1753           0 : }
    1754             : 
    1755             : void
    1756           3 : GLContext::PlatformStartup()
    1757             : {
    1758           3 :     RegisterStrongMemoryReporter(new GfxTexturesReporter());
    1759           3 : }
    1760             : 
    1761             : // Common code for checking for both GL extensions and GLX extensions.
    1762             : bool
    1763           0 : GLContext::ListHasExtension(const GLubyte* extensions, const char* extension)
    1764             : {
    1765             :     // fix bug 612572 - we were crashing as we were calling this function with extensions==null
    1766           0 :     if (extensions == nullptr || extension == nullptr)
    1767           0 :         return false;
    1768             : 
    1769             :     const GLubyte* start;
    1770             :     GLubyte* where;
    1771             :     GLubyte* terminator;
    1772             : 
    1773             :     /* Extension names should not have spaces. */
    1774           0 :     where = (GLubyte*) strchr(extension, ' ');
    1775           0 :     if (where || *extension == '\0')
    1776           0 :         return false;
    1777             : 
    1778             :     /*
    1779             :      * It takes a bit of care to be fool-proof about parsing the
    1780             :      * OpenGL extensions string. Don't be fooled by sub-strings,
    1781             :      * etc.
    1782             :      */
    1783           0 :     start = extensions;
    1784             :     for (;;) {
    1785           0 :         where = (GLubyte*) strstr((const char*) start, extension);
    1786           0 :         if (!where) {
    1787           0 :             break;
    1788             :         }
    1789           0 :         terminator = where + strlen(extension);
    1790           0 :         if (where == start || *(where - 1) == ' ') {
    1791           0 :             if (*terminator == ' ' || *terminator == '\0') {
    1792           0 :                 return true;
    1793             :             }
    1794             :         }
    1795           0 :         start = terminator;
    1796             :     }
    1797           0 :     return false;
    1798             : }
    1799             : 
    1800             : GLFormats
    1801           0 : GLContext::ChooseGLFormats(const SurfaceCaps& caps) const
    1802             : {
    1803           0 :     GLFormats formats;
    1804             : 
    1805             :     // If we're on ES2 hardware and we have an explicit request for 16 bits of color or less
    1806             :     // OR we don't support full 8-bit color, return a 4444 or 565 format.
    1807           0 :     bool bpp16 = caps.bpp16;
    1808           0 :     if (IsGLES()) {
    1809           0 :         if (!IsExtensionSupported(OES_rgb8_rgba8))
    1810           0 :             bpp16 = true;
    1811             :     } else {
    1812             :         // RGB565 is uncommon on desktop, requiring ARB_ES2_compatibility.
    1813             :         // Since it's also vanishingly useless there, let's not support it.
    1814           0 :         bpp16 = false;
    1815             :     }
    1816             : 
    1817           0 :     if (bpp16) {
    1818           0 :         MOZ_ASSERT(IsGLES());
    1819           0 :         if (caps.alpha) {
    1820           0 :             formats.color_texInternalFormat = LOCAL_GL_RGBA;
    1821           0 :             formats.color_texFormat = LOCAL_GL_RGBA;
    1822           0 :             formats.color_texType   = LOCAL_GL_UNSIGNED_SHORT_4_4_4_4;
    1823           0 :             formats.color_rbFormat  = LOCAL_GL_RGBA4;
    1824             :         } else {
    1825           0 :             formats.color_texInternalFormat = LOCAL_GL_RGB;
    1826           0 :             formats.color_texFormat = LOCAL_GL_RGB;
    1827           0 :             formats.color_texType   = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
    1828           0 :             formats.color_rbFormat  = LOCAL_GL_RGB565;
    1829             :         }
    1830             :     } else {
    1831           0 :         formats.color_texType = LOCAL_GL_UNSIGNED_BYTE;
    1832             : 
    1833           0 :         if (caps.alpha) {
    1834           0 :             formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGBA : LOCAL_GL_RGBA8;
    1835           0 :             formats.color_texFormat = LOCAL_GL_RGBA;
    1836           0 :             formats.color_rbFormat  = LOCAL_GL_RGBA8;
    1837             :         } else {
    1838           0 :             formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGB : LOCAL_GL_RGB8;
    1839           0 :             formats.color_texFormat = LOCAL_GL_RGB;
    1840           0 :             formats.color_rbFormat  = LOCAL_GL_RGB8;
    1841             :         }
    1842             :     }
    1843             : 
    1844           0 :     uint32_t msaaLevel = gfxPrefs::MSAALevel();
    1845           0 :     GLsizei samples = msaaLevel * msaaLevel;
    1846           0 :     samples = std::min(samples, mMaxSamples);
    1847             : 
    1848             :     // Bug 778765.
    1849           0 :     if (WorkAroundDriverBugs() && samples == 1) {
    1850           0 :         samples = 0;
    1851             :     }
    1852           0 :     formats.samples = samples;
    1853             : 
    1854             : 
    1855             :     // Be clear that these are 0 if unavailable.
    1856           0 :     formats.depthStencil = 0;
    1857           0 :     if (IsSupported(GLFeature::packed_depth_stencil)) {
    1858           0 :         formats.depthStencil = LOCAL_GL_DEPTH24_STENCIL8;
    1859             :     }
    1860             : 
    1861           0 :     formats.depth = 0;
    1862           0 :     if (IsGLES()) {
    1863           0 :         if (IsExtensionSupported(OES_depth24)) {
    1864           0 :             formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
    1865             :         } else {
    1866           0 :             formats.depth = LOCAL_GL_DEPTH_COMPONENT16;
    1867             :         }
    1868             :     } else {
    1869           0 :         formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
    1870             :     }
    1871             : 
    1872           0 :     formats.stencil = LOCAL_GL_STENCIL_INDEX8;
    1873             : 
    1874           0 :     return formats;
    1875             : }
    1876             : 
    1877             : bool
    1878           0 : GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus)
    1879             : {
    1880           0 :     MOZ_ASSERT(fb);
    1881             : 
    1882           0 :     ScopedBindFramebuffer autoFB(this, fb);
    1883           0 :     MOZ_ASSERT(fIsFramebuffer(fb));
    1884             : 
    1885           0 :     GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
    1886           0 :     if (pStatus)
    1887           0 :         *pStatus = status;
    1888             : 
    1889           0 :     return status == LOCAL_GL_FRAMEBUFFER_COMPLETE;
    1890             : }
    1891             : 
    1892             : void
    1893           0 : GLContext::AttachBuffersToFB(GLuint colorTex, GLuint colorRB,
    1894             :                              GLuint depthRB, GLuint stencilRB,
    1895             :                              GLuint fb, GLenum target)
    1896             : {
    1897           0 :     MOZ_ASSERT(fb);
    1898           0 :     MOZ_ASSERT( !(colorTex && colorRB) );
    1899             : 
    1900           0 :     ScopedBindFramebuffer autoFB(this, fb);
    1901           0 :     MOZ_ASSERT(fIsFramebuffer(fb)); // It only counts after being bound.
    1902             : 
    1903           0 :     if (colorTex) {
    1904           0 :         MOZ_ASSERT(fIsTexture(colorTex));
    1905           0 :         MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
    1906             :                    target == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
    1907             :         fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
    1908             :                               LOCAL_GL_COLOR_ATTACHMENT0,
    1909             :                               target,
    1910             :                               colorTex,
    1911           0 :                               0);
    1912           0 :     } else if (colorRB) {
    1913             :         // On the Android 4.3 emulator, IsRenderbuffer may return false incorrectly.
    1914           0 :         MOZ_ASSERT_IF(Renderer() != GLRenderer::AndroidEmulator, fIsRenderbuffer(colorRB));
    1915             :         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
    1916             :                                  LOCAL_GL_COLOR_ATTACHMENT0,
    1917             :                                  LOCAL_GL_RENDERBUFFER,
    1918           0 :                                  colorRB);
    1919             :     }
    1920             : 
    1921           0 :     if (depthRB) {
    1922           0 :         MOZ_ASSERT_IF(Renderer() != GLRenderer::AndroidEmulator, fIsRenderbuffer(depthRB));
    1923             :         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
    1924             :                                  LOCAL_GL_DEPTH_ATTACHMENT,
    1925             :                                  LOCAL_GL_RENDERBUFFER,
    1926           0 :                                  depthRB);
    1927             :     }
    1928             : 
    1929           0 :     if (stencilRB) {
    1930           0 :         MOZ_ASSERT_IF(Renderer() != GLRenderer::AndroidEmulator, fIsRenderbuffer(stencilRB));
    1931             :         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
    1932             :                                  LOCAL_GL_STENCIL_ATTACHMENT,
    1933             :                                  LOCAL_GL_RENDERBUFFER,
    1934           0 :                                  stencilRB);
    1935             :     }
    1936           0 : }
    1937             : 
    1938             : bool
    1939           0 : GLContext::AssembleOffscreenFBs(const GLuint colorMSRB,
    1940             :                                 const GLuint depthRB,
    1941             :                                 const GLuint stencilRB,
    1942             :                                 const GLuint texture,
    1943             :                                 GLuint* drawFB_out,
    1944             :                                 GLuint* readFB_out)
    1945             : {
    1946           0 :     if (!colorMSRB && !texture) {
    1947           0 :         MOZ_ASSERT(!depthRB && !stencilRB);
    1948             : 
    1949           0 :         if (drawFB_out)
    1950           0 :             *drawFB_out = 0;
    1951           0 :         if (readFB_out)
    1952           0 :             *readFB_out = 0;
    1953             : 
    1954           0 :         return true;
    1955             :     }
    1956             : 
    1957           0 :     ScopedBindFramebuffer autoFB(this);
    1958             : 
    1959           0 :     GLuint drawFB = 0;
    1960           0 :     GLuint readFB = 0;
    1961             : 
    1962           0 :     if (texture) {
    1963           0 :         readFB = 0;
    1964           0 :         fGenFramebuffers(1, &readFB);
    1965           0 :         BindFB(readFB);
    1966             :         fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
    1967             :                               LOCAL_GL_COLOR_ATTACHMENT0,
    1968             :                               LOCAL_GL_TEXTURE_2D,
    1969             :                               texture,
    1970           0 :                               0);
    1971             :     }
    1972             : 
    1973           0 :     if (colorMSRB) {
    1974           0 :         drawFB = 0;
    1975           0 :         fGenFramebuffers(1, &drawFB);
    1976           0 :         BindFB(drawFB);
    1977             :         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
    1978             :                                  LOCAL_GL_COLOR_ATTACHMENT0,
    1979             :                                  LOCAL_GL_RENDERBUFFER,
    1980           0 :                                  colorMSRB);
    1981             :     } else {
    1982           0 :         drawFB = readFB;
    1983             :     }
    1984           0 :     MOZ_ASSERT(GetFB() == drawFB);
    1985             : 
    1986           0 :     if (depthRB) {
    1987             :         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
    1988             :                                  LOCAL_GL_DEPTH_ATTACHMENT,
    1989             :                                  LOCAL_GL_RENDERBUFFER,
    1990           0 :                                  depthRB);
    1991             :     }
    1992             : 
    1993           0 :     if (stencilRB) {
    1994             :         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
    1995             :                                  LOCAL_GL_STENCIL_ATTACHMENT,
    1996             :                                  LOCAL_GL_RENDERBUFFER,
    1997           0 :                                  stencilRB);
    1998             :     }
    1999             : 
    2000             :     // We should be all resized.  Check for framebuffer completeness.
    2001             :     GLenum status;
    2002           0 :     bool isComplete = true;
    2003             : 
    2004           0 :     if (!IsFramebufferComplete(drawFB, &status)) {
    2005           0 :         NS_WARNING("DrawFBO: Incomplete");
    2006             :   #ifdef MOZ_GL_DEBUG
    2007           0 :         if (ShouldSpew()) {
    2008           0 :             printf_stderr("Framebuffer status: %X\n", status);
    2009             :         }
    2010             :   #endif
    2011           0 :         isComplete = false;
    2012             :     }
    2013             : 
    2014           0 :     if (!IsFramebufferComplete(readFB, &status)) {
    2015           0 :         NS_WARNING("ReadFBO: Incomplete");
    2016             :   #ifdef MOZ_GL_DEBUG
    2017           0 :         if (ShouldSpew()) {
    2018           0 :             printf_stderr("Framebuffer status: %X\n", status);
    2019             :         }
    2020             :   #endif
    2021           0 :         isComplete = false;
    2022             :     }
    2023             : 
    2024           0 :     if (drawFB_out) {
    2025           0 :         *drawFB_out = drawFB;
    2026           0 :     } else if (drawFB) {
    2027           0 :         MOZ_CRASH("drawFB created when not requested!");
    2028             :     }
    2029             : 
    2030           0 :     if (readFB_out) {
    2031           0 :         *readFB_out = readFB;
    2032           0 :     } else if (readFB) {
    2033           0 :         MOZ_CRASH("readFB created when not requested!");
    2034             :     }
    2035             : 
    2036           0 :     return isComplete;
    2037             : }
    2038             : 
    2039             : 
    2040             : void
    2041           0 : GLContext::ClearSafely()
    2042             : {
    2043             :     // bug 659349 --- we must be very careful here: clearing a GL framebuffer is nontrivial, relies on a lot of state,
    2044             :     // and in the case of the backbuffer of a WebGL context, state is exposed to scripts.
    2045             :     //
    2046             :     // The code here is taken from WebGLContext::ForceClearFramebufferWithDefaultValues, but I didn't find a good way of
    2047             :     // sharing code with it. WebGL's code is somewhat performance-critical as it is typically called on every frame, so
    2048             :     // WebGL keeps track of GL state to avoid having to query it everytime, and also tries to only do work for actually
    2049             :     // present buffers (e.g. stencil buffer). Doing that here seems like premature optimization,
    2050             :     // as ClearSafely() is called only when e.g. a canvas is resized, not on every animation frame.
    2051             : 
    2052             :     realGLboolean scissorTestEnabled;
    2053             :     realGLboolean ditherEnabled;
    2054             :     realGLboolean colorWriteMask[4];
    2055             :     realGLboolean depthWriteMask;
    2056             :     GLint stencilWriteMaskFront, stencilWriteMaskBack;
    2057             :     GLfloat colorClearValue[4];
    2058             :     GLfloat depthClearValue;
    2059             :     GLint stencilClearValue;
    2060             : 
    2061             :     // save current GL state
    2062           0 :     fGetBooleanv(LOCAL_GL_SCISSOR_TEST, &scissorTestEnabled);
    2063           0 :     fGetBooleanv(LOCAL_GL_DITHER, &ditherEnabled);
    2064           0 :     fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
    2065           0 :     fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
    2066           0 :     fGetIntegerv(LOCAL_GL_STENCIL_WRITEMASK, &stencilWriteMaskFront);
    2067           0 :     fGetIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK, &stencilWriteMaskBack);
    2068           0 :     fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);
    2069           0 :     fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
    2070           0 :     fGetIntegerv(LOCAL_GL_STENCIL_CLEAR_VALUE, &stencilClearValue);
    2071             : 
    2072             :     // prepare GL state for clearing
    2073           0 :     fDisable(LOCAL_GL_SCISSOR_TEST);
    2074           0 :     fDisable(LOCAL_GL_DITHER);
    2075             : 
    2076           0 :     fColorMask(1, 1, 1, 1);
    2077           0 :     fClearColor(0.f, 0.f, 0.f, 0.f);
    2078             : 
    2079           0 :     fDepthMask(1);
    2080           0 :     fClearDepth(1.0f);
    2081             : 
    2082           0 :     fStencilMask(0xffffffff);
    2083           0 :     fClearStencil(0);
    2084             : 
    2085             :     // do clear
    2086             :     fClear(LOCAL_GL_COLOR_BUFFER_BIT |
    2087             :            LOCAL_GL_DEPTH_BUFFER_BIT |
    2088           0 :            LOCAL_GL_STENCIL_BUFFER_BIT);
    2089             : 
    2090             :     // restore GL state after clearing
    2091           0 :     fColorMask(colorWriteMask[0],
    2092           0 :                colorWriteMask[1],
    2093           0 :                colorWriteMask[2],
    2094           0 :                colorWriteMask[3]);
    2095           0 :     fClearColor(colorClearValue[0],
    2096             :                 colorClearValue[1],
    2097             :                 colorClearValue[2],
    2098           0 :                 colorClearValue[3]);
    2099             : 
    2100           0 :     fDepthMask(depthWriteMask);
    2101           0 :     fClearDepth(depthClearValue);
    2102             : 
    2103           0 :     fStencilMaskSeparate(LOCAL_GL_FRONT, stencilWriteMaskFront);
    2104           0 :     fStencilMaskSeparate(LOCAL_GL_BACK, stencilWriteMaskBack);
    2105           0 :     fClearStencil(stencilClearValue);
    2106             : 
    2107           0 :     if (ditherEnabled)
    2108           0 :         fEnable(LOCAL_GL_DITHER);
    2109             :     else
    2110           0 :         fDisable(LOCAL_GL_DITHER);
    2111             : 
    2112           0 :     if (scissorTestEnabled)
    2113           0 :         fEnable(LOCAL_GL_SCISSOR_TEST);
    2114             :     else
    2115           0 :         fDisable(LOCAL_GL_SCISSOR_TEST);
    2116             : 
    2117           0 : }
    2118             : 
    2119             : void
    2120           0 : GLContext::MarkDestroyed()
    2121             : {
    2122           0 :     if (IsDestroyed())
    2123           0 :         return;
    2124             : 
    2125             :     // Null these before they're naturally nulled after dtor, as we want GLContext to
    2126             :     // still be alive in *their* dtors.
    2127           0 :     mScreen = nullptr;
    2128           0 :     mBlitHelper = nullptr;
    2129           0 :     mReadTexImageHelper = nullptr;
    2130             : 
    2131           0 :     if (!MakeCurrent()) {
    2132           0 :         NS_WARNING("MakeCurrent() failed during MarkDestroyed! Skipping GL object teardown.");
    2133             :     }
    2134             : 
    2135           0 :     mSymbols.Zero();
    2136             : }
    2137             : 
    2138             : #ifdef MOZ_GL_DEBUG
    2139             : /* static */ void
    2140           0 : GLContext::AssertNotPassingStackBufferToTheGL(const void* ptr)
    2141             : {
    2142             :   int somethingOnTheStack;
    2143           0 :   const void* someStackPtr = &somethingOnTheStack;
    2144           0 :   const int page_bits = 12;
    2145           0 :   intptr_t page = reinterpret_cast<uintptr_t>(ptr) >> page_bits;
    2146           0 :   intptr_t someStackPage = reinterpret_cast<uintptr_t>(someStackPtr) >> page_bits;
    2147           0 :   uintptr_t pageDistance = std::abs(page - someStackPage);
    2148             : 
    2149             :   // Explanation for the "distance <= 1" check here as opposed to just
    2150             :   // an equality check.
    2151             :   //
    2152             :   // Here we assume that pages immediately adjacent to the someStackAddress page,
    2153             :   // are also stack pages. That allows to catch the case where the calling frame put
    2154             :   // a buffer on the stack, and we just crossed the page boundary. That is likely
    2155             :   // to happen, precisely, when using stack arrays. I hit that specifically
    2156             :   // with CompositorOGL::Initialize.
    2157             :   //
    2158             :   // In theory we could be unlucky and wrongly assert here. If that happens,
    2159             :   // it will only affect debug builds, and looking at stacks we'll be able to
    2160             :   // see that this assert is wrong and revert to the conservative and safe
    2161             :   // approach of only asserting when address and someStackAddress are
    2162             :   // on the same page.
    2163           0 :   bool isStackAddress = pageDistance <= 1;
    2164           0 :   MOZ_ASSERT(!isStackAddress,
    2165             :              "Please don't pass stack arrays to the GL. "
    2166             :              "Consider using HeapCopyOfStackArray. "
    2167             :              "See bug 1005658.");
    2168           0 : }
    2169             : 
    2170             : void
    2171           0 : GLContext::CreatedProgram(GLContext* aOrigin, GLuint aName)
    2172             : {
    2173           0 :     mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName));
    2174           0 : }
    2175             : 
    2176             : void
    2177           0 : GLContext::CreatedShader(GLContext* aOrigin, GLuint aName)
    2178             : {
    2179           0 :     mTrackedShaders.AppendElement(NamedResource(aOrigin, aName));
    2180           0 : }
    2181             : 
    2182             : void
    2183           0 : GLContext::CreatedBuffers(GLContext* aOrigin, GLsizei aCount, GLuint* aNames)
    2184             : {
    2185           0 :     for (GLsizei i = 0; i < aCount; ++i) {
    2186           0 :         mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
    2187             :     }
    2188           0 : }
    2189             : 
    2190             : void
    2191           0 : GLContext::CreatedQueries(GLContext* aOrigin, GLsizei aCount, GLuint* aNames)
    2192             : {
    2193           0 :     for (GLsizei i = 0; i < aCount; ++i) {
    2194           0 :         mTrackedQueries.AppendElement(NamedResource(aOrigin, aNames[i]));
    2195             :     }
    2196           0 : }
    2197             : 
    2198             : void
    2199           0 : GLContext::CreatedTextures(GLContext* aOrigin, GLsizei aCount, GLuint* aNames)
    2200             : {
    2201           0 :     for (GLsizei i = 0; i < aCount; ++i) {
    2202           0 :         mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i]));
    2203             :     }
    2204           0 : }
    2205             : 
    2206             : void
    2207           0 : GLContext::CreatedFramebuffers(GLContext* aOrigin, GLsizei aCount, GLuint* aNames)
    2208             : {
    2209           0 :     for (GLsizei i = 0; i < aCount; ++i) {
    2210           0 :         mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
    2211             :     }
    2212           0 : }
    2213             : 
    2214             : void
    2215           0 : GLContext::CreatedRenderbuffers(GLContext* aOrigin, GLsizei aCount, GLuint* aNames)
    2216             : {
    2217           0 :     for (GLsizei i = 0; i < aCount; ++i) {
    2218           0 :         mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
    2219             :     }
    2220           0 : }
    2221             : 
    2222             : static void
    2223           0 : RemoveNamesFromArray(GLContext* aOrigin, GLsizei aCount, const GLuint* aNames, nsTArray<GLContext::NamedResource>& aArray)
    2224             : {
    2225           0 :     for (GLsizei j = 0; j < aCount; ++j) {
    2226           0 :         GLuint name = aNames[j];
    2227             :         // name 0 can be ignored
    2228           0 :         if (name == 0)
    2229           0 :             continue;
    2230             : 
    2231           0 :         for (uint32_t i = 0; i < aArray.Length(); ++i) {
    2232           0 :             if (aArray[i].name == name) {
    2233           0 :                 aArray.RemoveElementAt(i);
    2234           0 :                 break;
    2235             :             }
    2236             :         }
    2237             :     }
    2238           0 : }
    2239             : 
    2240             : void
    2241           0 : GLContext::DeletedProgram(GLContext* aOrigin, GLuint aName)
    2242             : {
    2243           0 :     RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms);
    2244           0 : }
    2245             : 
    2246             : void
    2247           0 : GLContext::DeletedShader(GLContext* aOrigin, GLuint aName)
    2248             : {
    2249           0 :     RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders);
    2250           0 : }
    2251             : 
    2252             : void
    2253           0 : GLContext::DeletedBuffers(GLContext* aOrigin, GLsizei aCount, const GLuint* aNames)
    2254             : {
    2255           0 :     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers);
    2256           0 : }
    2257             : 
    2258             : void
    2259           0 : GLContext::DeletedQueries(GLContext* aOrigin, GLsizei aCount, const GLuint* aNames)
    2260             : {
    2261           0 :     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedQueries);
    2262           0 : }
    2263             : 
    2264             : void
    2265           0 : GLContext::DeletedTextures(GLContext* aOrigin, GLsizei aCount, const GLuint* aNames)
    2266             : {
    2267           0 :     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures);
    2268           0 : }
    2269             : 
    2270             : void
    2271           0 : GLContext::DeletedFramebuffers(GLContext* aOrigin, GLsizei aCount, const GLuint* aNames)
    2272             : {
    2273           0 :     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers);
    2274           0 : }
    2275             : 
    2276             : void
    2277           0 : GLContext::DeletedRenderbuffers(GLContext* aOrigin, GLsizei aCount, const GLuint* aNames)
    2278             : {
    2279           0 :     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers);
    2280           0 : }
    2281             : 
    2282             : static void
    2283           0 : MarkContextDestroyedInArray(GLContext* aContext, nsTArray<GLContext::NamedResource>& aArray)
    2284             : {
    2285           0 :     for (uint32_t i = 0; i < aArray.Length(); ++i) {
    2286           0 :         if (aArray[i].origin == aContext)
    2287           0 :             aArray[i].originDeleted = true;
    2288             :     }
    2289           0 : }
    2290             : 
    2291             : void
    2292           0 : GLContext::SharedContextDestroyed(GLContext* aChild)
    2293             : {
    2294           0 :     MarkContextDestroyedInArray(aChild, mTrackedPrograms);
    2295           0 :     MarkContextDestroyedInArray(aChild, mTrackedShaders);
    2296           0 :     MarkContextDestroyedInArray(aChild, mTrackedTextures);
    2297           0 :     MarkContextDestroyedInArray(aChild, mTrackedFramebuffers);
    2298           0 :     MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers);
    2299           0 :     MarkContextDestroyedInArray(aChild, mTrackedBuffers);
    2300           0 :     MarkContextDestroyedInArray(aChild, mTrackedQueries);
    2301           0 : }
    2302             : 
    2303             : static void
    2304           0 : ReportArrayContents(const char* title, const nsTArray<GLContext::NamedResource>& aArray)
    2305             : {
    2306           0 :     if (aArray.Length() == 0)
    2307           0 :         return;
    2308             : 
    2309           0 :     printf_stderr("%s:\n", title);
    2310             : 
    2311           0 :     nsTArray<GLContext::NamedResource> copy(aArray);
    2312           0 :     copy.Sort();
    2313             : 
    2314           0 :     GLContext* lastContext = nullptr;
    2315           0 :     for (uint32_t i = 0; i < copy.Length(); ++i) {
    2316           0 :         if (lastContext != copy[i].origin) {
    2317           0 :             if (lastContext)
    2318           0 :                 printf_stderr("\n");
    2319           0 :             printf_stderr("  [%p - %s] ", copy[i].origin, copy[i].originDeleted ? "deleted" : "live");
    2320           0 :             lastContext = copy[i].origin;
    2321             :         }
    2322           0 :         printf_stderr("%d ", copy[i].name);
    2323             :     }
    2324           0 :     printf_stderr("\n");
    2325             : }
    2326             : 
    2327             : void
    2328           0 : GLContext::ReportOutstandingNames()
    2329             : {
    2330           0 :     if (!ShouldSpew())
    2331           0 :         return;
    2332             : 
    2333           0 :     printf_stderr("== GLContext %p Outstanding ==\n", this);
    2334             : 
    2335           0 :     ReportArrayContents("Outstanding Textures", mTrackedTextures);
    2336           0 :     ReportArrayContents("Outstanding Buffers", mTrackedBuffers);
    2337           0 :     ReportArrayContents("Outstanding Queries", mTrackedQueries);
    2338           0 :     ReportArrayContents("Outstanding Programs", mTrackedPrograms);
    2339           0 :     ReportArrayContents("Outstanding Shaders", mTrackedShaders);
    2340           0 :     ReportArrayContents("Outstanding Framebuffers", mTrackedFramebuffers);
    2341           0 :     ReportArrayContents("Outstanding Renderbuffers", mTrackedRenderbuffers);
    2342             : }
    2343             : 
    2344             : #endif /* DEBUG */
    2345             : 
    2346             : void
    2347           0 : GLContext::GuaranteeResolve()
    2348             : {
    2349           0 :     if (mScreen) {
    2350           0 :         mScreen->AssureBlitted();
    2351             :     }
    2352           0 :     fFinish();
    2353           0 : }
    2354             : 
    2355             : const gfx::IntSize&
    2356           0 : GLContext::OffscreenSize() const
    2357             : {
    2358           0 :     MOZ_ASSERT(IsOffscreen());
    2359           0 :     return mScreen->Size();
    2360             : }
    2361             : 
    2362             : bool
    2363           0 : GLContext::CreateScreenBufferImpl(const IntSize& size, const SurfaceCaps& caps)
    2364             : {
    2365           0 :     UniquePtr<GLScreenBuffer> newScreen = GLScreenBuffer::Create(this, size, caps);
    2366           0 :     if (!newScreen)
    2367           0 :         return false;
    2368             : 
    2369           0 :     if (!newScreen->Resize(size)) {
    2370           0 :         return false;
    2371             :     }
    2372             : 
    2373             :     // This will rebind to 0 (Screen) if needed when
    2374             :     // it falls out of scope.
    2375           0 :     ScopedBindFramebuffer autoFB(this);
    2376             : 
    2377           0 :     mScreen = Move(newScreen);
    2378             : 
    2379           0 :     return true;
    2380             : }
    2381             : 
    2382             : bool
    2383           0 : GLContext::ResizeScreenBuffer(const IntSize& size)
    2384             : {
    2385           0 :     if (!IsOffscreenSizeAllowed(size))
    2386           0 :         return false;
    2387             : 
    2388           0 :     return mScreen->Resize(size);
    2389             : }
    2390             : 
    2391             : void
    2392           0 : GLContext::ForceDirtyScreen()
    2393             : {
    2394           0 :     ScopedBindFramebuffer autoFB(0);
    2395             : 
    2396           0 :     BeforeGLDrawCall();
    2397             :     // no-op; just pretend we did something
    2398           0 :     AfterGLDrawCall();
    2399           0 : }
    2400             : 
    2401             : void
    2402           0 : GLContext::CleanDirtyScreen()
    2403             : {
    2404           0 :     ScopedBindFramebuffer autoFB(0);
    2405             : 
    2406           0 :     BeforeGLReadCall();
    2407             :     // no-op; we just want to make sure the Read FBO is updated if it needs to be
    2408           0 :     AfterGLReadCall();
    2409           0 : }
    2410             : 
    2411             : bool
    2412           0 : GLContext::IsOffscreenSizeAllowed(const IntSize& aSize) const
    2413             : {
    2414           0 :     int32_t biggerDimension = std::max(aSize.width, aSize.height);
    2415           0 :     int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize);
    2416           0 :     return biggerDimension <= maxAllowed;
    2417             : }
    2418             : 
    2419             : bool
    2420           0 : GLContext::IsOwningThreadCurrent()
    2421             : {
    2422           0 :     return PlatformThread::CurrentId() == mOwningThreadId;
    2423             : }
    2424             : 
    2425             : GLBlitHelper*
    2426           0 : GLContext::BlitHelper()
    2427             : {
    2428           0 :     if (!mBlitHelper) {
    2429           0 :         mBlitHelper.reset(new GLBlitHelper(this));
    2430             :     }
    2431             : 
    2432           0 :     return mBlitHelper.get();
    2433             : }
    2434             : 
    2435             : GLReadTexImageHelper*
    2436           0 : GLContext::ReadTexImageHelper()
    2437             : {
    2438           0 :     if (!mReadTexImageHelper) {
    2439           0 :         mReadTexImageHelper = MakeUnique<GLReadTexImageHelper>(this);
    2440             :     }
    2441             : 
    2442           0 :     return mReadTexImageHelper.get();
    2443             : }
    2444             : 
    2445             : void
    2446           0 : GLContext::FlushIfHeavyGLCallsSinceLastFlush()
    2447             : {
    2448           0 :     if (!mHeavyGLCallsSinceLastFlush) {
    2449           0 :         return;
    2450             :     }
    2451           0 :     MakeCurrent();
    2452           0 :     fFlush();
    2453             : }
    2454             : 
    2455             : /*static*/ bool
    2456           0 : GLContext::ShouldDumpExts()
    2457             : {
    2458           0 :     return gfxEnv::GlDumpExtensions();
    2459             : }
    2460             : 
    2461             : bool
    2462           0 : DoesStringMatch(const char* aString, const char* aWantedString)
    2463             : {
    2464           0 :     if (!aString || !aWantedString)
    2465           0 :         return false;
    2466             : 
    2467           0 :     const char* occurrence = strstr(aString, aWantedString);
    2468             : 
    2469             :     // aWanted not found
    2470           0 :     if (!occurrence)
    2471           0 :         return false;
    2472             : 
    2473             :     // aWantedString preceded by alpha character
    2474           0 :     if (occurrence != aString && isalpha(*(occurrence-1)))
    2475           0 :         return false;
    2476             : 
    2477             :     // aWantedVendor followed by alpha character
    2478           0 :     const char* afterOccurrence = occurrence + strlen(aWantedString);
    2479           0 :     if (isalpha(*afterOccurrence))
    2480           0 :         return false;
    2481             : 
    2482           0 :     return true;
    2483             : }
    2484             : 
    2485             : /*static*/ bool
    2486           0 : GLContext::ShouldSpew()
    2487             : {
    2488           0 :     return gfxEnv::GlSpew();
    2489             : }
    2490             : 
    2491             : void
    2492           0 : SplitByChar(const nsACString& str, const char delim, std::vector<nsCString>* const out)
    2493             : {
    2494           0 :     uint32_t start = 0;
    2495             :     while (true) {
    2496           0 :         int32_t end = str.FindChar(' ', start);
    2497           0 :         if (end == -1)
    2498           0 :             break;
    2499             : 
    2500           0 :         uint32_t len = (uint32_t)end - start;
    2501           0 :         nsDependentCSubstring substr(str, start, len);
    2502           0 :         out->push_back(nsCString(substr));
    2503             : 
    2504           0 :         start = end + 1;
    2505           0 :         continue;
    2506           0 :     }
    2507             : 
    2508           0 :     nsDependentCSubstring substr(str, start);
    2509           0 :     out->push_back(nsCString(substr));
    2510           0 : }
    2511             : 
    2512             : void
    2513           0 : GLContext::Readback(SharedSurface* src, gfx::DataSourceSurface* dest)
    2514             : {
    2515           0 :     MOZ_ASSERT(src && dest);
    2516           0 :     MOZ_ASSERT(dest->GetSize() == src->mSize);
    2517           0 :     MOZ_ASSERT(dest->GetFormat() == (src->mHasAlpha ? SurfaceFormat::B8G8R8A8
    2518             :                                                     : SurfaceFormat::B8G8R8X8));
    2519             : 
    2520           0 :     MakeCurrent();
    2521             : 
    2522           0 :     SharedSurface* prev = GetLockedSurface();
    2523             : 
    2524           0 :     const bool needsSwap = src != prev;
    2525           0 :     if (needsSwap) {
    2526           0 :         if (prev)
    2527           0 :             prev->UnlockProd();
    2528           0 :         src->LockProd();
    2529             :     }
    2530             : 
    2531           0 :     GLuint tempFB = 0;
    2532           0 :     GLuint tempTex = 0;
    2533             : 
    2534             :     {
    2535           0 :         ScopedBindFramebuffer autoFB(this);
    2536             : 
    2537             :         // We're consuming from the producer side, so which do we use?
    2538             :         // Really, we just want a read-only lock, so ConsumerAcquire is the best match.
    2539           0 :         src->ProducerReadAcquire();
    2540             : 
    2541           0 :         if (src->mAttachType == AttachmentType::Screen) {
    2542           0 :             fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
    2543             :         } else {
    2544           0 :             fGenFramebuffers(1, &tempFB);
    2545           0 :             fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, tempFB);
    2546             : 
    2547           0 :             switch (src->mAttachType) {
    2548             :             case AttachmentType::GLTexture:
    2549           0 :                 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
    2550           0 :                                       src->ProdTextureTarget(), src->ProdTexture(), 0);
    2551           0 :                 break;
    2552             :             case AttachmentType::GLRenderbuffer:
    2553           0 :                 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
    2554           0 :                                          LOCAL_GL_RENDERBUFFER, src->ProdRenderbuffer());
    2555           0 :                 break;
    2556             :             default:
    2557           0 :                 MOZ_CRASH("GFX: bad `src->mAttachType`.");
    2558             :             }
    2559             : 
    2560           0 :             DebugOnly<GLenum> status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
    2561           0 :             MOZ_ASSERT(status == LOCAL_GL_FRAMEBUFFER_COMPLETE);
    2562             :         }
    2563             : 
    2564           0 :         if (src->NeedsIndirectReads()) {
    2565           0 :             fGenTextures(1, &tempTex);
    2566             :             {
    2567           0 :                 ScopedBindTexture autoTex(this, tempTex);
    2568             : 
    2569           0 :                 GLenum format = src->mHasAlpha ? LOCAL_GL_RGBA
    2570           0 :                                                : LOCAL_GL_RGB;
    2571           0 :                 auto width = src->mSize.width;
    2572           0 :                 auto height = src->mSize.height;
    2573             :                 fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, format, 0, 0, width,
    2574           0 :                                 height, 0);
    2575             :             }
    2576             : 
    2577             :             fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
    2578             :                                   LOCAL_GL_COLOR_ATTACHMENT0,
    2579           0 :                                   LOCAL_GL_TEXTURE_2D, tempTex, 0);
    2580             :         }
    2581             : 
    2582           0 :         ReadPixelsIntoDataSurface(this, dest);
    2583             : 
    2584           0 :         src->ProducerReadRelease();
    2585             :     }
    2586             : 
    2587           0 :     if (tempFB)
    2588           0 :         fDeleteFramebuffers(1, &tempFB);
    2589             : 
    2590           0 :     if (tempTex) {
    2591           0 :         fDeleteTextures(1, &tempTex);
    2592             :     }
    2593             : 
    2594           0 :     if (needsSwap) {
    2595           0 :         src->UnlockProd();
    2596           0 :         if (prev)
    2597           0 :             prev->LockProd();
    2598             :     }
    2599           0 : }
    2600             : 
    2601             : // Do whatever tear-down is necessary after drawing to our offscreen FBO,
    2602             : // if it's bound.
    2603             : void
    2604           0 : GLContext::AfterGLDrawCall()
    2605             : {
    2606           0 :     if (mScreen) {
    2607           0 :         mScreen->AfterDrawCall();
    2608             :     }
    2609           0 :     mHeavyGLCallsSinceLastFlush = true;
    2610           0 : }
    2611             : 
    2612             : // Do whatever setup is necessary to read from our offscreen FBO, if it's
    2613             : // bound.
    2614             : void
    2615           0 : GLContext::BeforeGLReadCall()
    2616             : {
    2617           0 :     if (mScreen)
    2618           0 :         mScreen->BeforeReadCall();
    2619           0 : }
    2620             : 
    2621             : void
    2622           0 : GLContext::fBindFramebuffer(GLenum target, GLuint framebuffer)
    2623             : {
    2624           0 :     if (!mScreen) {
    2625           0 :         raw_fBindFramebuffer(target, framebuffer);
    2626           0 :         return;
    2627             :     }
    2628             : 
    2629           0 :     switch (target) {
    2630             :         case LOCAL_GL_DRAW_FRAMEBUFFER_EXT:
    2631           0 :             mScreen->BindDrawFB(framebuffer);
    2632           0 :             return;
    2633             : 
    2634             :         case LOCAL_GL_READ_FRAMEBUFFER_EXT:
    2635           0 :             mScreen->BindReadFB(framebuffer);
    2636           0 :             return;
    2637             : 
    2638             :         case LOCAL_GL_FRAMEBUFFER:
    2639           0 :             mScreen->BindFB(framebuffer);
    2640           0 :             return;
    2641             : 
    2642             :         default:
    2643             :             // Nothing we care about, likely an error.
    2644           0 :             break;
    2645             :     }
    2646             : 
    2647           0 :     raw_fBindFramebuffer(target, framebuffer);
    2648             : }
    2649             : 
    2650             : void
    2651           0 : GLContext::fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x,
    2652             :                            GLint y, GLsizei width, GLsizei height, GLint border)
    2653             : {
    2654           0 :     if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
    2655             :         // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
    2656             :         // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
    2657           0 :         level = -1;
    2658           0 :         width = -1;
    2659           0 :         height = -1;
    2660           0 :         border = -1;
    2661             :     }
    2662             : 
    2663           0 :     BeforeGLReadCall();
    2664           0 :     bool didCopyTexImage2D = false;
    2665           0 :     if (mScreen) {
    2666           0 :         didCopyTexImage2D = mScreen->CopyTexImage2D(target, level, internalformat, x,
    2667           0 :                                                     y, width, height, border);
    2668             :     }
    2669             : 
    2670           0 :     if (!didCopyTexImage2D) {
    2671             :         raw_fCopyTexImage2D(target, level, internalformat, x, y, width, height,
    2672           0 :                             border);
    2673             :     }
    2674           0 :     AfterGLReadCall();
    2675           0 : }
    2676             : 
    2677             : void
    2678           0 : GLContext::fGetIntegerv(GLenum pname, GLint* params)
    2679             : {
    2680           0 :     switch (pname) {
    2681             :         // LOCAL_GL_FRAMEBUFFER_BINDING is equal to
    2682             :         // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT,
    2683             :         // so we don't need two cases.
    2684             :         case LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT:
    2685           0 :             if (mScreen) {
    2686           0 :                 *params = mScreen->GetDrawFB();
    2687             :             } else {
    2688           0 :                 raw_fGetIntegerv(pname, params);
    2689             :             }
    2690           0 :             break;
    2691             : 
    2692             :         case LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT:
    2693           0 :             if (mScreen) {
    2694           0 :                 *params = mScreen->GetReadFB();
    2695             :             } else {
    2696           0 :                 raw_fGetIntegerv(pname, params);
    2697             :             }
    2698           0 :             break;
    2699             : 
    2700             :         case LOCAL_GL_MAX_TEXTURE_SIZE:
    2701           0 :             MOZ_ASSERT(mMaxTextureSize>0);
    2702           0 :             *params = mMaxTextureSize;
    2703           0 :             break;
    2704             : 
    2705             :         case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
    2706           0 :             MOZ_ASSERT(mMaxCubeMapTextureSize>0);
    2707           0 :             *params = mMaxCubeMapTextureSize;
    2708           0 :             break;
    2709             : 
    2710             :         case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
    2711           0 :             MOZ_ASSERT(mMaxRenderbufferSize>0);
    2712           0 :             *params = mMaxRenderbufferSize;
    2713           0 :             break;
    2714             : 
    2715             :         case LOCAL_GL_VIEWPORT:
    2716           0 :             for (size_t i = 0; i < 4; i++) {
    2717           0 :                 params[i] = mViewportRect[i];
    2718             :             }
    2719           0 :             break;
    2720             : 
    2721             :         case LOCAL_GL_SCISSOR_BOX:
    2722           0 :             for (size_t i = 0; i < 4; i++) {
    2723           0 :                 params[i] = mScissorRect[i];
    2724             :             }
    2725           0 :             break;
    2726             : 
    2727             :         default:
    2728           0 :             raw_fGetIntegerv(pname, params);
    2729           0 :             break;
    2730             :     }
    2731           0 : }
    2732             : 
    2733             : void
    2734           0 : GLContext::fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
    2735             :                        GLenum type, GLvoid* pixels)
    2736             : {
    2737           0 :     BeforeGLReadCall();
    2738             : 
    2739           0 :     bool didReadPixels = false;
    2740           0 :     if (mScreen) {
    2741           0 :         didReadPixels = mScreen->ReadPixels(x, y, width, height, format, type, pixels);
    2742             :     }
    2743             : 
    2744           0 :     if (!didReadPixels) {
    2745           0 :         raw_fReadPixels(x, y, width, height, format, type, pixels);
    2746             :     }
    2747             : 
    2748           0 :     AfterGLReadCall();
    2749             : 
    2750             :     // Check if GL is giving back 1.0 alpha for
    2751             :     // RGBA reads to RGBA images from no-alpha buffers.
    2752             : #ifdef XP_MACOSX
    2753             :     if (WorkAroundDriverBugs() &&
    2754             :         Vendor() == gl::GLVendor::NVIDIA &&
    2755             :         format == LOCAL_GL_RGBA &&
    2756             :         type == LOCAL_GL_UNSIGNED_BYTE &&
    2757             :         !IsCoreProfile() &&
    2758             :         width && height)
    2759             :     {
    2760             :         GLint alphaBits = 0;
    2761             :         fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits);
    2762             :         if (!alphaBits) {
    2763             :             const uint32_t alphaMask = 0xff000000;
    2764             : 
    2765             :             uint32_t* itr = (uint32_t*)pixels;
    2766             :             uint32_t testPixel = *itr;
    2767             :             if ((testPixel & alphaMask) != alphaMask) {
    2768             :                 // We need to set the alpha channel to 1.0 manually.
    2769             :                 uint32_t* itrEnd = itr + width*height;  // Stride is guaranteed to be width*4.
    2770             : 
    2771             :                 for (; itr != itrEnd; itr++) {
    2772             :                     *itr |= alphaMask;
    2773             :                 }
    2774             :             }
    2775             :         }
    2776             :     }
    2777             : #endif
    2778           0 : }
    2779             : 
    2780             : void
    2781           0 : GLContext::fDeleteFramebuffers(GLsizei n, const GLuint* names)
    2782             : {
    2783           0 :     if (mScreen) {
    2784             :         // Notify mScreen which framebuffers we're deleting.
    2785             :         // Otherwise, we will get framebuffer binding mispredictions.
    2786           0 :         for (int i = 0; i < n; i++) {
    2787           0 :             mScreen->DeletingFB(names[i]);
    2788             :         }
    2789             :     }
    2790             : 
    2791             :     // Avoid crash by flushing before glDeleteFramebuffers. See bug 1194923.
    2792           0 :     if (mNeedsFlushBeforeDeleteFB) {
    2793           0 :         fFlush();
    2794             :     }
    2795             : 
    2796           0 :     if (n == 1 && *names == 0) {
    2797             :         // Deleting framebuffer 0 causes hangs on the DROID. See bug 623228.
    2798             :     } else {
    2799           0 :         raw_fDeleteFramebuffers(n, names);
    2800             :     }
    2801           0 :     TRACKING_CONTEXT(DeletedFramebuffers(this, n, names));
    2802           0 : }
    2803             : 
    2804             : #ifdef MOZ_WIDGET_ANDROID
    2805             : /**
    2806             :  * Conservatively estimate whether there is enough available
    2807             :  * contiguous virtual address space to map a newly allocated texture.
    2808             :  */
    2809             : static bool
    2810             : WillTextureMapSucceed(GLsizei width, GLsizei height, GLenum format, GLenum type)
    2811             : {
    2812             :     bool willSucceed = false;
    2813             :     // Some drivers leave large gaps between textures, so require
    2814             :     // there to be double the actual size of the texture available.
    2815             :     size_t size = width * height * GetBytesPerTexel(format, type) * 2;
    2816             : 
    2817             :     void *p = mmap(nullptr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    2818             :     if (p != MAP_FAILED) {
    2819             :         willSucceed = true;
    2820             :         munmap(p, size);
    2821             :     }
    2822             : 
    2823             :     return willSucceed;
    2824             : }
    2825             : #endif // MOZ_WIDGET_ANDROID
    2826             : 
    2827             : void
    2828           0 : GLContext::fTexImage2D(GLenum target, GLint level, GLint internalformat,
    2829             :                        GLsizei width, GLsizei height, GLint border,
    2830             :                        GLenum format, GLenum type, const GLvoid* pixels) {
    2831           0 :     if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
    2832             :         // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
    2833             :         // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
    2834           0 :         level = -1;
    2835           0 :         width = -1;
    2836           0 :         height = -1;
    2837           0 :         border = -1;
    2838             :     }
    2839             : #if MOZ_WIDGET_ANDROID
    2840             :     if (mTextureAllocCrashesOnMapFailure) {
    2841             :         // We have no way of knowing whether this texture already has
    2842             :         // storage allocated for it, and therefore whether this check
    2843             :         // is necessary. We must therefore assume it does not and
    2844             :         // always perform the check.
    2845             :         if (!WillTextureMapSucceed(width, height, internalformat, type)) {
    2846             :             return;
    2847             :         }
    2848             :     }
    2849             : #endif
    2850           0 :     raw_fTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
    2851           0 : }
    2852             : 
    2853             : GLuint
    2854           0 : GLContext::GetDrawFB()
    2855             : {
    2856           0 :     if (mScreen)
    2857           0 :         return mScreen->GetDrawFB();
    2858             : 
    2859           0 :     GLuint ret = 0;
    2860           0 :     GetUIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, &ret);
    2861           0 :     return ret;
    2862             : }
    2863             : 
    2864             : GLuint
    2865           0 : GLContext::GetReadFB()
    2866             : {
    2867           0 :     if (mScreen)
    2868           0 :         return mScreen->GetReadFB();
    2869             : 
    2870           0 :     GLenum bindEnum = IsSupported(GLFeature::split_framebuffer)
    2871           0 :                         ? LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT
    2872           0 :                         : LOCAL_GL_FRAMEBUFFER_BINDING;
    2873             : 
    2874           0 :     GLuint ret = 0;
    2875           0 :     GetUIntegerv(bindEnum, &ret);
    2876           0 :     return ret;
    2877             : }
    2878             : 
    2879             : GLuint
    2880           0 : GLContext::GetFB()
    2881             : {
    2882           0 :     if (mScreen) {
    2883             :         // This has a very important extra assert that checks that we're
    2884             :         // not accidentally ignoring a situation where the draw and read
    2885             :         // FBs differ.
    2886           0 :         return mScreen->GetFB();
    2887             :     }
    2888             : 
    2889           0 :     GLuint ret = 0;
    2890           0 :     GetUIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &ret);
    2891           0 :     return ret;
    2892             : }
    2893             : 
    2894             : bool
    2895           0 : GLContext::InitOffscreen(const gfx::IntSize& size, const SurfaceCaps& caps)
    2896             : {
    2897           0 :     if (!CreateScreenBuffer(size, caps))
    2898           0 :         return false;
    2899             : 
    2900           0 :     MakeCurrent();
    2901           0 :     fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
    2902           0 :     fScissor(0, 0, size.width, size.height);
    2903           0 :     fViewport(0, 0, size.width, size.height);
    2904             : 
    2905           0 :     mCaps = mScreen->mCaps;
    2906           0 :     MOZ_ASSERT(!mCaps.any);
    2907             : 
    2908           0 :     return true;
    2909             : }
    2910             : 
    2911             : bool
    2912           0 : GLContext::IsDrawingToDefaultFramebuffer()
    2913             : {
    2914           0 :     return Screen()->IsDrawFramebufferDefault();
    2915             : }
    2916             : 
    2917             : GLuint
    2918           0 : CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat,
    2919             :               GLenum aType, const gfx::IntSize& aSize, bool linear)
    2920             : {
    2921           0 :     GLuint tex = 0;
    2922           0 :     aGL->fGenTextures(1, &tex);
    2923           0 :     ScopedBindTexture autoTex(aGL, tex);
    2924             : 
    2925           0 :     aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D,
    2926             :                         LOCAL_GL_TEXTURE_MIN_FILTER, linear ? LOCAL_GL_LINEAR
    2927           0 :                                                             : LOCAL_GL_NEAREST);
    2928           0 :     aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D,
    2929             :                         LOCAL_GL_TEXTURE_MAG_FILTER, linear ? LOCAL_GL_LINEAR
    2930           0 :                                                             : LOCAL_GL_NEAREST);
    2931             :     aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S,
    2932           0 :                         LOCAL_GL_CLAMP_TO_EDGE);
    2933             :     aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T,
    2934           0 :                         LOCAL_GL_CLAMP_TO_EDGE);
    2935             : 
    2936           0 :     aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
    2937             :                      0,
    2938             :                      aInternalFormat,
    2939           0 :                      aSize.width, aSize.height,
    2940             :                      0,
    2941             :                      aFormat,
    2942             :                      aType,
    2943           0 :                      nullptr);
    2944             : 
    2945           0 :     return tex;
    2946             : }
    2947             : 
    2948             : GLuint
    2949           0 : CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats,
    2950             :                           const gfx::IntSize& aSize)
    2951             : {
    2952           0 :     MOZ_ASSERT(aFormats.color_texInternalFormat);
    2953           0 :     MOZ_ASSERT(aFormats.color_texFormat);
    2954           0 :     MOZ_ASSERT(aFormats.color_texType);
    2955             : 
    2956           0 :     GLenum internalFormat = aFormats.color_texInternalFormat;
    2957           0 :     GLenum unpackFormat = aFormats.color_texFormat;
    2958           0 :     GLenum unpackType = aFormats.color_texType;
    2959           0 :     if (aGL->IsANGLE()) {
    2960           0 :         MOZ_ASSERT(internalFormat == LOCAL_GL_RGBA);
    2961           0 :         MOZ_ASSERT(unpackFormat == LOCAL_GL_RGBA);
    2962           0 :         MOZ_ASSERT(unpackType == LOCAL_GL_UNSIGNED_BYTE);
    2963           0 :         internalFormat = LOCAL_GL_BGRA_EXT;
    2964           0 :         unpackFormat = LOCAL_GL_BGRA_EXT;
    2965             :     }
    2966             : 
    2967           0 :     return CreateTexture(aGL, internalFormat, unpackFormat, unpackType, aSize);
    2968             : }
    2969             : 
    2970             : uint32_t
    2971           0 : GetBytesPerTexel(GLenum format, GLenum type)
    2972             : {
    2973             :     // If there is no defined format or type, we're not taking up any memory
    2974           0 :     if (!format || !type) {
    2975           0 :         return 0;
    2976             :     }
    2977             : 
    2978           0 :     if (format == LOCAL_GL_DEPTH_COMPONENT) {
    2979           0 :         if (type == LOCAL_GL_UNSIGNED_SHORT)
    2980           0 :             return 2;
    2981           0 :         else if (type == LOCAL_GL_UNSIGNED_INT)
    2982           0 :             return 4;
    2983           0 :     } else if (format == LOCAL_GL_DEPTH_STENCIL) {
    2984           0 :         if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
    2985           0 :             return 4;
    2986             :     }
    2987             : 
    2988           0 :     if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT || type == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV) {
    2989           0 :         uint32_t multiplier = type == LOCAL_GL_UNSIGNED_BYTE ? 1 : 4;
    2990           0 :         switch (format) {
    2991             :             case LOCAL_GL_ALPHA:
    2992             :             case LOCAL_GL_LUMINANCE:
    2993           0 :                 return 1 * multiplier;
    2994             :             case LOCAL_GL_LUMINANCE_ALPHA:
    2995           0 :                 return 2 * multiplier;
    2996             :             case LOCAL_GL_RGB:
    2997           0 :                 return 3 * multiplier;
    2998             :             case LOCAL_GL_RGBA:
    2999             :             case LOCAL_GL_BGRA_EXT:
    3000           0 :                 return 4 * multiplier;
    3001             :             default:
    3002           0 :                 break;
    3003           0 :         }
    3004           0 :     } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
    3005           0 :                type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
    3006             :                type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
    3007             :     {
    3008           0 :         return 2;
    3009             :     }
    3010             : 
    3011           0 :     gfxCriticalError() << "Unknown texture type " << type << " or format " << format;
    3012           0 :     return 0;
    3013             : }
    3014             : 
    3015           0 : bool GLContext::MakeCurrent(bool aForce)
    3016             : {
    3017           0 :     if (IsDestroyed())
    3018           0 :         return false;
    3019             : 
    3020             : #ifdef MOZ_GL_DEBUG
    3021           0 :     PR_SetThreadPrivate(sCurrentGLContextTLS, this);
    3022             : 
    3023             :     // XXX this assertion is disabled because it's triggering on Mac;
    3024             :     // we need to figure out why and reenable it.
    3025             : #if 0
    3026             :     // IsOwningThreadCurrent is a bit of a misnomer;
    3027             :     // the "owning thread" is the creation thread,
    3028             :     // and the only thread that can own this.  We don't
    3029             :     // support contexts used on multiple threads.
    3030             :     NS_ASSERTION(IsOwningThreadCurrent(),
    3031             :                  "MakeCurrent() called on different thread than this context was created on!");
    3032             : #endif
    3033             : #endif
    3034           0 :     if (mUseTLSIsCurrent && !aForce && sCurrentContext.get() == this) {
    3035           0 :         MOZ_ASSERT(IsCurrent());
    3036           0 :         return true;
    3037             :     }
    3038             : 
    3039           0 :     if (!MakeCurrentImpl(aForce))
    3040           0 :         return false;
    3041             : 
    3042           0 :     if (mUseTLSIsCurrent) {
    3043           0 :         sCurrentContext.set(this);
    3044             :     }
    3045             : 
    3046           0 :     return true;
    3047             : }
    3048             : 
    3049             : 
    3050             : } /* namespace gl */
    3051             : } /* namespace mozilla */

Generated by: LCOV version 1.13