gfx/gl/GLContext.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/gl/GLContext.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2038 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* vim: set ts=8 sts=4 et sw=4 tw=80: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include <algorithm>
    1.11 +#include <stdio.h>
    1.12 +#include <string.h>
    1.13 +#include <ctype.h>
    1.14 +
    1.15 +#include "GLContext.h"
    1.16 +#include "GLBlitHelper.h"
    1.17 +#include "GLBlitTextureImageHelper.h"
    1.18 +#include "GLReadTexImageHelper.h"
    1.19 +
    1.20 +#include "gfxCrashReporterUtils.h"
    1.21 +#include "gfxUtils.h"
    1.22 +#include "GLContextProvider.h"
    1.23 +#include "GLTextureImage.h"
    1.24 +#include "nsPrintfCString.h"
    1.25 +#include "nsThreadUtils.h"
    1.26 +#include "prenv.h"
    1.27 +#include "prlink.h"
    1.28 +#include "ScopedGLHelpers.h"
    1.29 +#include "SharedSurfaceGL.h"
    1.30 +#include "SurfaceStream.h"
    1.31 +#include "GfxTexturesReporter.h"
    1.32 +#include "TextureGarbageBin.h"
    1.33 +#include "gfx2DGlue.h"
    1.34 +#include "gfxPrefs.h"
    1.35 +
    1.36 +#include "OGLShaderProgram.h" // for ShaderProgramType
    1.37 +
    1.38 +#include "mozilla/DebugOnly.h"
    1.39 +
    1.40 +#ifdef XP_MACOSX
    1.41 +#include <CoreServices/CoreServices.h>
    1.42 +#include "gfxColor.h"
    1.43 +#endif
    1.44 +
    1.45 +#if defined(MOZ_WIDGET_COCOA)
    1.46 +#include "nsCocoaFeatures.h"
    1.47 +#endif
    1.48 +
    1.49 +using namespace mozilla::gfx;
    1.50 +using namespace mozilla::layers;
    1.51 +
    1.52 +namespace mozilla {
    1.53 +namespace gl {
    1.54 +
    1.55 +#ifdef DEBUG
    1.56 +unsigned GLContext::sCurrentGLContextTLS = -1;
    1.57 +#endif
    1.58 +
    1.59 +uint32_t GLContext::sDebugMode = 0;
    1.60 +
    1.61 +
    1.62 +#define MAX_SYMBOL_LENGTH 128
    1.63 +#define MAX_SYMBOL_NAMES 5
    1.64 +
    1.65 +// should match the order of GLExtensions, and be null-terminated.
    1.66 +static const char *sExtensionNames[] = {
    1.67 +    "GL_EXT_framebuffer_object",
    1.68 +    "GL_ARB_framebuffer_object",
    1.69 +    "GL_ARB_texture_rectangle",
    1.70 +    "GL_EXT_bgra",
    1.71 +    "GL_EXT_texture_format_BGRA8888",
    1.72 +    "GL_OES_depth24",
    1.73 +    "GL_OES_depth32",
    1.74 +    "GL_OES_stencil8",
    1.75 +    "GL_OES_texture_npot",
    1.76 +    "GL_ARB_depth_texture",
    1.77 +    "GL_OES_depth_texture",
    1.78 +    "GL_OES_packed_depth_stencil",
    1.79 +    "GL_IMG_read_format",
    1.80 +    "GL_EXT_read_format_bgra",
    1.81 +    "GL_APPLE_client_storage",
    1.82 +    "GL_APPLE_texture_range",
    1.83 +    "GL_ARB_texture_non_power_of_two",
    1.84 +    "GL_ARB_pixel_buffer_object",
    1.85 +    "GL_ARB_ES2_compatibility",
    1.86 +    "GL_ARB_ES3_compatibility",
    1.87 +    "GL_OES_texture_float",
    1.88 +    "GL_OES_texture_float_linear",
    1.89 +    "GL_ARB_texture_float",
    1.90 +    "GL_OES_texture_half_float",
    1.91 +    "GL_OES_texture_half_float_linear",
    1.92 +    "GL_NV_half_float",
    1.93 +    "GL_EXT_color_buffer_float",
    1.94 +    "GL_EXT_color_buffer_half_float",
    1.95 +    "GL_ARB_color_buffer_float",
    1.96 +    "GL_EXT_unpack_subimage",
    1.97 +    "GL_OES_standard_derivatives",
    1.98 +    "GL_EXT_texture_filter_anisotropic",
    1.99 +    "GL_EXT_texture_compression_s3tc",
   1.100 +    "GL_EXT_texture_compression_dxt1",
   1.101 +    "GL_ANGLE_texture_compression_dxt3",
   1.102 +    "GL_ANGLE_texture_compression_dxt5",
   1.103 +    "GL_AMD_compressed_ATC_texture",
   1.104 +    "GL_IMG_texture_compression_pvrtc",
   1.105 +    "GL_EXT_framebuffer_blit",
   1.106 +    "GL_ANGLE_framebuffer_blit",
   1.107 +    "GL_EXT_framebuffer_multisample",
   1.108 +    "GL_ANGLE_framebuffer_multisample",
   1.109 +    "GL_OES_rgb8_rgba8",
   1.110 +    "GL_ARB_robustness",
   1.111 +    "GL_EXT_robustness",
   1.112 +    "GL_ARB_sync",
   1.113 +    "GL_OES_EGL_image",
   1.114 +    "GL_OES_EGL_sync",
   1.115 +    "GL_OES_EGL_image_external",
   1.116 +    "GL_EXT_packed_depth_stencil",
   1.117 +    "GL_OES_element_index_uint",
   1.118 +    "GL_OES_vertex_array_object",
   1.119 +    "GL_ARB_vertex_array_object",
   1.120 +    "GL_APPLE_vertex_array_object",
   1.121 +    "GL_ARB_draw_buffers",
   1.122 +    "GL_EXT_draw_buffers",
   1.123 +    "GL_EXT_gpu_shader4",
   1.124 +    "GL_EXT_blend_minmax",
   1.125 +    "GL_ARB_draw_instanced",
   1.126 +    "GL_EXT_draw_instanced",
   1.127 +    "GL_NV_draw_instanced",
   1.128 +    "GL_ARB_instanced_arrays",
   1.129 +    "GL_NV_instanced_arrays",
   1.130 +    "GL_ANGLE_instanced_arrays",
   1.131 +    "GL_EXT_occlusion_query_boolean",
   1.132 +    "GL_ARB_occlusion_query2",
   1.133 +    "GL_EXT_transform_feedback",
   1.134 +    "GL_NV_transform_feedback",
   1.135 +    "GL_ANGLE_depth_texture",
   1.136 +    "GL_EXT_sRGB",
   1.137 +    "GL_EXT_texture_sRGB",
   1.138 +    "GL_ARB_framebuffer_sRGB",
   1.139 +    "GL_EXT_framebuffer_sRGB",
   1.140 +    "GL_KHR_debug",
   1.141 +    "GL_ARB_half_float_pixel",
   1.142 +    "GL_EXT_frag_depth",
   1.143 +    "GL_OES_compressed_ETC1_RGB8_texture",
   1.144 +    "GL_EXT_draw_range_elements",
   1.145 +    nullptr
   1.146 +};
   1.147 +
   1.148 +static bool
   1.149 +ParseGLVersion(GLContext* gl, unsigned int* version)
   1.150 +{
   1.151 +    GLenum error = gl->fGetError();
   1.152 +    if (error != LOCAL_GL_NO_ERROR) {
   1.153 +        MOZ_ASSERT(false, "An OpenGL error has been triggered before.");
   1.154 +        return false;
   1.155 +    }
   1.156 +
   1.157 +    /**
   1.158 +     * B2G emulator bug work around: The emulator implements OpenGL ES 2.0 on
   1.159 +     * OpenGL 3.2. The bug is that GetIntegerv(LOCAL_GL_{MAJOR,MINOR}_VERSION)
   1.160 +     * returns OpenGL 3.2 instead of generating an error.
   1.161 +     */
   1.162 +    if (!gl->IsGLES())
   1.163 +    {
   1.164 +        /**
   1.165 +         * OpenGL 3.1 and OpenGL ES 3.0 both introduce GL_{MAJOR,MINOR}_VERSION
   1.166 +         * with GetIntegerv. So we first try those constants even though we
   1.167 +         * might not have an OpenGL context supporting them, has this is a
   1.168 +         * better way than parsing GL_VERSION.
   1.169 +         */
   1.170 +        GLint majorVersion = 0;
   1.171 +        GLint minorVersion = 0;
   1.172 +
   1.173 +        gl->fGetIntegerv(LOCAL_GL_MAJOR_VERSION, &majorVersion);
   1.174 +        gl->fGetIntegerv(LOCAL_GL_MINOR_VERSION, &minorVersion);
   1.175 +
   1.176 +        // If it's not an OpenGL (ES) 3.0 context, we will have an error
   1.177 +        error = gl->fGetError();
   1.178 +        if (error == LOCAL_GL_NO_ERROR &&
   1.179 +            majorVersion > 0 &&
   1.180 +            minorVersion >= 0)
   1.181 +        {
   1.182 +            *version = majorVersion * 100 + minorVersion * 10;
   1.183 +            return true;
   1.184 +        }
   1.185 +    }
   1.186 +
   1.187 +    /**
   1.188 +     * We were not able to use GL_{MAJOR,MINOR}_VERSION, so we parse
   1.189 +     * GL_VERSION.
   1.190 +     *
   1.191 +     *
   1.192 +     * OpenGL 2.x, 3.x, 4.x specifications:
   1.193 +     *  The VERSION and SHADING_LANGUAGE_VERSION strings are laid out as follows:
   1.194 +     *
   1.195 +     *    <version number><space><vendor-specific information>
   1.196 +     *
   1.197 +     *  The version number is either of the form major_number.minor_number or
   1.198 +     *  major_number.minor_number.release_number, where the numbers all have
   1.199 +     *  one or more digits.
   1.200 +     *
   1.201 +     *
   1.202 +     * OpenGL ES 2.0, 3.0 specifications:
   1.203 +     *  The VERSION string is laid out as follows:
   1.204 +     *
   1.205 +     *     "OpenGL ES N.M vendor-specific information"
   1.206 +     *
   1.207 +     *  The version number is either of the form major_number.minor_number or
   1.208 +     *  major_number.minor_number.release_number, where the numbers all have
   1.209 +     *  one or more digits.
   1.210 +     *
   1.211 +     *
   1.212 +     * Note:
   1.213 +     *  We don't care about release_number.
   1.214 +     */
   1.215 +    const char* versionString = (const char*)gl->fGetString(LOCAL_GL_VERSION);
   1.216 +
   1.217 +    error = gl->fGetError();
   1.218 +    if (error != LOCAL_GL_NO_ERROR) {
   1.219 +        MOZ_ASSERT(false, "glGetString(GL_VERSION) has generated an error");
   1.220 +        return false;
   1.221 +    } else if (!versionString) {
   1.222 +        MOZ_ASSERT(false, "glGetString(GL_VERSION) has returned 0");
   1.223 +        return false;
   1.224 +    }
   1.225 +
   1.226 +    const char kGLESVersionPrefix[] = "OpenGL ES ";
   1.227 +    if (strncmp(versionString, kGLESVersionPrefix, strlen(kGLESVersionPrefix)) == 0) {
   1.228 +        versionString += strlen(kGLESVersionPrefix);
   1.229 +    }
   1.230 +
   1.231 +    const char* itr = versionString;
   1.232 +    char* end = nullptr;
   1.233 +    int majorVersion = (int)strtol(itr, &end, 10);
   1.234 +
   1.235 +    if (!end) {
   1.236 +        MOZ_ASSERT(false, "Failed to parse the GL major version number.");
   1.237 +        return false;
   1.238 +    } else if (*end != '.') {
   1.239 +        MOZ_ASSERT(false, "Failed to parse GL's major-minor version number separator.");
   1.240 +        return false;
   1.241 +    }
   1.242 +
   1.243 +    // we skip the '.' between the major and the minor version
   1.244 +    itr = end + 1;
   1.245 +
   1.246 +    end = nullptr;
   1.247 +
   1.248 +    int minorVersion = (int)strtol(itr, &end, 10);
   1.249 +    if (!end) {
   1.250 +        MOZ_ASSERT(false, "Failed to parse GL's minor version number.");
   1.251 +        return false;
   1.252 +    }
   1.253 +
   1.254 +    if (majorVersion <= 0 || majorVersion >= 100) {
   1.255 +        MOZ_ASSERT(false, "Invalid major version.");
   1.256 +        return false;
   1.257 +    } else if (minorVersion < 0 || minorVersion >= 10) {
   1.258 +        MOZ_ASSERT(false, "Invalid minor version.");
   1.259 +        return false;
   1.260 +    }
   1.261 +
   1.262 +    *version = (unsigned int)(majorVersion * 100 + minorVersion * 10);
   1.263 +    return true;
   1.264 +}
   1.265 +
   1.266 +GLContext::GLContext(const SurfaceCaps& caps,
   1.267 +          GLContext* sharedContext,
   1.268 +          bool isOffscreen)
   1.269 +  : mInitialized(false),
   1.270 +    mIsOffscreen(isOffscreen),
   1.271 +    mContextLost(false),
   1.272 +    mVersion(0),
   1.273 +    mProfile(ContextProfile::Unknown),
   1.274 +    mVendor(GLVendor::Other),
   1.275 +    mRenderer(GLRenderer::Other),
   1.276 +    mHasRobustness(false),
   1.277 +#ifdef DEBUG
   1.278 +    mGLError(LOCAL_GL_NO_ERROR),
   1.279 +#endif
   1.280 +    mSharedContext(sharedContext),
   1.281 +    mCaps(caps),
   1.282 +    mScreen(nullptr),
   1.283 +    mLockedSurface(nullptr),
   1.284 +    mMaxTextureSize(0),
   1.285 +    mMaxCubeMapTextureSize(0),
   1.286 +    mMaxTextureImageSize(0),
   1.287 +    mMaxRenderbufferSize(0),
   1.288 +    mNeedsTextureSizeChecks(false),
   1.289 +    mWorkAroundDriverBugs(true)
   1.290 +{
   1.291 +    mOwningThread = NS_GetCurrentThread();
   1.292 +}
   1.293 +
   1.294 +GLContext::~GLContext() {
   1.295 +    NS_ASSERTION(IsDestroyed(), "GLContext implementation must call MarkDestroyed in destructor!");
   1.296 +#ifdef DEBUG
   1.297 +    if (mSharedContext) {
   1.298 +        GLContext *tip = mSharedContext;
   1.299 +        while (tip->mSharedContext)
   1.300 +            tip = tip->mSharedContext;
   1.301 +        tip->SharedContextDestroyed(this);
   1.302 +        tip->ReportOutstandingNames();
   1.303 +    } else {
   1.304 +        ReportOutstandingNames();
   1.305 +    }
   1.306 +#endif
   1.307 +}
   1.308 +
   1.309 +bool
   1.310 +GLContext::InitWithPrefix(const char *prefix, bool trygl)
   1.311 +{
   1.312 +    ScopedGfxFeatureReporter reporter("GL Context");
   1.313 +
   1.314 +    if (mInitialized) {
   1.315 +        reporter.SetSuccessful();
   1.316 +        return true;
   1.317 +    }
   1.318 +
   1.319 +    mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs();
   1.320 +
   1.321 +    SymLoadStruct symbols[] = {
   1.322 +        { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } },
   1.323 +        { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } },
   1.324 +        { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } },
   1.325 +        { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } },
   1.326 +        { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } },
   1.327 +        { (PRFuncPtr*) &mSymbols.fBlendColor, { "BlendColor", nullptr } },
   1.328 +        { (PRFuncPtr*) &mSymbols.fBlendEquation, { "BlendEquation", nullptr } },
   1.329 +        { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, { "BlendEquationSeparate", "BlendEquationSeparateEXT", nullptr } },
   1.330 +        { (PRFuncPtr*) &mSymbols.fBlendFunc, { "BlendFunc", nullptr } },
   1.331 +        { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, { "BlendFuncSeparate", "BlendFuncSeparateEXT", nullptr } },
   1.332 +        { (PRFuncPtr*) &mSymbols.fBufferData, { "BufferData", nullptr } },
   1.333 +        { (PRFuncPtr*) &mSymbols.fBufferSubData, { "BufferSubData", nullptr } },
   1.334 +        { (PRFuncPtr*) &mSymbols.fClear, { "Clear", nullptr } },
   1.335 +        { (PRFuncPtr*) &mSymbols.fClearColor, { "ClearColor", nullptr } },
   1.336 +        { (PRFuncPtr*) &mSymbols.fClearStencil, { "ClearStencil", nullptr } },
   1.337 +        { (PRFuncPtr*) &mSymbols.fColorMask, { "ColorMask", nullptr } },
   1.338 +        { (PRFuncPtr*) &mSymbols.fCompressedTexImage2D, {"CompressedTexImage2D", nullptr} },
   1.339 +        { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage2D, {"CompressedTexSubImage2D", nullptr} },
   1.340 +        { (PRFuncPtr*) &mSymbols.fCullFace, { "CullFace", nullptr } },
   1.341 +        { (PRFuncPtr*) &mSymbols.fDetachShader, { "DetachShader", "DetachShaderARB", nullptr } },
   1.342 +        { (PRFuncPtr*) &mSymbols.fDepthFunc, { "DepthFunc", nullptr } },
   1.343 +        { (PRFuncPtr*) &mSymbols.fDepthMask, { "DepthMask", nullptr } },
   1.344 +        { (PRFuncPtr*) &mSymbols.fDisable, { "Disable", nullptr } },
   1.345 +        { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, { "DisableVertexAttribArray", "DisableVertexAttribArrayARB", nullptr } },
   1.346 +        { (PRFuncPtr*) &mSymbols.fDrawArrays, { "DrawArrays", nullptr } },
   1.347 +        { (PRFuncPtr*) &mSymbols.fDrawElements, { "DrawElements", nullptr } },
   1.348 +        { (PRFuncPtr*) &mSymbols.fEnable, { "Enable", nullptr } },
   1.349 +        { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, { "EnableVertexAttribArray", "EnableVertexAttribArrayARB", nullptr } },
   1.350 +        { (PRFuncPtr*) &mSymbols.fFinish, { "Finish", nullptr } },
   1.351 +        { (PRFuncPtr*) &mSymbols.fFlush, { "Flush", nullptr } },
   1.352 +        { (PRFuncPtr*) &mSymbols.fFrontFace, { "FrontFace", nullptr } },
   1.353 +        { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, { "GetActiveAttrib", "GetActiveAttribARB", nullptr } },
   1.354 +        { (PRFuncPtr*) &mSymbols.fGetActiveUniform, { "GetActiveUniform", "GetActiveUniformARB", nullptr } },
   1.355 +        { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, { "GetAttachedShaders", "GetAttachedShadersARB", nullptr } },
   1.356 +        { (PRFuncPtr*) &mSymbols.fGetAttribLocation, { "GetAttribLocation", "GetAttribLocationARB", nullptr } },
   1.357 +        { (PRFuncPtr*) &mSymbols.fGetIntegerv, { "GetIntegerv", nullptr } },
   1.358 +        { (PRFuncPtr*) &mSymbols.fGetFloatv, { "GetFloatv", nullptr } },
   1.359 +        { (PRFuncPtr*) &mSymbols.fGetBooleanv, { "GetBooleanv", nullptr } },
   1.360 +        { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, { "GetBufferParameteriv", "GetBufferParameterivARB", nullptr } },
   1.361 +        { (PRFuncPtr*) &mSymbols.fGetError, { "GetError", nullptr } },
   1.362 +        { (PRFuncPtr*) &mSymbols.fGetProgramiv, { "GetProgramiv", "GetProgramivARB", nullptr } },
   1.363 +        { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, { "GetProgramInfoLog", "GetProgramInfoLogARB", nullptr } },
   1.364 +        { (PRFuncPtr*) &mSymbols.fTexParameteri, { "TexParameteri", nullptr } },
   1.365 +        { (PRFuncPtr*) &mSymbols.fTexParameteriv, { "TexParameteriv", nullptr } },
   1.366 +        { (PRFuncPtr*) &mSymbols.fTexParameterf, { "TexParameterf", nullptr } },
   1.367 +        { (PRFuncPtr*) &mSymbols.fGetString, { "GetString", nullptr } },
   1.368 +        { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, { "GetTexParameterfv", nullptr } },
   1.369 +        { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, { "GetTexParameteriv", nullptr } },
   1.370 +        { (PRFuncPtr*) &mSymbols.fGetUniformfv, { "GetUniformfv", "GetUniformfvARB", nullptr } },
   1.371 +        { (PRFuncPtr*) &mSymbols.fGetUniformiv, { "GetUniformiv", "GetUniformivARB", nullptr } },
   1.372 +        { (PRFuncPtr*) &mSymbols.fGetUniformLocation, { "GetUniformLocation", "GetUniformLocationARB", nullptr } },
   1.373 +        { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, { "GetVertexAttribfv", "GetVertexAttribfvARB", nullptr } },
   1.374 +        { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, { "GetVertexAttribiv", "GetVertexAttribivARB", nullptr } },
   1.375 +        { (PRFuncPtr*) &mSymbols.fGetVertexAttribPointerv, { "GetVertexAttribPointerv", nullptr } },
   1.376 +        { (PRFuncPtr*) &mSymbols.fHint, { "Hint", nullptr } },
   1.377 +        { (PRFuncPtr*) &mSymbols.fIsBuffer, { "IsBuffer", "IsBufferARB", nullptr } },
   1.378 +        { (PRFuncPtr*) &mSymbols.fIsEnabled, { "IsEnabled", nullptr } },
   1.379 +        { (PRFuncPtr*) &mSymbols.fIsProgram, { "IsProgram", "IsProgramARB", nullptr } },
   1.380 +        { (PRFuncPtr*) &mSymbols.fIsShader, { "IsShader", "IsShaderARB", nullptr } },
   1.381 +        { (PRFuncPtr*) &mSymbols.fIsTexture, { "IsTexture", "IsTextureARB", nullptr } },
   1.382 +        { (PRFuncPtr*) &mSymbols.fLineWidth, { "LineWidth", nullptr } },
   1.383 +        { (PRFuncPtr*) &mSymbols.fLinkProgram, { "LinkProgram", "LinkProgramARB", nullptr } },
   1.384 +        { (PRFuncPtr*) &mSymbols.fPixelStorei, { "PixelStorei", nullptr } },
   1.385 +        { (PRFuncPtr*) &mSymbols.fPolygonOffset, { "PolygonOffset", nullptr } },
   1.386 +        { (PRFuncPtr*) &mSymbols.fReadPixels, { "ReadPixels", nullptr } },
   1.387 +        { (PRFuncPtr*) &mSymbols.fSampleCoverage, { "SampleCoverage", nullptr } },
   1.388 +        { (PRFuncPtr*) &mSymbols.fScissor, { "Scissor", nullptr } },
   1.389 +        { (PRFuncPtr*) &mSymbols.fStencilFunc, { "StencilFunc", nullptr } },
   1.390 +        { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, { "StencilFuncSeparate", "StencilFuncSeparateEXT", nullptr } },
   1.391 +        { (PRFuncPtr*) &mSymbols.fStencilMask, { "StencilMask", nullptr } },
   1.392 +        { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, { "StencilMaskSeparate", "StencilMaskSeparateEXT", nullptr } },
   1.393 +        { (PRFuncPtr*) &mSymbols.fStencilOp, { "StencilOp", nullptr } },
   1.394 +        { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, { "StencilOpSeparate", "StencilOpSeparateEXT", nullptr } },
   1.395 +        { (PRFuncPtr*) &mSymbols.fTexImage2D, { "TexImage2D", nullptr } },
   1.396 +        { (PRFuncPtr*) &mSymbols.fTexSubImage2D, { "TexSubImage2D", nullptr } },
   1.397 +        { (PRFuncPtr*) &mSymbols.fUniform1f, { "Uniform1f", nullptr } },
   1.398 +        { (PRFuncPtr*) &mSymbols.fUniform1fv, { "Uniform1fv", nullptr } },
   1.399 +        { (PRFuncPtr*) &mSymbols.fUniform1i, { "Uniform1i", nullptr } },
   1.400 +        { (PRFuncPtr*) &mSymbols.fUniform1iv, { "Uniform1iv", nullptr } },
   1.401 +        { (PRFuncPtr*) &mSymbols.fUniform2f, { "Uniform2f", nullptr } },
   1.402 +        { (PRFuncPtr*) &mSymbols.fUniform2fv, { "Uniform2fv", nullptr } },
   1.403 +        { (PRFuncPtr*) &mSymbols.fUniform2i, { "Uniform2i", nullptr } },
   1.404 +        { (PRFuncPtr*) &mSymbols.fUniform2iv, { "Uniform2iv", nullptr } },
   1.405 +        { (PRFuncPtr*) &mSymbols.fUniform3f, { "Uniform3f", nullptr } },
   1.406 +        { (PRFuncPtr*) &mSymbols.fUniform3fv, { "Uniform3fv", nullptr } },
   1.407 +        { (PRFuncPtr*) &mSymbols.fUniform3i, { "Uniform3i", nullptr } },
   1.408 +        { (PRFuncPtr*) &mSymbols.fUniform3iv, { "Uniform3iv", nullptr } },
   1.409 +        { (PRFuncPtr*) &mSymbols.fUniform4f, { "Uniform4f", nullptr } },
   1.410 +        { (PRFuncPtr*) &mSymbols.fUniform4fv, { "Uniform4fv", nullptr } },
   1.411 +        { (PRFuncPtr*) &mSymbols.fUniform4i, { "Uniform4i", nullptr } },
   1.412 +        { (PRFuncPtr*) &mSymbols.fUniform4iv, { "Uniform4iv", nullptr } },
   1.413 +        { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, { "UniformMatrix2fv", nullptr } },
   1.414 +        { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, { "UniformMatrix3fv", nullptr } },
   1.415 +        { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, { "UniformMatrix4fv", nullptr } },
   1.416 +        { (PRFuncPtr*) &mSymbols.fUseProgram, { "UseProgram", nullptr } },
   1.417 +        { (PRFuncPtr*) &mSymbols.fValidateProgram, { "ValidateProgram", nullptr } },
   1.418 +        { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
   1.419 +        { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, { "VertexAttrib1f", nullptr } },
   1.420 +        { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, { "VertexAttrib2f", nullptr } },
   1.421 +        { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, { "VertexAttrib3f", nullptr } },
   1.422 +        { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, { "VertexAttrib4f", nullptr } },
   1.423 +        { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, { "VertexAttrib1fv", nullptr } },
   1.424 +        { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, { "VertexAttrib2fv", nullptr } },
   1.425 +        { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, { "VertexAttrib3fv", nullptr } },
   1.426 +        { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, { "VertexAttrib4fv", nullptr } },
   1.427 +        { (PRFuncPtr*) &mSymbols.fViewport, { "Viewport", nullptr } },
   1.428 +        { (PRFuncPtr*) &mSymbols.fCompileShader, { "CompileShader", nullptr } },
   1.429 +        { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, { "CopyTexImage2D", nullptr } },
   1.430 +        { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, { "CopyTexSubImage2D", nullptr } },
   1.431 +        { (PRFuncPtr*) &mSymbols.fGetShaderiv, { "GetShaderiv", nullptr } },
   1.432 +        { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, { "GetShaderInfoLog", nullptr } },
   1.433 +        { (PRFuncPtr*) &mSymbols.fGetShaderSource, { "GetShaderSource", nullptr } },
   1.434 +        { (PRFuncPtr*) &mSymbols.fShaderSource, { "ShaderSource", nullptr } },
   1.435 +        { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
   1.436 +        { (PRFuncPtr*) &mSymbols.fBindFramebuffer, { "BindFramebuffer", "BindFramebufferEXT", nullptr } },
   1.437 +        { (PRFuncPtr*) &mSymbols.fBindRenderbuffer, { "BindRenderbuffer", "BindRenderbufferEXT", nullptr } },
   1.438 +        { (PRFuncPtr*) &mSymbols.fCheckFramebufferStatus, { "CheckFramebufferStatus", "CheckFramebufferStatusEXT", nullptr } },
   1.439 +        { (PRFuncPtr*) &mSymbols.fFramebufferRenderbuffer, { "FramebufferRenderbuffer", "FramebufferRenderbufferEXT", nullptr } },
   1.440 +        { (PRFuncPtr*) &mSymbols.fFramebufferTexture2D, { "FramebufferTexture2D", "FramebufferTexture2DEXT", nullptr } },
   1.441 +        { (PRFuncPtr*) &mSymbols.fGenerateMipmap, { "GenerateMipmap", "GenerateMipmapEXT", nullptr } },
   1.442 +        { (PRFuncPtr*) &mSymbols.fGetFramebufferAttachmentParameteriv, { "GetFramebufferAttachmentParameteriv", "GetFramebufferAttachmentParameterivEXT", nullptr } },
   1.443 +        { (PRFuncPtr*) &mSymbols.fGetRenderbufferParameteriv, { "GetRenderbufferParameteriv", "GetRenderbufferParameterivEXT", nullptr } },
   1.444 +        { (PRFuncPtr*) &mSymbols.fIsFramebuffer, { "IsFramebuffer", "IsFramebufferEXT", nullptr } },
   1.445 +        { (PRFuncPtr*) &mSymbols.fIsRenderbuffer, { "IsRenderbuffer", "IsRenderbufferEXT", nullptr } },
   1.446 +        { (PRFuncPtr*) &mSymbols.fRenderbufferStorage, { "RenderbufferStorage", "RenderbufferStorageEXT", nullptr } },
   1.447 +
   1.448 +        { (PRFuncPtr*) &mSymbols.fGenBuffers, { "GenBuffers", "GenBuffersARB", nullptr } },
   1.449 +        { (PRFuncPtr*) &mSymbols.fGenTextures, { "GenTextures", nullptr } },
   1.450 +        { (PRFuncPtr*) &mSymbols.fCreateProgram, { "CreateProgram", "CreateProgramARB", nullptr } },
   1.451 +        { (PRFuncPtr*) &mSymbols.fCreateShader, { "CreateShader", "CreateShaderARB", nullptr } },
   1.452 +        { (PRFuncPtr*) &mSymbols.fGenFramebuffers, { "GenFramebuffers", "GenFramebuffersEXT", nullptr } },
   1.453 +        { (PRFuncPtr*) &mSymbols.fGenRenderbuffers, { "GenRenderbuffers", "GenRenderbuffersEXT", nullptr } },
   1.454 +
   1.455 +        { (PRFuncPtr*) &mSymbols.fDeleteBuffers, { "DeleteBuffers", "DeleteBuffersARB", nullptr } },
   1.456 +        { (PRFuncPtr*) &mSymbols.fDeleteTextures, { "DeleteTextures", "DeleteTexturesARB", nullptr } },
   1.457 +        { (PRFuncPtr*) &mSymbols.fDeleteProgram, { "DeleteProgram", "DeleteProgramARB", nullptr } },
   1.458 +        { (PRFuncPtr*) &mSymbols.fDeleteShader, { "DeleteShader", "DeleteShaderARB", nullptr } },
   1.459 +        { (PRFuncPtr*) &mSymbols.fDeleteFramebuffers, { "DeleteFramebuffers", "DeleteFramebuffersEXT", nullptr } },
   1.460 +        { (PRFuncPtr*) &mSymbols.fDeleteRenderbuffers, { "DeleteRenderbuffers", "DeleteRenderbuffersEXT", nullptr } },
   1.461 +
   1.462 +        { nullptr, { nullptr } },
   1.463 +
   1.464 +    };
   1.465 +
   1.466 +    mInitialized = LoadSymbols(&symbols[0], trygl, prefix);
   1.467 +    MakeCurrent();
   1.468 +    if (mInitialized) {
   1.469 +        unsigned int version = 0;
   1.470 +
   1.471 +        ParseGLVersion(this, &version);
   1.472 +
   1.473 +#ifdef DEBUG
   1.474 +        printf_stderr("OpenGL version detected: %u\n", version);
   1.475 +        printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR));
   1.476 +        printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER));
   1.477 +#endif
   1.478 +
   1.479 +        if (version >= mVersion) {
   1.480 +            mVersion = version;
   1.481 +        }
   1.482 +        // Don't fail if version < mVersion, see bug 999445,
   1.483 +        // Mac OSX 10.6/10.7 machines with Intel GPUs claim only OpenGL 1.4 but
   1.484 +        // have all the GL2+ extensions that we need.
   1.485 +    }
   1.486 +
   1.487 +    // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
   1.488 +    if (mInitialized) {
   1.489 +        if (IsGLES()) {
   1.490 +            SymLoadStruct symbols_ES2[] = {
   1.491 +                { (PRFuncPtr*) &mSymbols.fGetShaderPrecisionFormat, { "GetShaderPrecisionFormat", nullptr } },
   1.492 +                { (PRFuncPtr*) &mSymbols.fClearDepthf, { "ClearDepthf", nullptr } },
   1.493 +                { (PRFuncPtr*) &mSymbols.fDepthRangef, { "DepthRangef", nullptr } },
   1.494 +                { nullptr, { nullptr } },
   1.495 +            };
   1.496 +
   1.497 +            if (!LoadSymbols(&symbols_ES2[0], trygl, prefix)) {
   1.498 +                NS_ERROR("OpenGL ES 2.0 supported, but symbols could not be loaded.");
   1.499 +                mInitialized = false;
   1.500 +            }
   1.501 +        } else {
   1.502 +            SymLoadStruct symbols_desktop[] = {
   1.503 +                { (PRFuncPtr*) &mSymbols.fClearDepth, { "ClearDepth", nullptr } },
   1.504 +                { (PRFuncPtr*) &mSymbols.fDepthRange, { "DepthRange", nullptr } },
   1.505 +                { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } },
   1.506 +                { (PRFuncPtr*) &mSymbols.fMapBuffer, { "MapBuffer", nullptr } },
   1.507 +                { (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", nullptr } },
   1.508 +                { (PRFuncPtr*) &mSymbols.fPointParameterf, { "PointParameterf", nullptr } },
   1.509 +                { (PRFuncPtr*) &mSymbols.fDrawBuffer, { "DrawBuffer", nullptr } },
   1.510 +                    // These functions are only used by Skia/GL in desktop mode.
   1.511 +                    // Other parts of Gecko should avoid using these
   1.512 +                    { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
   1.513 +                    { (PRFuncPtr*) &mSymbols.fClientActiveTexture, { "ClientActiveTexture", nullptr } },
   1.514 +                    { (PRFuncPtr*) &mSymbols.fDisableClientState, { "DisableClientState", nullptr } },
   1.515 +                    { (PRFuncPtr*) &mSymbols.fEnableClientState, { "EnableClientState", nullptr } },
   1.516 +                    { (PRFuncPtr*) &mSymbols.fLoadIdentity, { "LoadIdentity", nullptr } },
   1.517 +                    { (PRFuncPtr*) &mSymbols.fLoadMatrixf, { "LoadMatrixf", nullptr } },
   1.518 +                    { (PRFuncPtr*) &mSymbols.fMatrixMode, { "MatrixMode", nullptr } },
   1.519 +                    { (PRFuncPtr*) &mSymbols.fTexGeni, { "TexGeni", nullptr } },
   1.520 +                    { (PRFuncPtr*) &mSymbols.fTexGenf, { "TexGenf", nullptr } },
   1.521 +                    { (PRFuncPtr*) &mSymbols.fTexGenfv, { "TexGenfv", nullptr } },
   1.522 +                    { (PRFuncPtr*) &mSymbols.fVertexPointer, { "VertexPointer", nullptr } },
   1.523 +                { nullptr, { nullptr } },
   1.524 +            };
   1.525 +
   1.526 +            if (!LoadSymbols(&symbols_desktop[0], trygl, prefix)) {
   1.527 +                NS_ERROR("Desktop symbols failed to load.");
   1.528 +                mInitialized = false;
   1.529 +            }
   1.530 +        }
   1.531 +    }
   1.532 +
   1.533 +    const char *glVendorString = nullptr;
   1.534 +    const char *glRendererString = nullptr;
   1.535 +
   1.536 +    if (mInitialized) {
   1.537 +        // The order of these strings must match up with the order of the enum
   1.538 +        // defined in GLContext.h for vendor IDs
   1.539 +        glVendorString = (const char *)fGetString(LOCAL_GL_VENDOR);
   1.540 +        if (!glVendorString)
   1.541 +            mInitialized = false;
   1.542 +
   1.543 +        const char *vendorMatchStrings[size_t(GLVendor::Other)] = {
   1.544 +                "Intel",
   1.545 +                "NVIDIA",
   1.546 +                "ATI",
   1.547 +                "Qualcomm",
   1.548 +                "Imagination",
   1.549 +                "nouveau",
   1.550 +                "Vivante",
   1.551 +                "VMware, Inc."
   1.552 +        };
   1.553 +
   1.554 +        mVendor = GLVendor::Other;
   1.555 +        for (size_t i = 0; i < size_t(GLVendor::Other); ++i) {
   1.556 +            if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
   1.557 +                mVendor = GLVendor(i);
   1.558 +                break;
   1.559 +            }
   1.560 +        }
   1.561 +
   1.562 +        // The order of these strings must match up with the order of the enum
   1.563 +        // defined in GLContext.h for renderer IDs
   1.564 +        glRendererString = (const char *)fGetString(LOCAL_GL_RENDERER);
   1.565 +        if (!glRendererString)
   1.566 +            mInitialized = false;
   1.567 +
   1.568 +        const char *rendererMatchStrings[size_t(GLRenderer::Other)] = {
   1.569 +                "Adreno 200",
   1.570 +                "Adreno 205",
   1.571 +                "Adreno (TM) 205",
   1.572 +                "Adreno (TM) 320",
   1.573 +                "PowerVR SGX 530",
   1.574 +                "PowerVR SGX 540",
   1.575 +                "NVIDIA Tegra",
   1.576 +                "Android Emulator",
   1.577 +                "Gallium 0.4 on llvmpipe"
   1.578 +        };
   1.579 +
   1.580 +        mRenderer = GLRenderer::Other;
   1.581 +        for (size_t i = 0; i < size_t(GLRenderer::Other); ++i) {
   1.582 +            if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) {
   1.583 +                mRenderer = GLRenderer(i);
   1.584 +                break;
   1.585 +            }
   1.586 +        }
   1.587 +    }
   1.588 +
   1.589 +
   1.590 +#ifdef DEBUG
   1.591 +    if (PR_GetEnv("MOZ_GL_DEBUG"))
   1.592 +        sDebugMode |= DebugEnabled;
   1.593 +
   1.594 +    // enables extra verbose output, informing of the start and finish of every GL call.
   1.595 +    // useful e.g. to record information to investigate graphics system crashes/lockups
   1.596 +    if (PR_GetEnv("MOZ_GL_DEBUG_VERBOSE"))
   1.597 +        sDebugMode |= DebugTrace;
   1.598 +
   1.599 +    // aborts on GL error. Can be useful to debug quicker code that is known not to generate any GL error in principle.
   1.600 +    if (PR_GetEnv("MOZ_GL_DEBUG_ABORT_ON_ERROR"))
   1.601 +        sDebugMode |= DebugAbortOnError;
   1.602 +#endif
   1.603 +
   1.604 +    if (mInitialized) {
   1.605 +#ifdef DEBUG
   1.606 +        static bool firstRun = true;
   1.607 +        if (firstRun && DebugMode()) {
   1.608 +            const char *vendors[size_t(GLVendor::Other)] = {
   1.609 +                "Intel",
   1.610 +                "NVIDIA",
   1.611 +                "ATI",
   1.612 +                "Qualcomm"
   1.613 +            };
   1.614 +
   1.615 +            MOZ_ASSERT(glVendorString);
   1.616 +            if (mVendor < GLVendor::Other) {
   1.617 +                printf_stderr("OpenGL vendor ('%s') recognized as: %s\n",
   1.618 +                              glVendorString, vendors[size_t(mVendor)]);
   1.619 +            } else {
   1.620 +                printf_stderr("OpenGL vendor ('%s') unrecognized\n", glVendorString);
   1.621 +            }
   1.622 +        }
   1.623 +        firstRun = false;
   1.624 +#endif
   1.625 +
   1.626 +        InitExtensions();
   1.627 +        InitFeatures();
   1.628 +
   1.629 +        // Disable extensions with partial or incorrect support.
   1.630 +        if (WorkAroundDriverBugs()) {
   1.631 +            if (Renderer() == GLRenderer::AdrenoTM320) {
   1.632 +                MarkUnsupported(GLFeature::standard_derivatives);
   1.633 +            }
   1.634 +
   1.635 +            if (Vendor() == GLVendor::Vivante) {
   1.636 +                // bug 958256
   1.637 +                MarkUnsupported(GLFeature::standard_derivatives);
   1.638 +            }
   1.639 +
   1.640 +            if (Vendor() == GLVendor::Imagination &&
   1.641 +                Renderer() == GLRenderer::SGX540) {
   1.642 +                // Bug 980048
   1.643 +                MarkExtensionUnsupported(OES_EGL_sync);
   1.644 +            }
   1.645 +
   1.646 +#ifdef XP_MACOSX
   1.647 +            // The Mac Nvidia driver, for versions up to and including 10.8, don't seem
   1.648 +            // to properly support this.  See 814839
   1.649 +            // this has been fixed in Mac OS X 10.9. See 907946
   1.650 +            if (Vendor() == gl::GLVendor::NVIDIA &&
   1.651 +                !nsCocoaFeatures::OnMavericksOrLater())
   1.652 +            {
   1.653 +                MarkUnsupported(GLFeature::depth_texture);
   1.654 +            }
   1.655 +#endif
   1.656 +            // ANGLE's divisor support is busted. (see bug 916816)
   1.657 +            if (IsANGLE()) {
   1.658 +                MarkUnsupported(GLFeature::instanced_arrays);
   1.659 +            }
   1.660 +        }
   1.661 +
   1.662 +        NS_ASSERTION(!IsExtensionSupported(GLContext::ARB_pixel_buffer_object) ||
   1.663 +                     (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
   1.664 +                     "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer being available!");
   1.665 +
   1.666 +        if (SupportsRobustness()) {
   1.667 +            mHasRobustness = false;
   1.668 +
   1.669 +            if (IsExtensionSupported(ARB_robustness)) {
   1.670 +                SymLoadStruct robustnessSymbols[] = {
   1.671 +                    { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusARB", nullptr } },
   1.672 +                    { nullptr, { nullptr } },
   1.673 +                };
   1.674 +
   1.675 +                if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
   1.676 +                    NS_ERROR("GL supports ARB_robustness without supplying GetGraphicsResetStatusARB.");
   1.677 +
   1.678 +                    mSymbols.fGetGraphicsResetStatus = nullptr;
   1.679 +                } else {
   1.680 +                    mHasRobustness = true;
   1.681 +                }
   1.682 +            }
   1.683 +            if (!IsExtensionSupported(ARB_robustness) &&
   1.684 +                IsExtensionSupported(EXT_robustness)) {
   1.685 +                SymLoadStruct robustnessSymbols[] = {
   1.686 +                    { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusEXT", nullptr } },
   1.687 +                    { nullptr, { nullptr } },
   1.688 +                };
   1.689 +
   1.690 +                if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
   1.691 +                    NS_ERROR("GL supports EXT_robustness without supplying GetGraphicsResetStatusEXT.");
   1.692 +
   1.693 +                    mSymbols.fGetGraphicsResetStatus = nullptr;
   1.694 +                } else {
   1.695 +                    mHasRobustness = true;
   1.696 +                }
   1.697 +            }
   1.698 +
   1.699 +            if (!mHasRobustness) {
   1.700 +                MarkUnsupported(GLFeature::robustness);
   1.701 +            }
   1.702 +        }
   1.703 +
   1.704 +        // Check for aux symbols based on extensions
   1.705 +        if (IsSupported(GLFeature::framebuffer_blit))
   1.706 +        {
   1.707 +            SymLoadStruct auxSymbols[] = {
   1.708 +                {
   1.709 +                    (PRFuncPtr*) &mSymbols.fBlitFramebuffer,
   1.710 +                    {
   1.711 +                        "BlitFramebuffer",
   1.712 +                        "BlitFramebufferEXT",
   1.713 +                        "BlitFramebufferANGLE",
   1.714 +                        nullptr
   1.715 +                    }
   1.716 +                },
   1.717 +                { nullptr, { nullptr } },
   1.718 +            };
   1.719 +            if (!LoadSymbols(&auxSymbols[0], trygl, prefix)) {
   1.720 +                NS_ERROR("GL supports framebuffer_blit without supplying glBlitFramebuffer");
   1.721 +
   1.722 +                MarkUnsupported(GLFeature::framebuffer_blit);
   1.723 +                mSymbols.fBlitFramebuffer = nullptr;
   1.724 +            }
   1.725 +        }
   1.726 +
   1.727 +        if (IsSupported(GLFeature::framebuffer_multisample))
   1.728 +        {
   1.729 +            SymLoadStruct auxSymbols[] = {
   1.730 +                {
   1.731 +                    (PRFuncPtr*) &mSymbols.fRenderbufferStorageMultisample,
   1.732 +                    {
   1.733 +                        "RenderbufferStorageMultisample",
   1.734 +                        "RenderbufferStorageMultisampleEXT",
   1.735 +                        "RenderbufferStorageMultisampleANGLE",
   1.736 +                        nullptr
   1.737 +                    }
   1.738 +                },
   1.739 +                { nullptr, { nullptr } },
   1.740 +            };
   1.741 +            if (!LoadSymbols(&auxSymbols[0], trygl, prefix)) {
   1.742 +                NS_ERROR("GL supports framebuffer_multisample without supplying glRenderbufferStorageMultisample");
   1.743 +
   1.744 +                MarkUnsupported(GLFeature::framebuffer_multisample);
   1.745 +                mSymbols.fRenderbufferStorageMultisample = nullptr;
   1.746 +            }
   1.747 +        }
   1.748 +
   1.749 +        if (IsExtensionSupported(ARB_sync)) {
   1.750 +            SymLoadStruct syncSymbols[] = {
   1.751 +                { (PRFuncPtr*) &mSymbols.fFenceSync,      { "FenceSync",      nullptr } },
   1.752 +                { (PRFuncPtr*) &mSymbols.fIsSync,         { "IsSync",         nullptr } },
   1.753 +                { (PRFuncPtr*) &mSymbols.fDeleteSync,     { "DeleteSync",     nullptr } },
   1.754 +                { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "ClientWaitSync", nullptr } },
   1.755 +                { (PRFuncPtr*) &mSymbols.fWaitSync,       { "WaitSync",       nullptr } },
   1.756 +                { (PRFuncPtr*) &mSymbols.fGetInteger64v,  { "GetInteger64v",  nullptr } },
   1.757 +                { (PRFuncPtr*) &mSymbols.fGetSynciv,      { "GetSynciv",      nullptr } },
   1.758 +                { nullptr, { nullptr } },
   1.759 +            };
   1.760 +
   1.761 +            if (!LoadSymbols(&syncSymbols[0], trygl, prefix)) {
   1.762 +                NS_ERROR("GL supports ARB_sync without supplying its functions.");
   1.763 +
   1.764 +                MarkExtensionUnsupported(ARB_sync);
   1.765 +                mSymbols.fFenceSync = nullptr;
   1.766 +                mSymbols.fIsSync = nullptr;
   1.767 +                mSymbols.fDeleteSync = nullptr;
   1.768 +                mSymbols.fClientWaitSync = nullptr;
   1.769 +                mSymbols.fWaitSync = nullptr;
   1.770 +                mSymbols.fGetInteger64v = nullptr;
   1.771 +                mSymbols.fGetSynciv = nullptr;
   1.772 +            }
   1.773 +        }
   1.774 +
   1.775 +        if (IsExtensionSupported(OES_EGL_image)) {
   1.776 +            SymLoadStruct imageSymbols[] = {
   1.777 +                { (PRFuncPtr*) &mSymbols.fEGLImageTargetTexture2D, { "EGLImageTargetTexture2DOES", nullptr } },
   1.778 +                { (PRFuncPtr*) &mSymbols.fEGLImageTargetRenderbufferStorage, { "EGLImageTargetRenderbufferStorageOES", nullptr } },
   1.779 +                { nullptr, { nullptr } },
   1.780 +            };
   1.781 +
   1.782 +            if (!LoadSymbols(&imageSymbols[0], trygl, prefix)) {
   1.783 +                NS_ERROR("GL supports OES_EGL_image without supplying its functions.");
   1.784 +
   1.785 +                MarkExtensionUnsupported(OES_EGL_image);
   1.786 +                mSymbols.fEGLImageTargetTexture2D = nullptr;
   1.787 +                mSymbols.fEGLImageTargetRenderbufferStorage = nullptr;
   1.788 +            }
   1.789 +        }
   1.790 +
   1.791 +        if (IsExtensionSupported(APPLE_texture_range)) {
   1.792 +            SymLoadStruct vaoSymbols[] = {
   1.793 +                { (PRFuncPtr*) &mSymbols.fTextureRangeAPPLE, { "TextureRangeAPPLE", nullptr } },
   1.794 +                { nullptr, { nullptr } },
   1.795 +            };
   1.796 +
   1.797 +            if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
   1.798 +                mSymbols.fTextureRangeAPPLE = nullptr;
   1.799 +            }
   1.800 +        }
   1.801 +
   1.802 +        if (IsExtensionSupported(ARB_vertex_array_object) ||
   1.803 +            IsExtensionSupported(OES_vertex_array_object)) {
   1.804 +            SymLoadStruct vaoSymbols[] = {
   1.805 +                { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", "IsVertexArrayOES", nullptr } },
   1.806 +                { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", "GenVertexArraysOES", nullptr } },
   1.807 +                { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", "BindVertexArrayOES", nullptr } },
   1.808 +                { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", "DeleteVertexArraysOES", nullptr } },
   1.809 +                { nullptr, { nullptr } },
   1.810 +            };
   1.811 +
   1.812 +            if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
   1.813 +                NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
   1.814 +
   1.815 +                MarkUnsupported(GLFeature::vertex_array_object);
   1.816 +                mSymbols.fIsVertexArray = nullptr;
   1.817 +                mSymbols.fGenVertexArrays = nullptr;
   1.818 +                mSymbols.fBindVertexArray = nullptr;
   1.819 +                mSymbols.fDeleteVertexArrays = nullptr;
   1.820 +            }
   1.821 +        }
   1.822 +        else if (IsExtensionSupported(APPLE_vertex_array_object)) {
   1.823 +            /*
   1.824 +             * separate call to LoadSymbols with APPLE_vertex_array_object to work around
   1.825 +             * a driver bug : the IsVertexArray symbol (without suffix) can be present but unusable.
   1.826 +             */
   1.827 +            SymLoadStruct vaoSymbols[] = {
   1.828 +                { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArrayAPPLE", nullptr } },
   1.829 +                { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArraysAPPLE", nullptr } },
   1.830 +                { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrayAPPLE", nullptr } },
   1.831 +                { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArraysAPPLE", nullptr } },
   1.832 +                { nullptr, { nullptr } },
   1.833 +            };
   1.834 +
   1.835 +            if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
   1.836 +                NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
   1.837 +
   1.838 +                MarkUnsupported(GLFeature::vertex_array_object);
   1.839 +                mSymbols.fIsVertexArray = nullptr;
   1.840 +                mSymbols.fGenVertexArrays = nullptr;
   1.841 +                mSymbols.fBindVertexArray = nullptr;
   1.842 +                mSymbols.fDeleteVertexArrays = nullptr;
   1.843 +            }
   1.844 +        }
   1.845 +
   1.846 +        if (IsSupported(GLFeature::draw_instanced)) {
   1.847 +            SymLoadStruct drawInstancedSymbols[] = {
   1.848 +                { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced,
   1.849 +                  { "DrawArraysInstanced",
   1.850 +                    "DrawArraysInstancedARB",
   1.851 +                    "DrawArraysInstancedEXT",
   1.852 +                    "DrawArraysInstancedNV",
   1.853 +                    "DrawArraysInstancedANGLE",
   1.854 +                    nullptr
   1.855 +                  }
   1.856 +                },
   1.857 +                { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced,
   1.858 +                  { "DrawElementsInstanced",
   1.859 +                    "DrawElementsInstancedARB",
   1.860 +                    "DrawElementsInstancedEXT",
   1.861 +                    "DrawElementsInstancedNV",
   1.862 +                    "DrawElementsInstancedANGLE",
   1.863 +                    nullptr
   1.864 +                  }
   1.865 +                },
   1.866 +                { nullptr, { nullptr } },
   1.867 +            };
   1.868 +
   1.869 +            if (!LoadSymbols(drawInstancedSymbols, trygl, prefix)) {
   1.870 +                NS_ERROR("GL supports instanced draws without supplying its functions.");
   1.871 +
   1.872 +                MarkUnsupported(GLFeature::draw_instanced);
   1.873 +                mSymbols.fDrawArraysInstanced = nullptr;
   1.874 +                mSymbols.fDrawElementsInstanced = nullptr;
   1.875 +            }
   1.876 +        }
   1.877 +
   1.878 +        if (IsSupported(GLFeature::instanced_arrays)) {
   1.879 +            SymLoadStruct instancedArraySymbols[] = {
   1.880 +                { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor,
   1.881 +                  { "VertexAttribDivisor",
   1.882 +                    "VertexAttribDivisorARB",
   1.883 +                    "VertexAttribDivisorNV",
   1.884 +                    "VertexAttribDivisorANGLE",
   1.885 +                    nullptr
   1.886 +                  }
   1.887 +                },
   1.888 +                { nullptr, { nullptr } },
   1.889 +            };
   1.890 +
   1.891 +            if (!LoadSymbols(instancedArraySymbols, trygl, prefix)) {
   1.892 +                NS_ERROR("GL supports array instanced without supplying it function.");
   1.893 +
   1.894 +                MarkUnsupported(GLFeature::instanced_arrays);
   1.895 +                mSymbols.fVertexAttribDivisor = nullptr;
   1.896 +            }
   1.897 +        }
   1.898 +
   1.899 +        if (IsSupported(GLFeature::transform_feedback)) {
   1.900 +            SymLoadStruct transformFeedbackSymbols[] = {
   1.901 +                { (PRFuncPtr*) &mSymbols.fBindBufferBase,
   1.902 +                  { "BindBufferBase",
   1.903 +                    "BindBufferBaseEXT",
   1.904 +                    "BindBufferBaseNV",
   1.905 +                    nullptr
   1.906 +                  }
   1.907 +                },
   1.908 +                { (PRFuncPtr*) &mSymbols.fBindBufferRange,
   1.909 +                  { "BindBufferRange",
   1.910 +                    "BindBufferRangeEXT",
   1.911 +                    "BindBufferRangeNV",
   1.912 +                    nullptr
   1.913 +                  }
   1.914 +                },
   1.915 +                { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback,
   1.916 +                  { "BeginTransformFeedback",
   1.917 +                    "BeginTransformFeedbackEXT",
   1.918 +                    "BeginTransformFeedbackNV",
   1.919 +                    nullptr
   1.920 +                  }
   1.921 +                },
   1.922 +                { (PRFuncPtr*) &mSymbols.fEndTransformFeedback,
   1.923 +                  { "EndTransformFeedback",
   1.924 +                    "EndTransformFeedbackEXT",
   1.925 +                    "EndTransformFeedbackNV",
   1.926 +                    nullptr
   1.927 +                  }
   1.928 +                },
   1.929 +                { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings,
   1.930 +                  { "TransformFeedbackVaryings",
   1.931 +                    "TransformFeedbackVaryingsEXT",
   1.932 +                    "TransformFeedbackVaryingsNV",
   1.933 +                    nullptr
   1.934 +                  }
   1.935 +                },
   1.936 +                { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying,
   1.937 +                  { "GetTransformFeedbackVarying",
   1.938 +                    "GetTransformFeedbackVaryingEXT",
   1.939 +                    "GetTransformFeedbackVaryingNV",
   1.940 +                    nullptr
   1.941 +                  }
   1.942 +                },
   1.943 +                { (PRFuncPtr*) &mSymbols.fGetIntegeri_v,
   1.944 +                  { "GetIntegeri_v",
   1.945 +                    "GetIntegerIndexedvEXT",
   1.946 +                    "GetIntegerIndexedvNV",
   1.947 +                    nullptr
   1.948 +                  }
   1.949 +                },
   1.950 +                { nullptr, { nullptr } },
   1.951 +            };
   1.952 +
   1.953 +            if (!LoadSymbols(transformFeedbackSymbols, trygl, prefix)) {
   1.954 +                NS_ERROR("GL supports transform feedback without supplying its functions.");
   1.955 +
   1.956 +                MarkUnsupported(GLFeature::transform_feedback);
   1.957 +                MarkUnsupported(GLFeature::bind_buffer_offset);
   1.958 +                mSymbols.fBindBufferBase = nullptr;
   1.959 +                mSymbols.fBindBufferRange = nullptr;
   1.960 +                mSymbols.fBeginTransformFeedback = nullptr;
   1.961 +                mSymbols.fEndTransformFeedback = nullptr;
   1.962 +                mSymbols.fTransformFeedbackVaryings = nullptr;
   1.963 +                mSymbols.fGetTransformFeedbackVarying = nullptr;
   1.964 +                mSymbols.fGetIntegeri_v = nullptr;
   1.965 +            }
   1.966 +        }
   1.967 +
   1.968 +        if (IsSupported(GLFeature::bind_buffer_offset)) {
   1.969 +            SymLoadStruct bindBufferOffsetSymbols[] = {
   1.970 +                { (PRFuncPtr*) &mSymbols.fBindBufferOffset,
   1.971 +                  { "BindBufferOffset",
   1.972 +                    "BindBufferOffsetEXT",
   1.973 +                    "BindBufferOffsetNV",
   1.974 +                    nullptr
   1.975 +                  }
   1.976 +                },
   1.977 +                { nullptr, { nullptr } },
   1.978 +            };
   1.979 +
   1.980 +            if (!LoadSymbols(bindBufferOffsetSymbols, trygl, prefix)) {
   1.981 +                NS_ERROR("GL supports BindBufferOffset without supplying its function.");
   1.982 +
   1.983 +                MarkUnsupported(GLFeature::bind_buffer_offset);
   1.984 +                mSymbols.fBindBufferOffset = nullptr;
   1.985 +            }
   1.986 +        }
   1.987 +
   1.988 +        if (IsSupported(GLFeature::query_objects)) {
   1.989 +            SymLoadStruct queryObjectsSymbols[] = {
   1.990 +                { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQuery", "BeginQueryEXT", nullptr } },
   1.991 +                { (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueries", "GenQueriesEXT", nullptr } },
   1.992 +                { (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueries", "DeleteQueriesEXT", nullptr } },
   1.993 +                { (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQuery", "EndQueryEXT", nullptr } },
   1.994 +                { (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryiv", "GetQueryivEXT", nullptr } },
   1.995 +                { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuiv", "GetQueryObjectuivEXT", nullptr } },
   1.996 +                { (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQuery", "IsQueryEXT", nullptr } },
   1.997 +                { nullptr, { nullptr } },
   1.998 +            };
   1.999 +
  1.1000 +            if (!LoadSymbols(queryObjectsSymbols, trygl, prefix)) {
  1.1001 +                NS_ERROR("GL supports query objects without supplying its functions.");
  1.1002 +
  1.1003 +                MarkUnsupported(GLFeature::query_objects);
  1.1004 +                MarkUnsupported(GLFeature::get_query_object_iv);
  1.1005 +                MarkUnsupported(GLFeature::occlusion_query);
  1.1006 +                MarkUnsupported(GLFeature::occlusion_query_boolean);
  1.1007 +                MarkUnsupported(GLFeature::occlusion_query2);
  1.1008 +                mSymbols.fBeginQuery = nullptr;
  1.1009 +                mSymbols.fGenQueries = nullptr;
  1.1010 +                mSymbols.fDeleteQueries = nullptr;
  1.1011 +                mSymbols.fEndQuery = nullptr;
  1.1012 +                mSymbols.fGetQueryiv = nullptr;
  1.1013 +                mSymbols.fGetQueryObjectuiv = nullptr;
  1.1014 +                mSymbols.fIsQuery = nullptr;
  1.1015 +            }
  1.1016 +        }
  1.1017 +
  1.1018 +        if (IsSupported(GLFeature::get_query_object_iv)) {
  1.1019 +            SymLoadStruct queryObjectsSymbols[] = {
  1.1020 +                { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectiv", "GetQueryObjectivEXT", nullptr } },
  1.1021 +                { nullptr, { nullptr } },
  1.1022 +            };
  1.1023 +
  1.1024 +            if (!LoadSymbols(queryObjectsSymbols, trygl, prefix)) {
  1.1025 +                NS_ERROR("GL supports query objects iv getter without supplying its function.");
  1.1026 +
  1.1027 +                MarkUnsupported(GLFeature::get_query_object_iv);
  1.1028 +                mSymbols.fGetQueryObjectiv = nullptr;
  1.1029 +            }
  1.1030 +        }
  1.1031 +
  1.1032 +        if (IsSupported(GLFeature::draw_buffers)) {
  1.1033 +            SymLoadStruct drawBuffersSymbols[] = {
  1.1034 +                { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
  1.1035 +                { nullptr, { nullptr } },
  1.1036 +            };
  1.1037 +
  1.1038 +            if (!LoadSymbols(drawBuffersSymbols, trygl, prefix)) {
  1.1039 +                NS_ERROR("GL supports draw_buffers without supplying its functions.");
  1.1040 +
  1.1041 +                MarkUnsupported(GLFeature::draw_buffers);
  1.1042 +                mSymbols.fDrawBuffers = nullptr;
  1.1043 +            }
  1.1044 +        }
  1.1045 +
  1.1046 +        if (IsExtensionSupported(KHR_debug)) {
  1.1047 +            SymLoadStruct extSymbols[] = {
  1.1048 +                { (PRFuncPtr*) &mSymbols.fDebugMessageControl,  { "DebugMessageControl",  "DebugMessageControlKHR",  nullptr } },
  1.1049 +                { (PRFuncPtr*) &mSymbols.fDebugMessageInsert,   { "DebugMessageInsert",   "DebugMessageInsertKHR",   nullptr } },
  1.1050 +                { (PRFuncPtr*) &mSymbols.fDebugMessageCallback, { "DebugMessageCallback", "DebugMessageCallbackKHR", nullptr } },
  1.1051 +                { (PRFuncPtr*) &mSymbols.fGetDebugMessageLog,   { "GetDebugMessageLog",   "GetDebugMessageLogKHR",   nullptr } },
  1.1052 +                { (PRFuncPtr*) &mSymbols.fGetPointerv,          { "GetPointerv",          "GetPointervKHR",          nullptr } },
  1.1053 +                { (PRFuncPtr*) &mSymbols.fPushDebugGroup,       { "PushDebugGroup",       "PushDebugGroupKHR",       nullptr } },
  1.1054 +                { (PRFuncPtr*) &mSymbols.fPopDebugGroup,        { "PopDebugGroup",        "PopDebugGroupKHR",        nullptr } },
  1.1055 +                { (PRFuncPtr*) &mSymbols.fObjectLabel,          { "ObjectLabel",          "ObjectLabelKHR",          nullptr } },
  1.1056 +                { (PRFuncPtr*) &mSymbols.fGetObjectLabel,       { "GetObjectLabel",       "GetObjectLabelKHR",       nullptr } },
  1.1057 +                { (PRFuncPtr*) &mSymbols.fObjectPtrLabel,       { "ObjectPtrLabel",       "ObjectPtrLabelKHR",       nullptr } },
  1.1058 +                { (PRFuncPtr*) &mSymbols.fGetObjectPtrLabel,    { "GetObjectPtrLabel",    "GetObjectPtrLabelKHR",    nullptr } },
  1.1059 +                { nullptr, { nullptr } },
  1.1060 +            };
  1.1061 +
  1.1062 +            if (!LoadSymbols(&extSymbols[0], trygl, prefix)) {
  1.1063 +                NS_ERROR("GL supports KHR_debug without supplying its functions.");
  1.1064 +
  1.1065 +                MarkExtensionUnsupported(KHR_debug);
  1.1066 +                mSymbols.fDebugMessageControl  = nullptr;
  1.1067 +                mSymbols.fDebugMessageInsert   = nullptr;
  1.1068 +                mSymbols.fDebugMessageCallback = nullptr;
  1.1069 +                mSymbols.fGetDebugMessageLog   = nullptr;
  1.1070 +                mSymbols.fGetPointerv          = nullptr;
  1.1071 +                mSymbols.fPushDebugGroup       = nullptr;
  1.1072 +                mSymbols.fPopDebugGroup        = nullptr;
  1.1073 +                mSymbols.fObjectLabel          = nullptr;
  1.1074 +                mSymbols.fGetObjectLabel       = nullptr;
  1.1075 +                mSymbols.fObjectPtrLabel       = nullptr;
  1.1076 +                mSymbols.fGetObjectPtrLabel    = nullptr;
  1.1077 +            }
  1.1078 +        }
  1.1079 +
  1.1080 +        if (IsSupported(GLFeature::draw_range_elements)) {
  1.1081 +            SymLoadStruct imageSymbols[] = {
  1.1082 +                { (PRFuncPtr*) &mSymbols.fDrawRangeElements, { "DrawRangeElementsEXT", "DrawRangeElements", nullptr } },
  1.1083 +                { nullptr, { nullptr } },
  1.1084 +            };
  1.1085 +
  1.1086 +            if (!LoadSymbols(&imageSymbols[0], trygl, prefix)) {
  1.1087 +                NS_ERROR("GL supports draw_range_elements without supplying its functions.");
  1.1088 +
  1.1089 +                MarkUnsupported(GLFeature::draw_range_elements);
  1.1090 +                mSymbols.fDrawRangeElements = nullptr;
  1.1091 +            }
  1.1092 +        }
  1.1093 +
  1.1094 +        // Load developer symbols, don't fail if we can't find them.
  1.1095 +        SymLoadStruct auxSymbols[] = {
  1.1096 +                { (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", nullptr } },
  1.1097 +                { (PRFuncPtr*) &mSymbols.fGetTexLevelParameteriv, { "GetTexLevelParameteriv", nullptr } },
  1.1098 +                { nullptr, { nullptr } },
  1.1099 +        };
  1.1100 +        bool warnOnFailures = DebugMode();
  1.1101 +        LoadSymbols(&auxSymbols[0], trygl, prefix, warnOnFailures);
  1.1102 +    }
  1.1103 +
  1.1104 +    if (mInitialized) {
  1.1105 +        raw_fGetIntegerv(LOCAL_GL_VIEWPORT, mViewportRect);
  1.1106 +        raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mScissorRect);
  1.1107 +        raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
  1.1108 +        raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
  1.1109 +        raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
  1.1110 +
  1.1111 +#ifdef XP_MACOSX
  1.1112 +        if (mWorkAroundDriverBugs) {
  1.1113 +            if (mVendor == GLVendor::Intel) {
  1.1114 +                // see bug 737182 for 2D textures, bug 684882 for cube map textures.
  1.1115 +                mMaxTextureSize        = std::min(mMaxTextureSize,        4096);
  1.1116 +                mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 512);
  1.1117 +                // for good measure, we align renderbuffers on what we do for 2D textures
  1.1118 +                mMaxRenderbufferSize   = std::min(mMaxRenderbufferSize,   4096);
  1.1119 +                mNeedsTextureSizeChecks = true;
  1.1120 +            } else if (mVendor == GLVendor::NVIDIA) {
  1.1121 +                if (nsCocoaFeatures::OnMountainLionOrLater()) {
  1.1122 +                    // See bug 879656.  8192 fails, 8191 works.
  1.1123 +                    mMaxTextureSize = std::min(mMaxTextureSize, 8191);
  1.1124 +                    mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 8191);
  1.1125 +                }
  1.1126 +                else {
  1.1127 +                    // See bug 877949.
  1.1128 +                    mMaxTextureSize = std::min(mMaxTextureSize, 4096);
  1.1129 +                    mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096);
  1.1130 +                }
  1.1131 +
  1.1132 +                // Part of the bug 879656, but it also doesn't hurt the 877949
  1.1133 +                mNeedsTextureSizeChecks = true;
  1.1134 +            }
  1.1135 +        }
  1.1136 +#endif
  1.1137 +#ifdef MOZ_X11
  1.1138 +        if (mWorkAroundDriverBugs &&
  1.1139 +            mVendor == GLVendor::Nouveau) {
  1.1140 +            // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau.
  1.1141 +            mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 2048);
  1.1142 +            mNeedsTextureSizeChecks = true;
  1.1143 +        }
  1.1144 +#endif
  1.1145 +
  1.1146 +        mMaxTextureImageSize = mMaxTextureSize;
  1.1147 +
  1.1148 +        mMaxSamples = 0;
  1.1149 +        if (IsSupported(GLFeature::framebuffer_multisample)) {
  1.1150 +            fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples);
  1.1151 +        }
  1.1152 +
  1.1153 +        // We're ready for final setup.
  1.1154 +        fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
  1.1155 +
  1.1156 +        if (mCaps.any)
  1.1157 +            DetermineCaps();
  1.1158 +
  1.1159 +        UpdatePixelFormat();
  1.1160 +        UpdateGLFormats(mCaps);
  1.1161 +
  1.1162 +        mTexGarbageBin = new TextureGarbageBin(this);
  1.1163 +
  1.1164 +        MOZ_ASSERT(IsCurrent());
  1.1165 +    }
  1.1166 +
  1.1167 +    if (mInitialized)
  1.1168 +        reporter.SetSuccessful();
  1.1169 +    else {
  1.1170 +        // if initialization fails, ensure all symbols are zero, to avoid hard-to-understand bugs
  1.1171 +        mSymbols.Zero();
  1.1172 +        NS_WARNING("InitWithPrefix failed!");
  1.1173 +    }
  1.1174 +
  1.1175 +    mVersionString = nsPrintfCString("%u.%u.%u", mVersion / 100, (mVersion / 10) % 10, mVersion % 10);
  1.1176 +
  1.1177 +    return mInitialized;
  1.1178 +}
  1.1179 +
  1.1180 +void
  1.1181 +GLContext::InitExtensions()
  1.1182 +{
  1.1183 +    MakeCurrent();
  1.1184 +    const char* extensions = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
  1.1185 +    if (!extensions)
  1.1186 +        return;
  1.1187 +
  1.1188 +#ifdef DEBUG
  1.1189 +    static bool firstRun = true;
  1.1190 +#else
  1.1191 +    // Non-DEBUG, so never spew.
  1.1192 +    const bool firstRun = false;
  1.1193 +#endif
  1.1194 +
  1.1195 +    InitializeExtensionsBitSet(mAvailableExtensions, extensions, sExtensionNames, firstRun && DebugMode());
  1.1196 +
  1.1197 +    if (WorkAroundDriverBugs() &&
  1.1198 +        Vendor() == GLVendor::Qualcomm) {
  1.1199 +
  1.1200 +        // Some Adreno drivers do not report GL_OES_EGL_sync, but they really do support it.
  1.1201 +        MarkExtensionSupported(OES_EGL_sync);
  1.1202 +    }
  1.1203 +
  1.1204 +    if (WorkAroundDriverBugs() &&
  1.1205 +        Renderer() == GLRenderer::AndroidEmulator) {
  1.1206 +        // the Android emulator, which we use to run B2G reftests on,
  1.1207 +        // doesn't expose the OES_rgb8_rgba8 extension, but it seems to
  1.1208 +        // support it (tautologically, as it only runs on desktop GL).
  1.1209 +        MarkExtensionSupported(OES_rgb8_rgba8);
  1.1210 +    }
  1.1211 +
  1.1212 +    if (WorkAroundDriverBugs() &&
  1.1213 +        Vendor() == GLVendor::VMware &&
  1.1214 +        Renderer() == GLRenderer::GalliumLlvmpipe)
  1.1215 +    {
  1.1216 +        // The llvmpipe driver that is used on linux try servers appears to have
  1.1217 +        // buggy support for s3tc/dxt1 compressed textures.
  1.1218 +        // See Bug 975824.
  1.1219 +        MarkExtensionUnsupported(EXT_texture_compression_s3tc);
  1.1220 +        MarkExtensionUnsupported(EXT_texture_compression_dxt1);
  1.1221 +        MarkExtensionUnsupported(ANGLE_texture_compression_dxt3);
  1.1222 +        MarkExtensionUnsupported(ANGLE_texture_compression_dxt5);
  1.1223 +    }
  1.1224 +
  1.1225 +#ifdef DEBUG
  1.1226 +    firstRun = false;
  1.1227 +#endif
  1.1228 +}
  1.1229 +
  1.1230 +void
  1.1231 +GLContext::PlatformStartup()
  1.1232 +{
  1.1233 +  RegisterStrongMemoryReporter(new GfxTexturesReporter());
  1.1234 +}
  1.1235 +
  1.1236 +// Common code for checking for both GL extensions and GLX extensions.
  1.1237 +bool
  1.1238 +GLContext::ListHasExtension(const GLubyte *extensions, const char *extension)
  1.1239 +{
  1.1240 +    // fix bug 612572 - we were crashing as we were calling this function with extensions==null
  1.1241 +    if (extensions == nullptr || extension == nullptr)
  1.1242 +        return false;
  1.1243 +
  1.1244 +    const GLubyte *start;
  1.1245 +    GLubyte *where, *terminator;
  1.1246 +
  1.1247 +    /* Extension names should not have spaces. */
  1.1248 +    where = (GLubyte *) strchr(extension, ' ');
  1.1249 +    if (where || *extension == '\0')
  1.1250 +        return false;
  1.1251 +
  1.1252 +    /*
  1.1253 +     * It takes a bit of care to be fool-proof about parsing the
  1.1254 +     * OpenGL extensions string. Don't be fooled by sub-strings,
  1.1255 +     * etc.
  1.1256 +     */
  1.1257 +    start = extensions;
  1.1258 +    for (;;) {
  1.1259 +        where = (GLubyte *) strstr((const char *) start, extension);
  1.1260 +        if (!where) {
  1.1261 +            break;
  1.1262 +        }
  1.1263 +        terminator = where + strlen(extension);
  1.1264 +        if (where == start || *(where - 1) == ' ') {
  1.1265 +            if (*terminator == ' ' || *terminator == '\0') {
  1.1266 +                return true;
  1.1267 +            }
  1.1268 +        }
  1.1269 +        start = terminator;
  1.1270 +    }
  1.1271 +    return false;
  1.1272 +}
  1.1273 +
  1.1274 +void
  1.1275 +GLContext::DetermineCaps()
  1.1276 +{
  1.1277 +    PixelBufferFormat format = QueryPixelFormat();
  1.1278 +
  1.1279 +    SurfaceCaps caps;
  1.1280 +    caps.color = !!format.red && !!format.green && !!format.blue;
  1.1281 +    caps.bpp16 = caps.color && format.ColorBits() == 16;
  1.1282 +    caps.alpha = !!format.alpha;
  1.1283 +    caps.depth = !!format.depth;
  1.1284 +    caps.stencil = !!format.stencil;
  1.1285 +    caps.antialias = format.samples > 1;
  1.1286 +    caps.preserve = true;
  1.1287 +
  1.1288 +    mCaps = caps;
  1.1289 +}
  1.1290 +
  1.1291 +PixelBufferFormat
  1.1292 +GLContext::QueryPixelFormat()
  1.1293 +{
  1.1294 +    PixelBufferFormat format;
  1.1295 +
  1.1296 +    ScopedBindFramebuffer autoFB(this, 0);
  1.1297 +
  1.1298 +    fGetIntegerv(LOCAL_GL_RED_BITS  , &format.red  );
  1.1299 +    fGetIntegerv(LOCAL_GL_GREEN_BITS, &format.green);
  1.1300 +    fGetIntegerv(LOCAL_GL_BLUE_BITS , &format.blue );
  1.1301 +    fGetIntegerv(LOCAL_GL_ALPHA_BITS, &format.alpha);
  1.1302 +
  1.1303 +    fGetIntegerv(LOCAL_GL_DEPTH_BITS, &format.depth);
  1.1304 +    fGetIntegerv(LOCAL_GL_STENCIL_BITS, &format.stencil);
  1.1305 +
  1.1306 +    fGetIntegerv(LOCAL_GL_SAMPLES, &format.samples);
  1.1307 +
  1.1308 +    return format;
  1.1309 +}
  1.1310 +
  1.1311 +void
  1.1312 +GLContext::UpdatePixelFormat()
  1.1313 +{
  1.1314 +    PixelBufferFormat format = QueryPixelFormat();
  1.1315 +#ifdef DEBUG
  1.1316 +    const SurfaceCaps& caps = Caps();
  1.1317 +    MOZ_ASSERT(!caps.any, "Did you forget to DetermineCaps()?");
  1.1318 +
  1.1319 +    MOZ_ASSERT(caps.color == !!format.red);
  1.1320 +    MOZ_ASSERT(caps.color == !!format.green);
  1.1321 +    MOZ_ASSERT(caps.color == !!format.blue);
  1.1322 +
  1.1323 +    MOZ_ASSERT(caps.alpha == !!format.alpha);
  1.1324 +
  1.1325 +    // These we either must have if they're requested, or
  1.1326 +    // we can have if they're not.
  1.1327 +    MOZ_ASSERT(caps.depth == !!format.depth || !caps.depth);
  1.1328 +    MOZ_ASSERT(caps.stencil == !!format.stencil || !caps.stencil);
  1.1329 +
  1.1330 +    MOZ_ASSERT(caps.antialias == (format.samples > 1));
  1.1331 +#endif
  1.1332 +    mPixelFormat = new PixelBufferFormat(format);
  1.1333 +}
  1.1334 +
  1.1335 +GLFormats
  1.1336 +GLContext::ChooseGLFormats(const SurfaceCaps& caps) const
  1.1337 +{
  1.1338 +    GLFormats formats;
  1.1339 +
  1.1340 +    // If we're on ES2 hardware and we have an explicit request for 16 bits of color or less
  1.1341 +    // OR we don't support full 8-bit color, return a 4444 or 565 format.
  1.1342 +    bool bpp16 = caps.bpp16;
  1.1343 +    if (IsGLES()) {
  1.1344 +        if (!IsExtensionSupported(OES_rgb8_rgba8))
  1.1345 +            bpp16 = true;
  1.1346 +    } else {
  1.1347 +        // RGB565 is uncommon on desktop, requiring ARB_ES2_compatibility.
  1.1348 +        // Since it's also vanishingly useless there, let's not support it.
  1.1349 +        bpp16 = false;
  1.1350 +    }
  1.1351 +
  1.1352 +    if (bpp16) {
  1.1353 +        MOZ_ASSERT(IsGLES());
  1.1354 +        if (caps.alpha) {
  1.1355 +            formats.color_texInternalFormat = LOCAL_GL_RGBA;
  1.1356 +            formats.color_texFormat = LOCAL_GL_RGBA;
  1.1357 +            formats.color_texType   = LOCAL_GL_UNSIGNED_SHORT_4_4_4_4;
  1.1358 +            formats.color_rbFormat  = LOCAL_GL_RGBA4;
  1.1359 +        } else {
  1.1360 +            formats.color_texInternalFormat = LOCAL_GL_RGB;
  1.1361 +            formats.color_texFormat = LOCAL_GL_RGB;
  1.1362 +            formats.color_texType   = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
  1.1363 +            formats.color_rbFormat  = LOCAL_GL_RGB565;
  1.1364 +        }
  1.1365 +    } else {
  1.1366 +        formats.color_texType = LOCAL_GL_UNSIGNED_BYTE;
  1.1367 +
  1.1368 +        if (caps.alpha) {
  1.1369 +            formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGBA : LOCAL_GL_RGBA8;
  1.1370 +            formats.color_texFormat = LOCAL_GL_RGBA;
  1.1371 +            formats.color_rbFormat  = LOCAL_GL_RGBA8;
  1.1372 +        } else {
  1.1373 +            formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGB : LOCAL_GL_RGB8;
  1.1374 +            formats.color_texFormat = LOCAL_GL_RGB;
  1.1375 +            formats.color_rbFormat  = LOCAL_GL_RGB8;
  1.1376 +        }
  1.1377 +    }
  1.1378 +
  1.1379 +    uint32_t msaaLevel = gfxPrefs::MSAALevel();
  1.1380 +    GLsizei samples = msaaLevel * msaaLevel;
  1.1381 +    samples = std::min(samples, mMaxSamples);
  1.1382 +
  1.1383 +    // Bug 778765.
  1.1384 +    if (WorkAroundDriverBugs() && samples == 1) {
  1.1385 +        samples = 0;
  1.1386 +    }
  1.1387 +    formats.samples = samples;
  1.1388 +
  1.1389 +
  1.1390 +    // Be clear that these are 0 if unavailable.
  1.1391 +    formats.depthStencil = 0;
  1.1392 +    if (!IsGLES() || IsExtensionSupported(OES_packed_depth_stencil)) {
  1.1393 +        formats.depthStencil = LOCAL_GL_DEPTH24_STENCIL8;
  1.1394 +    }
  1.1395 +
  1.1396 +    formats.depth = 0;
  1.1397 +    if (IsGLES()) {
  1.1398 +        if (IsExtensionSupported(OES_depth24)) {
  1.1399 +            formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
  1.1400 +        } else {
  1.1401 +            formats.depth = LOCAL_GL_DEPTH_COMPONENT16;
  1.1402 +        }
  1.1403 +    } else {
  1.1404 +        formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
  1.1405 +    }
  1.1406 +
  1.1407 +    formats.stencil = LOCAL_GL_STENCIL_INDEX8;
  1.1408 +
  1.1409 +    return formats;
  1.1410 +}
  1.1411 +
  1.1412 +bool
  1.1413 +GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus)
  1.1414 +{
  1.1415 +    MOZ_ASSERT(fb);
  1.1416 +
  1.1417 +    ScopedBindFramebuffer autoFB(this, fb);
  1.1418 +    MOZ_ASSERT(fIsFramebuffer(fb));
  1.1419 +
  1.1420 +    GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
  1.1421 +    if (pStatus)
  1.1422 +        *pStatus = status;
  1.1423 +
  1.1424 +    return status == LOCAL_GL_FRAMEBUFFER_COMPLETE;
  1.1425 +}
  1.1426 +
  1.1427 +void
  1.1428 +GLContext::AttachBuffersToFB(GLuint colorTex, GLuint colorRB,
  1.1429 +                             GLuint depthRB, GLuint stencilRB,
  1.1430 +                             GLuint fb, GLenum target)
  1.1431 +{
  1.1432 +    MOZ_ASSERT(fb);
  1.1433 +    MOZ_ASSERT( !(colorTex && colorRB) );
  1.1434 +
  1.1435 +    ScopedBindFramebuffer autoFB(this, fb);
  1.1436 +    MOZ_ASSERT(fIsFramebuffer(fb)); // It only counts after being bound.
  1.1437 +
  1.1438 +    if (colorTex) {
  1.1439 +        MOZ_ASSERT(fIsTexture(colorTex));
  1.1440 +        MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
  1.1441 +                   target == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
  1.1442 +        fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
  1.1443 +                              LOCAL_GL_COLOR_ATTACHMENT0,
  1.1444 +                              target,
  1.1445 +                              colorTex,
  1.1446 +                              0);
  1.1447 +    } else if (colorRB) {
  1.1448 +        MOZ_ASSERT(fIsRenderbuffer(colorRB));
  1.1449 +        fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
  1.1450 +                                 LOCAL_GL_COLOR_ATTACHMENT0,
  1.1451 +                                 LOCAL_GL_RENDERBUFFER,
  1.1452 +                                 colorRB);
  1.1453 +    }
  1.1454 +
  1.1455 +    if (depthRB) {
  1.1456 +        MOZ_ASSERT(fIsRenderbuffer(depthRB));
  1.1457 +        fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
  1.1458 +                                 LOCAL_GL_DEPTH_ATTACHMENT,
  1.1459 +                                 LOCAL_GL_RENDERBUFFER,
  1.1460 +                                 depthRB);
  1.1461 +    }
  1.1462 +
  1.1463 +    if (stencilRB) {
  1.1464 +        MOZ_ASSERT(fIsRenderbuffer(stencilRB));
  1.1465 +        fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
  1.1466 +                                 LOCAL_GL_STENCIL_ATTACHMENT,
  1.1467 +                                 LOCAL_GL_RENDERBUFFER,
  1.1468 +                                 stencilRB);
  1.1469 +    }
  1.1470 +}
  1.1471 +
  1.1472 +bool
  1.1473 +GLContext::AssembleOffscreenFBs(const GLuint colorMSRB,
  1.1474 +                                const GLuint depthRB,
  1.1475 +                                const GLuint stencilRB,
  1.1476 +                                const GLuint texture,
  1.1477 +                                GLuint* drawFB_out,
  1.1478 +                                GLuint* readFB_out)
  1.1479 +{
  1.1480 +    if (!colorMSRB && !texture) {
  1.1481 +        MOZ_ASSERT(!depthRB && !stencilRB);
  1.1482 +
  1.1483 +        if (drawFB_out)
  1.1484 +            *drawFB_out = 0;
  1.1485 +        if (readFB_out)
  1.1486 +            *readFB_out = 0;
  1.1487 +
  1.1488 +        return true;
  1.1489 +    }
  1.1490 +
  1.1491 +    ScopedBindFramebuffer autoFB(this);
  1.1492 +
  1.1493 +    GLuint drawFB = 0;
  1.1494 +    GLuint readFB = 0;
  1.1495 +
  1.1496 +    if (texture) {
  1.1497 +        readFB = 0;
  1.1498 +        fGenFramebuffers(1, &readFB);
  1.1499 +        BindFB(readFB);
  1.1500 +        fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
  1.1501 +                              LOCAL_GL_COLOR_ATTACHMENT0,
  1.1502 +                              LOCAL_GL_TEXTURE_2D,
  1.1503 +                              texture,
  1.1504 +                              0);
  1.1505 +    }
  1.1506 +
  1.1507 +    if (colorMSRB) {
  1.1508 +        drawFB = 0;
  1.1509 +        fGenFramebuffers(1, &drawFB);
  1.1510 +        BindFB(drawFB);
  1.1511 +        fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
  1.1512 +                                 LOCAL_GL_COLOR_ATTACHMENT0,
  1.1513 +                                 LOCAL_GL_RENDERBUFFER,
  1.1514 +                                 colorMSRB);
  1.1515 +    } else {
  1.1516 +        drawFB = readFB;
  1.1517 +    }
  1.1518 +    MOZ_ASSERT(GetFB() == drawFB);
  1.1519 +
  1.1520 +    if (depthRB) {
  1.1521 +        fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
  1.1522 +                                 LOCAL_GL_DEPTH_ATTACHMENT,
  1.1523 +                                 LOCAL_GL_RENDERBUFFER,
  1.1524 +                                 depthRB);
  1.1525 +    }
  1.1526 +
  1.1527 +    if (stencilRB) {
  1.1528 +        fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
  1.1529 +                                 LOCAL_GL_STENCIL_ATTACHMENT,
  1.1530 +                                 LOCAL_GL_RENDERBUFFER,
  1.1531 +                                 stencilRB);
  1.1532 +    }
  1.1533 +
  1.1534 +    // We should be all resized.  Check for framebuffer completeness.
  1.1535 +    GLenum status;
  1.1536 +    bool isComplete = true;
  1.1537 +
  1.1538 +    if (!IsFramebufferComplete(drawFB, &status)) {
  1.1539 +        NS_WARNING("DrawFBO: Incomplete");
  1.1540 +  #ifdef DEBUG
  1.1541 +        if (DebugMode()) {
  1.1542 +            printf_stderr("Framebuffer status: %X\n", status);
  1.1543 +        }
  1.1544 +  #endif
  1.1545 +        isComplete = false;
  1.1546 +    }
  1.1547 +
  1.1548 +    if (!IsFramebufferComplete(readFB, &status)) {
  1.1549 +        NS_WARNING("ReadFBO: Incomplete");
  1.1550 +  #ifdef DEBUG
  1.1551 +        if (DebugMode()) {
  1.1552 +            printf_stderr("Framebuffer status: %X\n", status);
  1.1553 +        }
  1.1554 +  #endif
  1.1555 +        isComplete = false;
  1.1556 +    }
  1.1557 +
  1.1558 +    if (drawFB_out) {
  1.1559 +        *drawFB_out = drawFB;
  1.1560 +    } else if (drawFB) {
  1.1561 +        NS_RUNTIMEABORT("drawFB created when not requested!");
  1.1562 +    }
  1.1563 +
  1.1564 +    if (readFB_out) {
  1.1565 +        *readFB_out = readFB;
  1.1566 +    } else if (readFB) {
  1.1567 +        NS_RUNTIMEABORT("readFB created when not requested!");
  1.1568 +    }
  1.1569 +
  1.1570 +    return isComplete;
  1.1571 +}
  1.1572 +
  1.1573 +
  1.1574 +
  1.1575 +bool
  1.1576 +GLContext::PublishFrame()
  1.1577 +{
  1.1578 +    MOZ_ASSERT(mScreen);
  1.1579 +
  1.1580 +    if (!mScreen->PublishFrame(OffscreenSize()))
  1.1581 +        return false;
  1.1582 +
  1.1583 +    return true;
  1.1584 +}
  1.1585 +
  1.1586 +SharedSurface_GL*
  1.1587 +GLContext::RequestFrame()
  1.1588 +{
  1.1589 +    MOZ_ASSERT(mScreen);
  1.1590 +
  1.1591 +    SharedSurface* ret = mScreen->Stream()->SwapConsumer();
  1.1592 +    if (!ret)
  1.1593 +        return nullptr;
  1.1594 +
  1.1595 +    return SharedSurface_GL::Cast(ret);
  1.1596 +}
  1.1597 +
  1.1598 +
  1.1599 +
  1.1600 +void
  1.1601 +GLContext::ClearSafely()
  1.1602 +{
  1.1603 +    // bug 659349 --- we must be very careful here: clearing a GL framebuffer is nontrivial, relies on a lot of state,
  1.1604 +    // and in the case of the backbuffer of a WebGL context, state is exposed to scripts.
  1.1605 +    //
  1.1606 +    // The code here is taken from WebGLContext::ForceClearFramebufferWithDefaultValues, but I didn't find a good way of
  1.1607 +    // sharing code with it. WebGL's code is somewhat performance-critical as it is typically called on every frame, so
  1.1608 +    // WebGL keeps track of GL state to avoid having to query it everytime, and also tries to only do work for actually
  1.1609 +    // present buffers (e.g. stencil buffer). Doing that here seems like premature optimization,
  1.1610 +    // as ClearSafely() is called only when e.g. a canvas is resized, not on every animation frame.
  1.1611 +
  1.1612 +    realGLboolean scissorTestEnabled;
  1.1613 +    realGLboolean ditherEnabled;
  1.1614 +    realGLboolean colorWriteMask[4];
  1.1615 +    realGLboolean depthWriteMask;
  1.1616 +    GLint stencilWriteMaskFront, stencilWriteMaskBack;
  1.1617 +    GLfloat colorClearValue[4];
  1.1618 +    GLfloat depthClearValue;
  1.1619 +    GLint stencilClearValue;
  1.1620 +
  1.1621 +    // save current GL state
  1.1622 +    fGetBooleanv(LOCAL_GL_SCISSOR_TEST, &scissorTestEnabled);
  1.1623 +    fGetBooleanv(LOCAL_GL_DITHER, &ditherEnabled);
  1.1624 +    fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
  1.1625 +    fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
  1.1626 +    fGetIntegerv(LOCAL_GL_STENCIL_WRITEMASK, &stencilWriteMaskFront);
  1.1627 +    fGetIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK, &stencilWriteMaskBack);
  1.1628 +    fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);
  1.1629 +    fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
  1.1630 +    fGetIntegerv(LOCAL_GL_STENCIL_CLEAR_VALUE, &stencilClearValue);
  1.1631 +
  1.1632 +    // prepare GL state for clearing
  1.1633 +    fDisable(LOCAL_GL_SCISSOR_TEST);
  1.1634 +    fDisable(LOCAL_GL_DITHER);
  1.1635 +
  1.1636 +    fColorMask(1, 1, 1, 1);
  1.1637 +    fClearColor(0.f, 0.f, 0.f, 0.f);
  1.1638 +
  1.1639 +    fDepthMask(1);
  1.1640 +    fClearDepth(1.0f);
  1.1641 +
  1.1642 +    fStencilMask(0xffffffff);
  1.1643 +    fClearStencil(0);
  1.1644 +
  1.1645 +    // do clear
  1.1646 +    fClear(LOCAL_GL_COLOR_BUFFER_BIT |
  1.1647 +           LOCAL_GL_DEPTH_BUFFER_BIT |
  1.1648 +           LOCAL_GL_STENCIL_BUFFER_BIT);
  1.1649 +
  1.1650 +    // restore GL state after clearing
  1.1651 +    fColorMask(colorWriteMask[0],
  1.1652 +               colorWriteMask[1],
  1.1653 +               colorWriteMask[2],
  1.1654 +               colorWriteMask[3]);
  1.1655 +    fClearColor(colorClearValue[0],
  1.1656 +                colorClearValue[1],
  1.1657 +                colorClearValue[2],
  1.1658 +                colorClearValue[3]);
  1.1659 +
  1.1660 +    fDepthMask(depthWriteMask);
  1.1661 +    fClearDepth(depthClearValue);
  1.1662 +
  1.1663 +    fStencilMaskSeparate(LOCAL_GL_FRONT, stencilWriteMaskFront);
  1.1664 +    fStencilMaskSeparate(LOCAL_GL_BACK, stencilWriteMaskBack);
  1.1665 +    fClearStencil(stencilClearValue);
  1.1666 +
  1.1667 +    if (ditherEnabled)
  1.1668 +        fEnable(LOCAL_GL_DITHER);
  1.1669 +    else
  1.1670 +        fDisable(LOCAL_GL_DITHER);
  1.1671 +
  1.1672 +    if (scissorTestEnabled)
  1.1673 +        fEnable(LOCAL_GL_SCISSOR_TEST);
  1.1674 +    else
  1.1675 +        fDisable(LOCAL_GL_SCISSOR_TEST);
  1.1676 +
  1.1677 +}
  1.1678 +
  1.1679 +void
  1.1680 +GLContext::MarkDestroyed()
  1.1681 +{
  1.1682 +    if (IsDestroyed())
  1.1683 +        return;
  1.1684 +
  1.1685 +    if (MakeCurrent()) {
  1.1686 +        DestroyScreenBuffer();
  1.1687 +
  1.1688 +        mBlitHelper = nullptr;
  1.1689 +        mBlitTextureImageHelper = nullptr;
  1.1690 +        mReadTexImageHelper = nullptr;
  1.1691 +
  1.1692 +        mTexGarbageBin->GLContextTeardown();
  1.1693 +    } else {
  1.1694 +        NS_WARNING("MakeCurrent() failed during MarkDestroyed! Skipping GL object teardown.");
  1.1695 +    }
  1.1696 +
  1.1697 +    mSymbols.Zero();
  1.1698 +}
  1.1699 +
  1.1700 +#ifdef MOZ_ENABLE_GL_TRACKING
  1.1701 +void
  1.1702 +GLContext::CreatedProgram(GLContext *aOrigin, GLuint aName)
  1.1703 +{
  1.1704 +    mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName));
  1.1705 +}
  1.1706 +
  1.1707 +void
  1.1708 +GLContext::CreatedShader(GLContext *aOrigin, GLuint aName)
  1.1709 +{
  1.1710 +    mTrackedShaders.AppendElement(NamedResource(aOrigin, aName));
  1.1711 +}
  1.1712 +
  1.1713 +void
  1.1714 +GLContext::CreatedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
  1.1715 +{
  1.1716 +    for (GLsizei i = 0; i < aCount; ++i) {
  1.1717 +        mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
  1.1718 +    }
  1.1719 +}
  1.1720 +
  1.1721 +void
  1.1722 +GLContext::CreatedQueries(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
  1.1723 +{
  1.1724 +    for (GLsizei i = 0; i < aCount; ++i) {
  1.1725 +        mTrackedQueries.AppendElement(NamedResource(aOrigin, aNames[i]));
  1.1726 +    }
  1.1727 +}
  1.1728 +
  1.1729 +void
  1.1730 +GLContext::CreatedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
  1.1731 +{
  1.1732 +    for (GLsizei i = 0; i < aCount; ++i) {
  1.1733 +        mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i]));
  1.1734 +    }
  1.1735 +}
  1.1736 +
  1.1737 +void
  1.1738 +GLContext::CreatedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
  1.1739 +{
  1.1740 +    for (GLsizei i = 0; i < aCount; ++i) {
  1.1741 +        mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
  1.1742 +    }
  1.1743 +}
  1.1744 +
  1.1745 +void
  1.1746 +GLContext::CreatedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
  1.1747 +{
  1.1748 +    for (GLsizei i = 0; i < aCount; ++i) {
  1.1749 +        mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
  1.1750 +    }
  1.1751 +}
  1.1752 +
  1.1753 +static void
  1.1754 +RemoveNamesFromArray(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames, nsTArray<GLContext::NamedResource>& aArray)
  1.1755 +{
  1.1756 +    for (GLsizei j = 0; j < aCount; ++j) {
  1.1757 +        GLuint name = aNames[j];
  1.1758 +        // name 0 can be ignored
  1.1759 +        if (name == 0)
  1.1760 +            continue;
  1.1761 +
  1.1762 +        for (uint32_t i = 0; i < aArray.Length(); ++i) {
  1.1763 +            if (aArray[i].name == name) {
  1.1764 +                aArray.RemoveElementAt(i);
  1.1765 +                break;
  1.1766 +            }
  1.1767 +        }
  1.1768 +    }
  1.1769 +}
  1.1770 +
  1.1771 +void
  1.1772 +GLContext::DeletedProgram(GLContext *aOrigin, GLuint aName)
  1.1773 +{
  1.1774 +    RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms);
  1.1775 +}
  1.1776 +
  1.1777 +void
  1.1778 +GLContext::DeletedShader(GLContext *aOrigin, GLuint aName)
  1.1779 +{
  1.1780 +    RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders);
  1.1781 +}
  1.1782 +
  1.1783 +void
  1.1784 +GLContext::DeletedBuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
  1.1785 +{
  1.1786 +    RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers);
  1.1787 +}
  1.1788 +
  1.1789 +void
  1.1790 +GLContext::DeletedQueries(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
  1.1791 +{
  1.1792 +    RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedQueries);
  1.1793 +}
  1.1794 +
  1.1795 +void
  1.1796 +GLContext::DeletedTextures(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
  1.1797 +{
  1.1798 +    RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures);
  1.1799 +}
  1.1800 +
  1.1801 +void
  1.1802 +GLContext::DeletedFramebuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
  1.1803 +{
  1.1804 +    RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers);
  1.1805 +}
  1.1806 +
  1.1807 +void
  1.1808 +GLContext::DeletedRenderbuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
  1.1809 +{
  1.1810 +    RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers);
  1.1811 +}
  1.1812 +
  1.1813 +static void
  1.1814 +MarkContextDestroyedInArray(GLContext *aContext, nsTArray<GLContext::NamedResource>& aArray)
  1.1815 +{
  1.1816 +    for (uint32_t i = 0; i < aArray.Length(); ++i) {
  1.1817 +        if (aArray[i].origin == aContext)
  1.1818 +            aArray[i].originDeleted = true;
  1.1819 +    }
  1.1820 +}
  1.1821 +
  1.1822 +void
  1.1823 +GLContext::SharedContextDestroyed(GLContext *aChild)
  1.1824 +{
  1.1825 +    MarkContextDestroyedInArray(aChild, mTrackedPrograms);
  1.1826 +    MarkContextDestroyedInArray(aChild, mTrackedShaders);
  1.1827 +    MarkContextDestroyedInArray(aChild, mTrackedTextures);
  1.1828 +    MarkContextDestroyedInArray(aChild, mTrackedFramebuffers);
  1.1829 +    MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers);
  1.1830 +    MarkContextDestroyedInArray(aChild, mTrackedBuffers);
  1.1831 +    MarkContextDestroyedInArray(aChild, mTrackedQueries);
  1.1832 +}
  1.1833 +
  1.1834 +static void
  1.1835 +ReportArrayContents(const char *title, const nsTArray<GLContext::NamedResource>& aArray)
  1.1836 +{
  1.1837 +    if (aArray.Length() == 0)
  1.1838 +        return;
  1.1839 +
  1.1840 +    printf_stderr("%s:\n", title);
  1.1841 +
  1.1842 +    nsTArray<GLContext::NamedResource> copy(aArray);
  1.1843 +    copy.Sort();
  1.1844 +
  1.1845 +    GLContext *lastContext = nullptr;
  1.1846 +    for (uint32_t i = 0; i < copy.Length(); ++i) {
  1.1847 +        if (lastContext != copy[i].origin) {
  1.1848 +            if (lastContext)
  1.1849 +                printf_stderr("\n");
  1.1850 +            printf_stderr("  [%p - %s] ", copy[i].origin, copy[i].originDeleted ? "deleted" : "live");
  1.1851 +            lastContext = copy[i].origin;
  1.1852 +        }
  1.1853 +        printf_stderr("%d ", copy[i].name);
  1.1854 +    }
  1.1855 +    printf_stderr("\n");
  1.1856 +}
  1.1857 +
  1.1858 +void
  1.1859 +GLContext::ReportOutstandingNames()
  1.1860 +{
  1.1861 +    if (!DebugMode())
  1.1862 +        return;
  1.1863 +
  1.1864 +    printf_stderr("== GLContext %p Outstanding ==\n", this);
  1.1865 +
  1.1866 +    ReportArrayContents("Outstanding Textures", mTrackedTextures);
  1.1867 +    ReportArrayContents("Outstanding Buffers", mTrackedBuffers);
  1.1868 +    ReportArrayContents("Outstanding Queries", mTrackedQueries);
  1.1869 +    ReportArrayContents("Outstanding Programs", mTrackedPrograms);
  1.1870 +    ReportArrayContents("Outstanding Shaders", mTrackedShaders);
  1.1871 +    ReportArrayContents("Outstanding Framebuffers", mTrackedFramebuffers);
  1.1872 +    ReportArrayContents("Outstanding Renderbuffers", mTrackedRenderbuffers);
  1.1873 +}
  1.1874 +
  1.1875 +#endif /* DEBUG */
  1.1876 +
  1.1877 +
  1.1878 +void
  1.1879 +GLContext::GuaranteeResolve()
  1.1880 +{
  1.1881 +    if (mScreen) {
  1.1882 +        mScreen->AssureBlitted();
  1.1883 +    }
  1.1884 +    fFinish();
  1.1885 +}
  1.1886 +
  1.1887 +const gfx::IntSize&
  1.1888 +GLContext::OffscreenSize() const
  1.1889 +{
  1.1890 +    MOZ_ASSERT(IsOffscreen());
  1.1891 +    return mScreen->Size();
  1.1892 +}
  1.1893 +
  1.1894 +bool
  1.1895 +GLContext::CreateScreenBufferImpl(const IntSize& size, const SurfaceCaps& caps)
  1.1896 +{
  1.1897 +    GLScreenBuffer* newScreen = GLScreenBuffer::Create(this, size, caps);
  1.1898 +    if (!newScreen)
  1.1899 +        return false;
  1.1900 +
  1.1901 +    if (!newScreen->Resize(size)) {
  1.1902 +        delete newScreen;
  1.1903 +        return false;
  1.1904 +    }
  1.1905 +
  1.1906 +    DestroyScreenBuffer();
  1.1907 +
  1.1908 +    // This will rebind to 0 (Screen) if needed when
  1.1909 +    // it falls out of scope.
  1.1910 +    ScopedBindFramebuffer autoFB(this);
  1.1911 +
  1.1912 +    mScreen = newScreen;
  1.1913 +
  1.1914 +    return true;
  1.1915 +}
  1.1916 +
  1.1917 +bool
  1.1918 +GLContext::ResizeScreenBuffer(const IntSize& size)
  1.1919 +{
  1.1920 +    if (!IsOffscreenSizeAllowed(size))
  1.1921 +        return false;
  1.1922 +
  1.1923 +    return mScreen->Resize(size);
  1.1924 +}
  1.1925 +
  1.1926 +
  1.1927 +void
  1.1928 +GLContext::DestroyScreenBuffer()
  1.1929 +{
  1.1930 +    delete mScreen;
  1.1931 +    mScreen = nullptr;
  1.1932 +}
  1.1933 +
  1.1934 +void
  1.1935 +GLContext::ForceDirtyScreen()
  1.1936 +{
  1.1937 +    ScopedBindFramebuffer autoFB(0);
  1.1938 +
  1.1939 +    BeforeGLDrawCall();
  1.1940 +    // no-op; just pretend we did something
  1.1941 +    AfterGLDrawCall();
  1.1942 +}
  1.1943 +
  1.1944 +void
  1.1945 +GLContext::CleanDirtyScreen()
  1.1946 +{
  1.1947 +    ScopedBindFramebuffer autoFB(0);
  1.1948 +
  1.1949 +    BeforeGLReadCall();
  1.1950 +    // no-op; we just want to make sure the Read FBO is updated if it needs to be
  1.1951 +    AfterGLReadCall();
  1.1952 +}
  1.1953 +
  1.1954 +void
  1.1955 +GLContext::EmptyTexGarbageBin()
  1.1956 +{
  1.1957 +   TexGarbageBin()->EmptyGarbage();
  1.1958 +}
  1.1959 +
  1.1960 +bool
  1.1961 +GLContext::IsOffscreenSizeAllowed(const IntSize& aSize) const {
  1.1962 +  int32_t biggerDimension = std::max(aSize.width, aSize.height);
  1.1963 +  int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize);
  1.1964 +  return biggerDimension <= maxAllowed;
  1.1965 +}
  1.1966 +
  1.1967 +bool
  1.1968 +GLContext::IsOwningThreadCurrent()
  1.1969 +{
  1.1970 +  return NS_GetCurrentThread() == mOwningThread;
  1.1971 +}
  1.1972 +
  1.1973 +void
  1.1974 +GLContext::DispatchToOwningThread(nsIRunnable *event)
  1.1975 +{
  1.1976 +    // Before dispatching, we need to ensure we're not in the middle of
  1.1977 +    // shutting down. Dispatching runnables in the middle of shutdown
  1.1978 +    // (that is, when the main thread is no longer get-able) can cause them
  1.1979 +    // to leak. See Bug 741319, and Bug 744115.
  1.1980 +    nsCOMPtr<nsIThread> mainThread;
  1.1981 +    if (NS_SUCCEEDED(NS_GetMainThread(getter_AddRefs(mainThread)))) {
  1.1982 +        mOwningThread->Dispatch(event, NS_DISPATCH_NORMAL);
  1.1983 +    }
  1.1984 +}
  1.1985 +
  1.1986 +GLBlitHelper*
  1.1987 +GLContext::BlitHelper()
  1.1988 +{
  1.1989 +    if (!mBlitHelper) {
  1.1990 +        mBlitHelper = new GLBlitHelper(this);
  1.1991 +    }
  1.1992 +
  1.1993 +    return mBlitHelper;
  1.1994 +}
  1.1995 +
  1.1996 +GLBlitTextureImageHelper*
  1.1997 +GLContext::BlitTextureImageHelper()
  1.1998 +{
  1.1999 +    if (!mBlitTextureImageHelper) {
  1.2000 +        mBlitTextureImageHelper = new GLBlitTextureImageHelper(this);
  1.2001 +    }
  1.2002 +
  1.2003 +    return mBlitTextureImageHelper;
  1.2004 +}
  1.2005 +
  1.2006 +GLReadTexImageHelper*
  1.2007 +GLContext::ReadTexImageHelper()
  1.2008 +{
  1.2009 +    if (!mReadTexImageHelper) {
  1.2010 +        mReadTexImageHelper = new GLReadTexImageHelper(this);
  1.2011 +    }
  1.2012 +
  1.2013 +    return mReadTexImageHelper;
  1.2014 +}
  1.2015 +
  1.2016 +bool
  1.2017 +DoesStringMatch(const char* aString, const char *aWantedString)
  1.2018 +{
  1.2019 +    if (!aString || !aWantedString)
  1.2020 +        return false;
  1.2021 +
  1.2022 +    const char *occurrence = strstr(aString, aWantedString);
  1.2023 +
  1.2024 +    // aWanted not found
  1.2025 +    if (!occurrence)
  1.2026 +        return false;
  1.2027 +
  1.2028 +    // aWantedString preceded by alpha character
  1.2029 +    if (occurrence != aString && isalpha(*(occurrence-1)))
  1.2030 +        return false;
  1.2031 +
  1.2032 +    // aWantedVendor followed by alpha character
  1.2033 +    const char *afterOccurrence = occurrence + strlen(aWantedString);
  1.2034 +    if (isalpha(*afterOccurrence))
  1.2035 +        return false;
  1.2036 +
  1.2037 +    return true;
  1.2038 +}
  1.2039 +
  1.2040 +} /* namespace gl */
  1.2041 +} /* namespace mozilla */

mercurial