gfx/gl/GLContext.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* vim: set ts=8 sts=4 et sw=4 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include <algorithm>
     8 #include <stdio.h>
     9 #include <string.h>
    10 #include <ctype.h>
    12 #include "GLContext.h"
    13 #include "GLBlitHelper.h"
    14 #include "GLBlitTextureImageHelper.h"
    15 #include "GLReadTexImageHelper.h"
    17 #include "gfxCrashReporterUtils.h"
    18 #include "gfxUtils.h"
    19 #include "GLContextProvider.h"
    20 #include "GLTextureImage.h"
    21 #include "nsPrintfCString.h"
    22 #include "nsThreadUtils.h"
    23 #include "prenv.h"
    24 #include "prlink.h"
    25 #include "ScopedGLHelpers.h"
    26 #include "SharedSurfaceGL.h"
    27 #include "SurfaceStream.h"
    28 #include "GfxTexturesReporter.h"
    29 #include "TextureGarbageBin.h"
    30 #include "gfx2DGlue.h"
    31 #include "gfxPrefs.h"
    33 #include "OGLShaderProgram.h" // for ShaderProgramType
    35 #include "mozilla/DebugOnly.h"
    37 #ifdef XP_MACOSX
    38 #include <CoreServices/CoreServices.h>
    39 #include "gfxColor.h"
    40 #endif
    42 #if defined(MOZ_WIDGET_COCOA)
    43 #include "nsCocoaFeatures.h"
    44 #endif
    46 using namespace mozilla::gfx;
    47 using namespace mozilla::layers;
    49 namespace mozilla {
    50 namespace gl {
    52 #ifdef DEBUG
    53 unsigned GLContext::sCurrentGLContextTLS = -1;
    54 #endif
    56 uint32_t GLContext::sDebugMode = 0;
    59 #define MAX_SYMBOL_LENGTH 128
    60 #define MAX_SYMBOL_NAMES 5
    62 // should match the order of GLExtensions, and be null-terminated.
    63 static const char *sExtensionNames[] = {
    64     "GL_EXT_framebuffer_object",
    65     "GL_ARB_framebuffer_object",
    66     "GL_ARB_texture_rectangle",
    67     "GL_EXT_bgra",
    68     "GL_EXT_texture_format_BGRA8888",
    69     "GL_OES_depth24",
    70     "GL_OES_depth32",
    71     "GL_OES_stencil8",
    72     "GL_OES_texture_npot",
    73     "GL_ARB_depth_texture",
    74     "GL_OES_depth_texture",
    75     "GL_OES_packed_depth_stencil",
    76     "GL_IMG_read_format",
    77     "GL_EXT_read_format_bgra",
    78     "GL_APPLE_client_storage",
    79     "GL_APPLE_texture_range",
    80     "GL_ARB_texture_non_power_of_two",
    81     "GL_ARB_pixel_buffer_object",
    82     "GL_ARB_ES2_compatibility",
    83     "GL_ARB_ES3_compatibility",
    84     "GL_OES_texture_float",
    85     "GL_OES_texture_float_linear",
    86     "GL_ARB_texture_float",
    87     "GL_OES_texture_half_float",
    88     "GL_OES_texture_half_float_linear",
    89     "GL_NV_half_float",
    90     "GL_EXT_color_buffer_float",
    91     "GL_EXT_color_buffer_half_float",
    92     "GL_ARB_color_buffer_float",
    93     "GL_EXT_unpack_subimage",
    94     "GL_OES_standard_derivatives",
    95     "GL_EXT_texture_filter_anisotropic",
    96     "GL_EXT_texture_compression_s3tc",
    97     "GL_EXT_texture_compression_dxt1",
    98     "GL_ANGLE_texture_compression_dxt3",
    99     "GL_ANGLE_texture_compression_dxt5",
   100     "GL_AMD_compressed_ATC_texture",
   101     "GL_IMG_texture_compression_pvrtc",
   102     "GL_EXT_framebuffer_blit",
   103     "GL_ANGLE_framebuffer_blit",
   104     "GL_EXT_framebuffer_multisample",
   105     "GL_ANGLE_framebuffer_multisample",
   106     "GL_OES_rgb8_rgba8",
   107     "GL_ARB_robustness",
   108     "GL_EXT_robustness",
   109     "GL_ARB_sync",
   110     "GL_OES_EGL_image",
   111     "GL_OES_EGL_sync",
   112     "GL_OES_EGL_image_external",
   113     "GL_EXT_packed_depth_stencil",
   114     "GL_OES_element_index_uint",
   115     "GL_OES_vertex_array_object",
   116     "GL_ARB_vertex_array_object",
   117     "GL_APPLE_vertex_array_object",
   118     "GL_ARB_draw_buffers",
   119     "GL_EXT_draw_buffers",
   120     "GL_EXT_gpu_shader4",
   121     "GL_EXT_blend_minmax",
   122     "GL_ARB_draw_instanced",
   123     "GL_EXT_draw_instanced",
   124     "GL_NV_draw_instanced",
   125     "GL_ARB_instanced_arrays",
   126     "GL_NV_instanced_arrays",
   127     "GL_ANGLE_instanced_arrays",
   128     "GL_EXT_occlusion_query_boolean",
   129     "GL_ARB_occlusion_query2",
   130     "GL_EXT_transform_feedback",
   131     "GL_NV_transform_feedback",
   132     "GL_ANGLE_depth_texture",
   133     "GL_EXT_sRGB",
   134     "GL_EXT_texture_sRGB",
   135     "GL_ARB_framebuffer_sRGB",
   136     "GL_EXT_framebuffer_sRGB",
   137     "GL_KHR_debug",
   138     "GL_ARB_half_float_pixel",
   139     "GL_EXT_frag_depth",
   140     "GL_OES_compressed_ETC1_RGB8_texture",
   141     "GL_EXT_draw_range_elements",
   142     nullptr
   143 };
   145 static bool
   146 ParseGLVersion(GLContext* gl, unsigned int* version)
   147 {
   148     GLenum error = gl->fGetError();
   149     if (error != LOCAL_GL_NO_ERROR) {
   150         MOZ_ASSERT(false, "An OpenGL error has been triggered before.");
   151         return false;
   152     }
   154     /**
   155      * B2G emulator bug work around: The emulator implements OpenGL ES 2.0 on
   156      * OpenGL 3.2. The bug is that GetIntegerv(LOCAL_GL_{MAJOR,MINOR}_VERSION)
   157      * returns OpenGL 3.2 instead of generating an error.
   158      */
   159     if (!gl->IsGLES())
   160     {
   161         /**
   162          * OpenGL 3.1 and OpenGL ES 3.0 both introduce GL_{MAJOR,MINOR}_VERSION
   163          * with GetIntegerv. So we first try those constants even though we
   164          * might not have an OpenGL context supporting them, has this is a
   165          * better way than parsing GL_VERSION.
   166          */
   167         GLint majorVersion = 0;
   168         GLint minorVersion = 0;
   170         gl->fGetIntegerv(LOCAL_GL_MAJOR_VERSION, &majorVersion);
   171         gl->fGetIntegerv(LOCAL_GL_MINOR_VERSION, &minorVersion);
   173         // If it's not an OpenGL (ES) 3.0 context, we will have an error
   174         error = gl->fGetError();
   175         if (error == LOCAL_GL_NO_ERROR &&
   176             majorVersion > 0 &&
   177             minorVersion >= 0)
   178         {
   179             *version = majorVersion * 100 + minorVersion * 10;
   180             return true;
   181         }
   182     }
   184     /**
   185      * We were not able to use GL_{MAJOR,MINOR}_VERSION, so we parse
   186      * GL_VERSION.
   187      *
   188      *
   189      * OpenGL 2.x, 3.x, 4.x specifications:
   190      *  The VERSION and SHADING_LANGUAGE_VERSION strings are laid out as follows:
   191      *
   192      *    <version number><space><vendor-specific information>
   193      *
   194      *  The version number is either of the form major_number.minor_number or
   195      *  major_number.minor_number.release_number, where the numbers all have
   196      *  one or more digits.
   197      *
   198      *
   199      * OpenGL ES 2.0, 3.0 specifications:
   200      *  The VERSION string is laid out as follows:
   201      *
   202      *     "OpenGL ES N.M vendor-specific information"
   203      *
   204      *  The version number is either of the form major_number.minor_number or
   205      *  major_number.minor_number.release_number, where the numbers all have
   206      *  one or more digits.
   207      *
   208      *
   209      * Note:
   210      *  We don't care about release_number.
   211      */
   212     const char* versionString = (const char*)gl->fGetString(LOCAL_GL_VERSION);
   214     error = gl->fGetError();
   215     if (error != LOCAL_GL_NO_ERROR) {
   216         MOZ_ASSERT(false, "glGetString(GL_VERSION) has generated an error");
   217         return false;
   218     } else if (!versionString) {
   219         MOZ_ASSERT(false, "glGetString(GL_VERSION) has returned 0");
   220         return false;
   221     }
   223     const char kGLESVersionPrefix[] = "OpenGL ES ";
   224     if (strncmp(versionString, kGLESVersionPrefix, strlen(kGLESVersionPrefix)) == 0) {
   225         versionString += strlen(kGLESVersionPrefix);
   226     }
   228     const char* itr = versionString;
   229     char* end = nullptr;
   230     int majorVersion = (int)strtol(itr, &end, 10);
   232     if (!end) {
   233         MOZ_ASSERT(false, "Failed to parse the GL major version number.");
   234         return false;
   235     } else if (*end != '.') {
   236         MOZ_ASSERT(false, "Failed to parse GL's major-minor version number separator.");
   237         return false;
   238     }
   240     // we skip the '.' between the major and the minor version
   241     itr = end + 1;
   243     end = nullptr;
   245     int minorVersion = (int)strtol(itr, &end, 10);
   246     if (!end) {
   247         MOZ_ASSERT(false, "Failed to parse GL's minor version number.");
   248         return false;
   249     }
   251     if (majorVersion <= 0 || majorVersion >= 100) {
   252         MOZ_ASSERT(false, "Invalid major version.");
   253         return false;
   254     } else if (minorVersion < 0 || minorVersion >= 10) {
   255         MOZ_ASSERT(false, "Invalid minor version.");
   256         return false;
   257     }
   259     *version = (unsigned int)(majorVersion * 100 + minorVersion * 10);
   260     return true;
   261 }
   263 GLContext::GLContext(const SurfaceCaps& caps,
   264           GLContext* sharedContext,
   265           bool isOffscreen)
   266   : mInitialized(false),
   267     mIsOffscreen(isOffscreen),
   268     mContextLost(false),
   269     mVersion(0),
   270     mProfile(ContextProfile::Unknown),
   271     mVendor(GLVendor::Other),
   272     mRenderer(GLRenderer::Other),
   273     mHasRobustness(false),
   274 #ifdef DEBUG
   275     mGLError(LOCAL_GL_NO_ERROR),
   276 #endif
   277     mSharedContext(sharedContext),
   278     mCaps(caps),
   279     mScreen(nullptr),
   280     mLockedSurface(nullptr),
   281     mMaxTextureSize(0),
   282     mMaxCubeMapTextureSize(0),
   283     mMaxTextureImageSize(0),
   284     mMaxRenderbufferSize(0),
   285     mNeedsTextureSizeChecks(false),
   286     mWorkAroundDriverBugs(true)
   287 {
   288     mOwningThread = NS_GetCurrentThread();
   289 }
   291 GLContext::~GLContext() {
   292     NS_ASSERTION(IsDestroyed(), "GLContext implementation must call MarkDestroyed in destructor!");
   293 #ifdef DEBUG
   294     if (mSharedContext) {
   295         GLContext *tip = mSharedContext;
   296         while (tip->mSharedContext)
   297             tip = tip->mSharedContext;
   298         tip->SharedContextDestroyed(this);
   299         tip->ReportOutstandingNames();
   300     } else {
   301         ReportOutstandingNames();
   302     }
   303 #endif
   304 }
   306 bool
   307 GLContext::InitWithPrefix(const char *prefix, bool trygl)
   308 {
   309     ScopedGfxFeatureReporter reporter("GL Context");
   311     if (mInitialized) {
   312         reporter.SetSuccessful();
   313         return true;
   314     }
   316     mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs();
   318     SymLoadStruct symbols[] = {
   319         { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } },
   320         { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } },
   321         { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } },
   322         { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } },
   323         { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } },
   324         { (PRFuncPtr*) &mSymbols.fBlendColor, { "BlendColor", nullptr } },
   325         { (PRFuncPtr*) &mSymbols.fBlendEquation, { "BlendEquation", nullptr } },
   326         { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, { "BlendEquationSeparate", "BlendEquationSeparateEXT", nullptr } },
   327         { (PRFuncPtr*) &mSymbols.fBlendFunc, { "BlendFunc", nullptr } },
   328         { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, { "BlendFuncSeparate", "BlendFuncSeparateEXT", nullptr } },
   329         { (PRFuncPtr*) &mSymbols.fBufferData, { "BufferData", nullptr } },
   330         { (PRFuncPtr*) &mSymbols.fBufferSubData, { "BufferSubData", nullptr } },
   331         { (PRFuncPtr*) &mSymbols.fClear, { "Clear", nullptr } },
   332         { (PRFuncPtr*) &mSymbols.fClearColor, { "ClearColor", nullptr } },
   333         { (PRFuncPtr*) &mSymbols.fClearStencil, { "ClearStencil", nullptr } },
   334         { (PRFuncPtr*) &mSymbols.fColorMask, { "ColorMask", nullptr } },
   335         { (PRFuncPtr*) &mSymbols.fCompressedTexImage2D, {"CompressedTexImage2D", nullptr} },
   336         { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage2D, {"CompressedTexSubImage2D", nullptr} },
   337         { (PRFuncPtr*) &mSymbols.fCullFace, { "CullFace", nullptr } },
   338         { (PRFuncPtr*) &mSymbols.fDetachShader, { "DetachShader", "DetachShaderARB", nullptr } },
   339         { (PRFuncPtr*) &mSymbols.fDepthFunc, { "DepthFunc", nullptr } },
   340         { (PRFuncPtr*) &mSymbols.fDepthMask, { "DepthMask", nullptr } },
   341         { (PRFuncPtr*) &mSymbols.fDisable, { "Disable", nullptr } },
   342         { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, { "DisableVertexAttribArray", "DisableVertexAttribArrayARB", nullptr } },
   343         { (PRFuncPtr*) &mSymbols.fDrawArrays, { "DrawArrays", nullptr } },
   344         { (PRFuncPtr*) &mSymbols.fDrawElements, { "DrawElements", nullptr } },
   345         { (PRFuncPtr*) &mSymbols.fEnable, { "Enable", nullptr } },
   346         { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, { "EnableVertexAttribArray", "EnableVertexAttribArrayARB", nullptr } },
   347         { (PRFuncPtr*) &mSymbols.fFinish, { "Finish", nullptr } },
   348         { (PRFuncPtr*) &mSymbols.fFlush, { "Flush", nullptr } },
   349         { (PRFuncPtr*) &mSymbols.fFrontFace, { "FrontFace", nullptr } },
   350         { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, { "GetActiveAttrib", "GetActiveAttribARB", nullptr } },
   351         { (PRFuncPtr*) &mSymbols.fGetActiveUniform, { "GetActiveUniform", "GetActiveUniformARB", nullptr } },
   352         { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, { "GetAttachedShaders", "GetAttachedShadersARB", nullptr } },
   353         { (PRFuncPtr*) &mSymbols.fGetAttribLocation, { "GetAttribLocation", "GetAttribLocationARB", nullptr } },
   354         { (PRFuncPtr*) &mSymbols.fGetIntegerv, { "GetIntegerv", nullptr } },
   355         { (PRFuncPtr*) &mSymbols.fGetFloatv, { "GetFloatv", nullptr } },
   356         { (PRFuncPtr*) &mSymbols.fGetBooleanv, { "GetBooleanv", nullptr } },
   357         { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, { "GetBufferParameteriv", "GetBufferParameterivARB", nullptr } },
   358         { (PRFuncPtr*) &mSymbols.fGetError, { "GetError", nullptr } },
   359         { (PRFuncPtr*) &mSymbols.fGetProgramiv, { "GetProgramiv", "GetProgramivARB", nullptr } },
   360         { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, { "GetProgramInfoLog", "GetProgramInfoLogARB", nullptr } },
   361         { (PRFuncPtr*) &mSymbols.fTexParameteri, { "TexParameteri", nullptr } },
   362         { (PRFuncPtr*) &mSymbols.fTexParameteriv, { "TexParameteriv", nullptr } },
   363         { (PRFuncPtr*) &mSymbols.fTexParameterf, { "TexParameterf", nullptr } },
   364         { (PRFuncPtr*) &mSymbols.fGetString, { "GetString", nullptr } },
   365         { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, { "GetTexParameterfv", nullptr } },
   366         { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, { "GetTexParameteriv", nullptr } },
   367         { (PRFuncPtr*) &mSymbols.fGetUniformfv, { "GetUniformfv", "GetUniformfvARB", nullptr } },
   368         { (PRFuncPtr*) &mSymbols.fGetUniformiv, { "GetUniformiv", "GetUniformivARB", nullptr } },
   369         { (PRFuncPtr*) &mSymbols.fGetUniformLocation, { "GetUniformLocation", "GetUniformLocationARB", nullptr } },
   370         { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, { "GetVertexAttribfv", "GetVertexAttribfvARB", nullptr } },
   371         { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, { "GetVertexAttribiv", "GetVertexAttribivARB", nullptr } },
   372         { (PRFuncPtr*) &mSymbols.fGetVertexAttribPointerv, { "GetVertexAttribPointerv", nullptr } },
   373         { (PRFuncPtr*) &mSymbols.fHint, { "Hint", nullptr } },
   374         { (PRFuncPtr*) &mSymbols.fIsBuffer, { "IsBuffer", "IsBufferARB", nullptr } },
   375         { (PRFuncPtr*) &mSymbols.fIsEnabled, { "IsEnabled", nullptr } },
   376         { (PRFuncPtr*) &mSymbols.fIsProgram, { "IsProgram", "IsProgramARB", nullptr } },
   377         { (PRFuncPtr*) &mSymbols.fIsShader, { "IsShader", "IsShaderARB", nullptr } },
   378         { (PRFuncPtr*) &mSymbols.fIsTexture, { "IsTexture", "IsTextureARB", nullptr } },
   379         { (PRFuncPtr*) &mSymbols.fLineWidth, { "LineWidth", nullptr } },
   380         { (PRFuncPtr*) &mSymbols.fLinkProgram, { "LinkProgram", "LinkProgramARB", nullptr } },
   381         { (PRFuncPtr*) &mSymbols.fPixelStorei, { "PixelStorei", nullptr } },
   382         { (PRFuncPtr*) &mSymbols.fPolygonOffset, { "PolygonOffset", nullptr } },
   383         { (PRFuncPtr*) &mSymbols.fReadPixels, { "ReadPixels", nullptr } },
   384         { (PRFuncPtr*) &mSymbols.fSampleCoverage, { "SampleCoverage", nullptr } },
   385         { (PRFuncPtr*) &mSymbols.fScissor, { "Scissor", nullptr } },
   386         { (PRFuncPtr*) &mSymbols.fStencilFunc, { "StencilFunc", nullptr } },
   387         { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, { "StencilFuncSeparate", "StencilFuncSeparateEXT", nullptr } },
   388         { (PRFuncPtr*) &mSymbols.fStencilMask, { "StencilMask", nullptr } },
   389         { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, { "StencilMaskSeparate", "StencilMaskSeparateEXT", nullptr } },
   390         { (PRFuncPtr*) &mSymbols.fStencilOp, { "StencilOp", nullptr } },
   391         { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, { "StencilOpSeparate", "StencilOpSeparateEXT", nullptr } },
   392         { (PRFuncPtr*) &mSymbols.fTexImage2D, { "TexImage2D", nullptr } },
   393         { (PRFuncPtr*) &mSymbols.fTexSubImage2D, { "TexSubImage2D", nullptr } },
   394         { (PRFuncPtr*) &mSymbols.fUniform1f, { "Uniform1f", nullptr } },
   395         { (PRFuncPtr*) &mSymbols.fUniform1fv, { "Uniform1fv", nullptr } },
   396         { (PRFuncPtr*) &mSymbols.fUniform1i, { "Uniform1i", nullptr } },
   397         { (PRFuncPtr*) &mSymbols.fUniform1iv, { "Uniform1iv", nullptr } },
   398         { (PRFuncPtr*) &mSymbols.fUniform2f, { "Uniform2f", nullptr } },
   399         { (PRFuncPtr*) &mSymbols.fUniform2fv, { "Uniform2fv", nullptr } },
   400         { (PRFuncPtr*) &mSymbols.fUniform2i, { "Uniform2i", nullptr } },
   401         { (PRFuncPtr*) &mSymbols.fUniform2iv, { "Uniform2iv", nullptr } },
   402         { (PRFuncPtr*) &mSymbols.fUniform3f, { "Uniform3f", nullptr } },
   403         { (PRFuncPtr*) &mSymbols.fUniform3fv, { "Uniform3fv", nullptr } },
   404         { (PRFuncPtr*) &mSymbols.fUniform3i, { "Uniform3i", nullptr } },
   405         { (PRFuncPtr*) &mSymbols.fUniform3iv, { "Uniform3iv", nullptr } },
   406         { (PRFuncPtr*) &mSymbols.fUniform4f, { "Uniform4f", nullptr } },
   407         { (PRFuncPtr*) &mSymbols.fUniform4fv, { "Uniform4fv", nullptr } },
   408         { (PRFuncPtr*) &mSymbols.fUniform4i, { "Uniform4i", nullptr } },
   409         { (PRFuncPtr*) &mSymbols.fUniform4iv, { "Uniform4iv", nullptr } },
   410         { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, { "UniformMatrix2fv", nullptr } },
   411         { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, { "UniformMatrix3fv", nullptr } },
   412         { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, { "UniformMatrix4fv", nullptr } },
   413         { (PRFuncPtr*) &mSymbols.fUseProgram, { "UseProgram", nullptr } },
   414         { (PRFuncPtr*) &mSymbols.fValidateProgram, { "ValidateProgram", nullptr } },
   415         { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
   416         { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, { "VertexAttrib1f", nullptr } },
   417         { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, { "VertexAttrib2f", nullptr } },
   418         { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, { "VertexAttrib3f", nullptr } },
   419         { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, { "VertexAttrib4f", nullptr } },
   420         { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, { "VertexAttrib1fv", nullptr } },
   421         { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, { "VertexAttrib2fv", nullptr } },
   422         { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, { "VertexAttrib3fv", nullptr } },
   423         { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, { "VertexAttrib4fv", nullptr } },
   424         { (PRFuncPtr*) &mSymbols.fViewport, { "Viewport", nullptr } },
   425         { (PRFuncPtr*) &mSymbols.fCompileShader, { "CompileShader", nullptr } },
   426         { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, { "CopyTexImage2D", nullptr } },
   427         { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, { "CopyTexSubImage2D", nullptr } },
   428         { (PRFuncPtr*) &mSymbols.fGetShaderiv, { "GetShaderiv", nullptr } },
   429         { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, { "GetShaderInfoLog", nullptr } },
   430         { (PRFuncPtr*) &mSymbols.fGetShaderSource, { "GetShaderSource", nullptr } },
   431         { (PRFuncPtr*) &mSymbols.fShaderSource, { "ShaderSource", nullptr } },
   432         { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } },
   433         { (PRFuncPtr*) &mSymbols.fBindFramebuffer, { "BindFramebuffer", "BindFramebufferEXT", nullptr } },
   434         { (PRFuncPtr*) &mSymbols.fBindRenderbuffer, { "BindRenderbuffer", "BindRenderbufferEXT", nullptr } },
   435         { (PRFuncPtr*) &mSymbols.fCheckFramebufferStatus, { "CheckFramebufferStatus", "CheckFramebufferStatusEXT", nullptr } },
   436         { (PRFuncPtr*) &mSymbols.fFramebufferRenderbuffer, { "FramebufferRenderbuffer", "FramebufferRenderbufferEXT", nullptr } },
   437         { (PRFuncPtr*) &mSymbols.fFramebufferTexture2D, { "FramebufferTexture2D", "FramebufferTexture2DEXT", nullptr } },
   438         { (PRFuncPtr*) &mSymbols.fGenerateMipmap, { "GenerateMipmap", "GenerateMipmapEXT", nullptr } },
   439         { (PRFuncPtr*) &mSymbols.fGetFramebufferAttachmentParameteriv, { "GetFramebufferAttachmentParameteriv", "GetFramebufferAttachmentParameterivEXT", nullptr } },
   440         { (PRFuncPtr*) &mSymbols.fGetRenderbufferParameteriv, { "GetRenderbufferParameteriv", "GetRenderbufferParameterivEXT", nullptr } },
   441         { (PRFuncPtr*) &mSymbols.fIsFramebuffer, { "IsFramebuffer", "IsFramebufferEXT", nullptr } },
   442         { (PRFuncPtr*) &mSymbols.fIsRenderbuffer, { "IsRenderbuffer", "IsRenderbufferEXT", nullptr } },
   443         { (PRFuncPtr*) &mSymbols.fRenderbufferStorage, { "RenderbufferStorage", "RenderbufferStorageEXT", nullptr } },
   445         { (PRFuncPtr*) &mSymbols.fGenBuffers, { "GenBuffers", "GenBuffersARB", nullptr } },
   446         { (PRFuncPtr*) &mSymbols.fGenTextures, { "GenTextures", nullptr } },
   447         { (PRFuncPtr*) &mSymbols.fCreateProgram, { "CreateProgram", "CreateProgramARB", nullptr } },
   448         { (PRFuncPtr*) &mSymbols.fCreateShader, { "CreateShader", "CreateShaderARB", nullptr } },
   449         { (PRFuncPtr*) &mSymbols.fGenFramebuffers, { "GenFramebuffers", "GenFramebuffersEXT", nullptr } },
   450         { (PRFuncPtr*) &mSymbols.fGenRenderbuffers, { "GenRenderbuffers", "GenRenderbuffersEXT", nullptr } },
   452         { (PRFuncPtr*) &mSymbols.fDeleteBuffers, { "DeleteBuffers", "DeleteBuffersARB", nullptr } },
   453         { (PRFuncPtr*) &mSymbols.fDeleteTextures, { "DeleteTextures", "DeleteTexturesARB", nullptr } },
   454         { (PRFuncPtr*) &mSymbols.fDeleteProgram, { "DeleteProgram", "DeleteProgramARB", nullptr } },
   455         { (PRFuncPtr*) &mSymbols.fDeleteShader, { "DeleteShader", "DeleteShaderARB", nullptr } },
   456         { (PRFuncPtr*) &mSymbols.fDeleteFramebuffers, { "DeleteFramebuffers", "DeleteFramebuffersEXT", nullptr } },
   457         { (PRFuncPtr*) &mSymbols.fDeleteRenderbuffers, { "DeleteRenderbuffers", "DeleteRenderbuffersEXT", nullptr } },
   459         { nullptr, { nullptr } },
   461     };
   463     mInitialized = LoadSymbols(&symbols[0], trygl, prefix);
   464     MakeCurrent();
   465     if (mInitialized) {
   466         unsigned int version = 0;
   468         ParseGLVersion(this, &version);
   470 #ifdef DEBUG
   471         printf_stderr("OpenGL version detected: %u\n", version);
   472         printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR));
   473         printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER));
   474 #endif
   476         if (version >= mVersion) {
   477             mVersion = version;
   478         }
   479         // Don't fail if version < mVersion, see bug 999445,
   480         // Mac OSX 10.6/10.7 machines with Intel GPUs claim only OpenGL 1.4 but
   481         // have all the GL2+ extensions that we need.
   482     }
   484     // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
   485     if (mInitialized) {
   486         if (IsGLES()) {
   487             SymLoadStruct symbols_ES2[] = {
   488                 { (PRFuncPtr*) &mSymbols.fGetShaderPrecisionFormat, { "GetShaderPrecisionFormat", nullptr } },
   489                 { (PRFuncPtr*) &mSymbols.fClearDepthf, { "ClearDepthf", nullptr } },
   490                 { (PRFuncPtr*) &mSymbols.fDepthRangef, { "DepthRangef", nullptr } },
   491                 { nullptr, { nullptr } },
   492             };
   494             if (!LoadSymbols(&symbols_ES2[0], trygl, prefix)) {
   495                 NS_ERROR("OpenGL ES 2.0 supported, but symbols could not be loaded.");
   496                 mInitialized = false;
   497             }
   498         } else {
   499             SymLoadStruct symbols_desktop[] = {
   500                 { (PRFuncPtr*) &mSymbols.fClearDepth, { "ClearDepth", nullptr } },
   501                 { (PRFuncPtr*) &mSymbols.fDepthRange, { "DepthRange", nullptr } },
   502                 { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } },
   503                 { (PRFuncPtr*) &mSymbols.fMapBuffer, { "MapBuffer", nullptr } },
   504                 { (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", nullptr } },
   505                 { (PRFuncPtr*) &mSymbols.fPointParameterf, { "PointParameterf", nullptr } },
   506                 { (PRFuncPtr*) &mSymbols.fDrawBuffer, { "DrawBuffer", nullptr } },
   507                     // These functions are only used by Skia/GL in desktop mode.
   508                     // Other parts of Gecko should avoid using these
   509                     { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
   510                     { (PRFuncPtr*) &mSymbols.fClientActiveTexture, { "ClientActiveTexture", nullptr } },
   511                     { (PRFuncPtr*) &mSymbols.fDisableClientState, { "DisableClientState", nullptr } },
   512                     { (PRFuncPtr*) &mSymbols.fEnableClientState, { "EnableClientState", nullptr } },
   513                     { (PRFuncPtr*) &mSymbols.fLoadIdentity, { "LoadIdentity", nullptr } },
   514                     { (PRFuncPtr*) &mSymbols.fLoadMatrixf, { "LoadMatrixf", nullptr } },
   515                     { (PRFuncPtr*) &mSymbols.fMatrixMode, { "MatrixMode", nullptr } },
   516                     { (PRFuncPtr*) &mSymbols.fTexGeni, { "TexGeni", nullptr } },
   517                     { (PRFuncPtr*) &mSymbols.fTexGenf, { "TexGenf", nullptr } },
   518                     { (PRFuncPtr*) &mSymbols.fTexGenfv, { "TexGenfv", nullptr } },
   519                     { (PRFuncPtr*) &mSymbols.fVertexPointer, { "VertexPointer", nullptr } },
   520                 { nullptr, { nullptr } },
   521             };
   523             if (!LoadSymbols(&symbols_desktop[0], trygl, prefix)) {
   524                 NS_ERROR("Desktop symbols failed to load.");
   525                 mInitialized = false;
   526             }
   527         }
   528     }
   530     const char *glVendorString = nullptr;
   531     const char *glRendererString = nullptr;
   533     if (mInitialized) {
   534         // The order of these strings must match up with the order of the enum
   535         // defined in GLContext.h for vendor IDs
   536         glVendorString = (const char *)fGetString(LOCAL_GL_VENDOR);
   537         if (!glVendorString)
   538             mInitialized = false;
   540         const char *vendorMatchStrings[size_t(GLVendor::Other)] = {
   541                 "Intel",
   542                 "NVIDIA",
   543                 "ATI",
   544                 "Qualcomm",
   545                 "Imagination",
   546                 "nouveau",
   547                 "Vivante",
   548                 "VMware, Inc."
   549         };
   551         mVendor = GLVendor::Other;
   552         for (size_t i = 0; i < size_t(GLVendor::Other); ++i) {
   553             if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
   554                 mVendor = GLVendor(i);
   555                 break;
   556             }
   557         }
   559         // The order of these strings must match up with the order of the enum
   560         // defined in GLContext.h for renderer IDs
   561         glRendererString = (const char *)fGetString(LOCAL_GL_RENDERER);
   562         if (!glRendererString)
   563             mInitialized = false;
   565         const char *rendererMatchStrings[size_t(GLRenderer::Other)] = {
   566                 "Adreno 200",
   567                 "Adreno 205",
   568                 "Adreno (TM) 205",
   569                 "Adreno (TM) 320",
   570                 "PowerVR SGX 530",
   571                 "PowerVR SGX 540",
   572                 "NVIDIA Tegra",
   573                 "Android Emulator",
   574                 "Gallium 0.4 on llvmpipe"
   575         };
   577         mRenderer = GLRenderer::Other;
   578         for (size_t i = 0; i < size_t(GLRenderer::Other); ++i) {
   579             if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) {
   580                 mRenderer = GLRenderer(i);
   581                 break;
   582             }
   583         }
   584     }
   587 #ifdef DEBUG
   588     if (PR_GetEnv("MOZ_GL_DEBUG"))
   589         sDebugMode |= DebugEnabled;
   591     // enables extra verbose output, informing of the start and finish of every GL call.
   592     // useful e.g. to record information to investigate graphics system crashes/lockups
   593     if (PR_GetEnv("MOZ_GL_DEBUG_VERBOSE"))
   594         sDebugMode |= DebugTrace;
   596     // aborts on GL error. Can be useful to debug quicker code that is known not to generate any GL error in principle.
   597     if (PR_GetEnv("MOZ_GL_DEBUG_ABORT_ON_ERROR"))
   598         sDebugMode |= DebugAbortOnError;
   599 #endif
   601     if (mInitialized) {
   602 #ifdef DEBUG
   603         static bool firstRun = true;
   604         if (firstRun && DebugMode()) {
   605             const char *vendors[size_t(GLVendor::Other)] = {
   606                 "Intel",
   607                 "NVIDIA",
   608                 "ATI",
   609                 "Qualcomm"
   610             };
   612             MOZ_ASSERT(glVendorString);
   613             if (mVendor < GLVendor::Other) {
   614                 printf_stderr("OpenGL vendor ('%s') recognized as: %s\n",
   615                               glVendorString, vendors[size_t(mVendor)]);
   616             } else {
   617                 printf_stderr("OpenGL vendor ('%s') unrecognized\n", glVendorString);
   618             }
   619         }
   620         firstRun = false;
   621 #endif
   623         InitExtensions();
   624         InitFeatures();
   626         // Disable extensions with partial or incorrect support.
   627         if (WorkAroundDriverBugs()) {
   628             if (Renderer() == GLRenderer::AdrenoTM320) {
   629                 MarkUnsupported(GLFeature::standard_derivatives);
   630             }
   632             if (Vendor() == GLVendor::Vivante) {
   633                 // bug 958256
   634                 MarkUnsupported(GLFeature::standard_derivatives);
   635             }
   637             if (Vendor() == GLVendor::Imagination &&
   638                 Renderer() == GLRenderer::SGX540) {
   639                 // Bug 980048
   640                 MarkExtensionUnsupported(OES_EGL_sync);
   641             }
   643 #ifdef XP_MACOSX
   644             // The Mac Nvidia driver, for versions up to and including 10.8, don't seem
   645             // to properly support this.  See 814839
   646             // this has been fixed in Mac OS X 10.9. See 907946
   647             if (Vendor() == gl::GLVendor::NVIDIA &&
   648                 !nsCocoaFeatures::OnMavericksOrLater())
   649             {
   650                 MarkUnsupported(GLFeature::depth_texture);
   651             }
   652 #endif
   653             // ANGLE's divisor support is busted. (see bug 916816)
   654             if (IsANGLE()) {
   655                 MarkUnsupported(GLFeature::instanced_arrays);
   656             }
   657         }
   659         NS_ASSERTION(!IsExtensionSupported(GLContext::ARB_pixel_buffer_object) ||
   660                      (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
   661                      "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer being available!");
   663         if (SupportsRobustness()) {
   664             mHasRobustness = false;
   666             if (IsExtensionSupported(ARB_robustness)) {
   667                 SymLoadStruct robustnessSymbols[] = {
   668                     { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusARB", nullptr } },
   669                     { nullptr, { nullptr } },
   670                 };
   672                 if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
   673                     NS_ERROR("GL supports ARB_robustness without supplying GetGraphicsResetStatusARB.");
   675                     mSymbols.fGetGraphicsResetStatus = nullptr;
   676                 } else {
   677                     mHasRobustness = true;
   678                 }
   679             }
   680             if (!IsExtensionSupported(ARB_robustness) &&
   681                 IsExtensionSupported(EXT_robustness)) {
   682                 SymLoadStruct robustnessSymbols[] = {
   683                     { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusEXT", nullptr } },
   684                     { nullptr, { nullptr } },
   685                 };
   687                 if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
   688                     NS_ERROR("GL supports EXT_robustness without supplying GetGraphicsResetStatusEXT.");
   690                     mSymbols.fGetGraphicsResetStatus = nullptr;
   691                 } else {
   692                     mHasRobustness = true;
   693                 }
   694             }
   696             if (!mHasRobustness) {
   697                 MarkUnsupported(GLFeature::robustness);
   698             }
   699         }
   701         // Check for aux symbols based on extensions
   702         if (IsSupported(GLFeature::framebuffer_blit))
   703         {
   704             SymLoadStruct auxSymbols[] = {
   705                 {
   706                     (PRFuncPtr*) &mSymbols.fBlitFramebuffer,
   707                     {
   708                         "BlitFramebuffer",
   709                         "BlitFramebufferEXT",
   710                         "BlitFramebufferANGLE",
   711                         nullptr
   712                     }
   713                 },
   714                 { nullptr, { nullptr } },
   715             };
   716             if (!LoadSymbols(&auxSymbols[0], trygl, prefix)) {
   717                 NS_ERROR("GL supports framebuffer_blit without supplying glBlitFramebuffer");
   719                 MarkUnsupported(GLFeature::framebuffer_blit);
   720                 mSymbols.fBlitFramebuffer = nullptr;
   721             }
   722         }
   724         if (IsSupported(GLFeature::framebuffer_multisample))
   725         {
   726             SymLoadStruct auxSymbols[] = {
   727                 {
   728                     (PRFuncPtr*) &mSymbols.fRenderbufferStorageMultisample,
   729                     {
   730                         "RenderbufferStorageMultisample",
   731                         "RenderbufferStorageMultisampleEXT",
   732                         "RenderbufferStorageMultisampleANGLE",
   733                         nullptr
   734                     }
   735                 },
   736                 { nullptr, { nullptr } },
   737             };
   738             if (!LoadSymbols(&auxSymbols[0], trygl, prefix)) {
   739                 NS_ERROR("GL supports framebuffer_multisample without supplying glRenderbufferStorageMultisample");
   741                 MarkUnsupported(GLFeature::framebuffer_multisample);
   742                 mSymbols.fRenderbufferStorageMultisample = nullptr;
   743             }
   744         }
   746         if (IsExtensionSupported(ARB_sync)) {
   747             SymLoadStruct syncSymbols[] = {
   748                 { (PRFuncPtr*) &mSymbols.fFenceSync,      { "FenceSync",      nullptr } },
   749                 { (PRFuncPtr*) &mSymbols.fIsSync,         { "IsSync",         nullptr } },
   750                 { (PRFuncPtr*) &mSymbols.fDeleteSync,     { "DeleteSync",     nullptr } },
   751                 { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "ClientWaitSync", nullptr } },
   752                 { (PRFuncPtr*) &mSymbols.fWaitSync,       { "WaitSync",       nullptr } },
   753                 { (PRFuncPtr*) &mSymbols.fGetInteger64v,  { "GetInteger64v",  nullptr } },
   754                 { (PRFuncPtr*) &mSymbols.fGetSynciv,      { "GetSynciv",      nullptr } },
   755                 { nullptr, { nullptr } },
   756             };
   758             if (!LoadSymbols(&syncSymbols[0], trygl, prefix)) {
   759                 NS_ERROR("GL supports ARB_sync without supplying its functions.");
   761                 MarkExtensionUnsupported(ARB_sync);
   762                 mSymbols.fFenceSync = nullptr;
   763                 mSymbols.fIsSync = nullptr;
   764                 mSymbols.fDeleteSync = nullptr;
   765                 mSymbols.fClientWaitSync = nullptr;
   766                 mSymbols.fWaitSync = nullptr;
   767                 mSymbols.fGetInteger64v = nullptr;
   768                 mSymbols.fGetSynciv = nullptr;
   769             }
   770         }
   772         if (IsExtensionSupported(OES_EGL_image)) {
   773             SymLoadStruct imageSymbols[] = {
   774                 { (PRFuncPtr*) &mSymbols.fEGLImageTargetTexture2D, { "EGLImageTargetTexture2DOES", nullptr } },
   775                 { (PRFuncPtr*) &mSymbols.fEGLImageTargetRenderbufferStorage, { "EGLImageTargetRenderbufferStorageOES", nullptr } },
   776                 { nullptr, { nullptr } },
   777             };
   779             if (!LoadSymbols(&imageSymbols[0], trygl, prefix)) {
   780                 NS_ERROR("GL supports OES_EGL_image without supplying its functions.");
   782                 MarkExtensionUnsupported(OES_EGL_image);
   783                 mSymbols.fEGLImageTargetTexture2D = nullptr;
   784                 mSymbols.fEGLImageTargetRenderbufferStorage = nullptr;
   785             }
   786         }
   788         if (IsExtensionSupported(APPLE_texture_range)) {
   789             SymLoadStruct vaoSymbols[] = {
   790                 { (PRFuncPtr*) &mSymbols.fTextureRangeAPPLE, { "TextureRangeAPPLE", nullptr } },
   791                 { nullptr, { nullptr } },
   792             };
   794             if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
   795                 mSymbols.fTextureRangeAPPLE = nullptr;
   796             }
   797         }
   799         if (IsExtensionSupported(ARB_vertex_array_object) ||
   800             IsExtensionSupported(OES_vertex_array_object)) {
   801             SymLoadStruct vaoSymbols[] = {
   802                 { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", "IsVertexArrayOES", nullptr } },
   803                 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", "GenVertexArraysOES", nullptr } },
   804                 { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", "BindVertexArrayOES", nullptr } },
   805                 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", "DeleteVertexArraysOES", nullptr } },
   806                 { nullptr, { nullptr } },
   807             };
   809             if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
   810                 NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
   812                 MarkUnsupported(GLFeature::vertex_array_object);
   813                 mSymbols.fIsVertexArray = nullptr;
   814                 mSymbols.fGenVertexArrays = nullptr;
   815                 mSymbols.fBindVertexArray = nullptr;
   816                 mSymbols.fDeleteVertexArrays = nullptr;
   817             }
   818         }
   819         else if (IsExtensionSupported(APPLE_vertex_array_object)) {
   820             /*
   821              * separate call to LoadSymbols with APPLE_vertex_array_object to work around
   822              * a driver bug : the IsVertexArray symbol (without suffix) can be present but unusable.
   823              */
   824             SymLoadStruct vaoSymbols[] = {
   825                 { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArrayAPPLE", nullptr } },
   826                 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArraysAPPLE", nullptr } },
   827                 { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrayAPPLE", nullptr } },
   828                 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArraysAPPLE", nullptr } },
   829                 { nullptr, { nullptr } },
   830             };
   832             if (!LoadSymbols(&vaoSymbols[0], trygl, prefix)) {
   833                 NS_ERROR("GL supports Vertex Array Object without supplying its functions.");
   835                 MarkUnsupported(GLFeature::vertex_array_object);
   836                 mSymbols.fIsVertexArray = nullptr;
   837                 mSymbols.fGenVertexArrays = nullptr;
   838                 mSymbols.fBindVertexArray = nullptr;
   839                 mSymbols.fDeleteVertexArrays = nullptr;
   840             }
   841         }
   843         if (IsSupported(GLFeature::draw_instanced)) {
   844             SymLoadStruct drawInstancedSymbols[] = {
   845                 { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced,
   846                   { "DrawArraysInstanced",
   847                     "DrawArraysInstancedARB",
   848                     "DrawArraysInstancedEXT",
   849                     "DrawArraysInstancedNV",
   850                     "DrawArraysInstancedANGLE",
   851                     nullptr
   852                   }
   853                 },
   854                 { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced,
   855                   { "DrawElementsInstanced",
   856                     "DrawElementsInstancedARB",
   857                     "DrawElementsInstancedEXT",
   858                     "DrawElementsInstancedNV",
   859                     "DrawElementsInstancedANGLE",
   860                     nullptr
   861                   }
   862                 },
   863                 { nullptr, { nullptr } },
   864             };
   866             if (!LoadSymbols(drawInstancedSymbols, trygl, prefix)) {
   867                 NS_ERROR("GL supports instanced draws without supplying its functions.");
   869                 MarkUnsupported(GLFeature::draw_instanced);
   870                 mSymbols.fDrawArraysInstanced = nullptr;
   871                 mSymbols.fDrawElementsInstanced = nullptr;
   872             }
   873         }
   875         if (IsSupported(GLFeature::instanced_arrays)) {
   876             SymLoadStruct instancedArraySymbols[] = {
   877                 { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor,
   878                   { "VertexAttribDivisor",
   879                     "VertexAttribDivisorARB",
   880                     "VertexAttribDivisorNV",
   881                     "VertexAttribDivisorANGLE",
   882                     nullptr
   883                   }
   884                 },
   885                 { nullptr, { nullptr } },
   886             };
   888             if (!LoadSymbols(instancedArraySymbols, trygl, prefix)) {
   889                 NS_ERROR("GL supports array instanced without supplying it function.");
   891                 MarkUnsupported(GLFeature::instanced_arrays);
   892                 mSymbols.fVertexAttribDivisor = nullptr;
   893             }
   894         }
   896         if (IsSupported(GLFeature::transform_feedback)) {
   897             SymLoadStruct transformFeedbackSymbols[] = {
   898                 { (PRFuncPtr*) &mSymbols.fBindBufferBase,
   899                   { "BindBufferBase",
   900                     "BindBufferBaseEXT",
   901                     "BindBufferBaseNV",
   902                     nullptr
   903                   }
   904                 },
   905                 { (PRFuncPtr*) &mSymbols.fBindBufferRange,
   906                   { "BindBufferRange",
   907                     "BindBufferRangeEXT",
   908                     "BindBufferRangeNV",
   909                     nullptr
   910                   }
   911                 },
   912                 { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback,
   913                   { "BeginTransformFeedback",
   914                     "BeginTransformFeedbackEXT",
   915                     "BeginTransformFeedbackNV",
   916                     nullptr
   917                   }
   918                 },
   919                 { (PRFuncPtr*) &mSymbols.fEndTransformFeedback,
   920                   { "EndTransformFeedback",
   921                     "EndTransformFeedbackEXT",
   922                     "EndTransformFeedbackNV",
   923                     nullptr
   924                   }
   925                 },
   926                 { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings,
   927                   { "TransformFeedbackVaryings",
   928                     "TransformFeedbackVaryingsEXT",
   929                     "TransformFeedbackVaryingsNV",
   930                     nullptr
   931                   }
   932                 },
   933                 { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying,
   934                   { "GetTransformFeedbackVarying",
   935                     "GetTransformFeedbackVaryingEXT",
   936                     "GetTransformFeedbackVaryingNV",
   937                     nullptr
   938                   }
   939                 },
   940                 { (PRFuncPtr*) &mSymbols.fGetIntegeri_v,
   941                   { "GetIntegeri_v",
   942                     "GetIntegerIndexedvEXT",
   943                     "GetIntegerIndexedvNV",
   944                     nullptr
   945                   }
   946                 },
   947                 { nullptr, { nullptr } },
   948             };
   950             if (!LoadSymbols(transformFeedbackSymbols, trygl, prefix)) {
   951                 NS_ERROR("GL supports transform feedback without supplying its functions.");
   953                 MarkUnsupported(GLFeature::transform_feedback);
   954                 MarkUnsupported(GLFeature::bind_buffer_offset);
   955                 mSymbols.fBindBufferBase = nullptr;
   956                 mSymbols.fBindBufferRange = nullptr;
   957                 mSymbols.fBeginTransformFeedback = nullptr;
   958                 mSymbols.fEndTransformFeedback = nullptr;
   959                 mSymbols.fTransformFeedbackVaryings = nullptr;
   960                 mSymbols.fGetTransformFeedbackVarying = nullptr;
   961                 mSymbols.fGetIntegeri_v = nullptr;
   962             }
   963         }
   965         if (IsSupported(GLFeature::bind_buffer_offset)) {
   966             SymLoadStruct bindBufferOffsetSymbols[] = {
   967                 { (PRFuncPtr*) &mSymbols.fBindBufferOffset,
   968                   { "BindBufferOffset",
   969                     "BindBufferOffsetEXT",
   970                     "BindBufferOffsetNV",
   971                     nullptr
   972                   }
   973                 },
   974                 { nullptr, { nullptr } },
   975             };
   977             if (!LoadSymbols(bindBufferOffsetSymbols, trygl, prefix)) {
   978                 NS_ERROR("GL supports BindBufferOffset without supplying its function.");
   980                 MarkUnsupported(GLFeature::bind_buffer_offset);
   981                 mSymbols.fBindBufferOffset = nullptr;
   982             }
   983         }
   985         if (IsSupported(GLFeature::query_objects)) {
   986             SymLoadStruct queryObjectsSymbols[] = {
   987                 { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQuery", "BeginQueryEXT", nullptr } },
   988                 { (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueries", "GenQueriesEXT", nullptr } },
   989                 { (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueries", "DeleteQueriesEXT", nullptr } },
   990                 { (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQuery", "EndQueryEXT", nullptr } },
   991                 { (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryiv", "GetQueryivEXT", nullptr } },
   992                 { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuiv", "GetQueryObjectuivEXT", nullptr } },
   993                 { (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQuery", "IsQueryEXT", nullptr } },
   994                 { nullptr, { nullptr } },
   995             };
   997             if (!LoadSymbols(queryObjectsSymbols, trygl, prefix)) {
   998                 NS_ERROR("GL supports query objects without supplying its functions.");
  1000                 MarkUnsupported(GLFeature::query_objects);
  1001                 MarkUnsupported(GLFeature::get_query_object_iv);
  1002                 MarkUnsupported(GLFeature::occlusion_query);
  1003                 MarkUnsupported(GLFeature::occlusion_query_boolean);
  1004                 MarkUnsupported(GLFeature::occlusion_query2);
  1005                 mSymbols.fBeginQuery = nullptr;
  1006                 mSymbols.fGenQueries = nullptr;
  1007                 mSymbols.fDeleteQueries = nullptr;
  1008                 mSymbols.fEndQuery = nullptr;
  1009                 mSymbols.fGetQueryiv = nullptr;
  1010                 mSymbols.fGetQueryObjectuiv = nullptr;
  1011                 mSymbols.fIsQuery = nullptr;
  1015         if (IsSupported(GLFeature::get_query_object_iv)) {
  1016             SymLoadStruct queryObjectsSymbols[] = {
  1017                 { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectiv", "GetQueryObjectivEXT", nullptr } },
  1018                 { nullptr, { nullptr } },
  1019             };
  1021             if (!LoadSymbols(queryObjectsSymbols, trygl, prefix)) {
  1022                 NS_ERROR("GL supports query objects iv getter without supplying its function.");
  1024                 MarkUnsupported(GLFeature::get_query_object_iv);
  1025                 mSymbols.fGetQueryObjectiv = nullptr;
  1029         if (IsSupported(GLFeature::draw_buffers)) {
  1030             SymLoadStruct drawBuffersSymbols[] = {
  1031                 { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } },
  1032                 { nullptr, { nullptr } },
  1033             };
  1035             if (!LoadSymbols(drawBuffersSymbols, trygl, prefix)) {
  1036                 NS_ERROR("GL supports draw_buffers without supplying its functions.");
  1038                 MarkUnsupported(GLFeature::draw_buffers);
  1039                 mSymbols.fDrawBuffers = nullptr;
  1043         if (IsExtensionSupported(KHR_debug)) {
  1044             SymLoadStruct extSymbols[] = {
  1045                 { (PRFuncPtr*) &mSymbols.fDebugMessageControl,  { "DebugMessageControl",  "DebugMessageControlKHR",  nullptr } },
  1046                 { (PRFuncPtr*) &mSymbols.fDebugMessageInsert,   { "DebugMessageInsert",   "DebugMessageInsertKHR",   nullptr } },
  1047                 { (PRFuncPtr*) &mSymbols.fDebugMessageCallback, { "DebugMessageCallback", "DebugMessageCallbackKHR", nullptr } },
  1048                 { (PRFuncPtr*) &mSymbols.fGetDebugMessageLog,   { "GetDebugMessageLog",   "GetDebugMessageLogKHR",   nullptr } },
  1049                 { (PRFuncPtr*) &mSymbols.fGetPointerv,          { "GetPointerv",          "GetPointervKHR",          nullptr } },
  1050                 { (PRFuncPtr*) &mSymbols.fPushDebugGroup,       { "PushDebugGroup",       "PushDebugGroupKHR",       nullptr } },
  1051                 { (PRFuncPtr*) &mSymbols.fPopDebugGroup,        { "PopDebugGroup",        "PopDebugGroupKHR",        nullptr } },
  1052                 { (PRFuncPtr*) &mSymbols.fObjectLabel,          { "ObjectLabel",          "ObjectLabelKHR",          nullptr } },
  1053                 { (PRFuncPtr*) &mSymbols.fGetObjectLabel,       { "GetObjectLabel",       "GetObjectLabelKHR",       nullptr } },
  1054                 { (PRFuncPtr*) &mSymbols.fObjectPtrLabel,       { "ObjectPtrLabel",       "ObjectPtrLabelKHR",       nullptr } },
  1055                 { (PRFuncPtr*) &mSymbols.fGetObjectPtrLabel,    { "GetObjectPtrLabel",    "GetObjectPtrLabelKHR",    nullptr } },
  1056                 { nullptr, { nullptr } },
  1057             };
  1059             if (!LoadSymbols(&extSymbols[0], trygl, prefix)) {
  1060                 NS_ERROR("GL supports KHR_debug without supplying its functions.");
  1062                 MarkExtensionUnsupported(KHR_debug);
  1063                 mSymbols.fDebugMessageControl  = nullptr;
  1064                 mSymbols.fDebugMessageInsert   = nullptr;
  1065                 mSymbols.fDebugMessageCallback = nullptr;
  1066                 mSymbols.fGetDebugMessageLog   = nullptr;
  1067                 mSymbols.fGetPointerv          = nullptr;
  1068                 mSymbols.fPushDebugGroup       = nullptr;
  1069                 mSymbols.fPopDebugGroup        = nullptr;
  1070                 mSymbols.fObjectLabel          = nullptr;
  1071                 mSymbols.fGetObjectLabel       = nullptr;
  1072                 mSymbols.fObjectPtrLabel       = nullptr;
  1073                 mSymbols.fGetObjectPtrLabel    = nullptr;
  1077         if (IsSupported(GLFeature::draw_range_elements)) {
  1078             SymLoadStruct imageSymbols[] = {
  1079                 { (PRFuncPtr*) &mSymbols.fDrawRangeElements, { "DrawRangeElementsEXT", "DrawRangeElements", nullptr } },
  1080                 { nullptr, { nullptr } },
  1081             };
  1083             if (!LoadSymbols(&imageSymbols[0], trygl, prefix)) {
  1084                 NS_ERROR("GL supports draw_range_elements without supplying its functions.");
  1086                 MarkUnsupported(GLFeature::draw_range_elements);
  1087                 mSymbols.fDrawRangeElements = nullptr;
  1091         // Load developer symbols, don't fail if we can't find them.
  1092         SymLoadStruct auxSymbols[] = {
  1093                 { (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", nullptr } },
  1094                 { (PRFuncPtr*) &mSymbols.fGetTexLevelParameteriv, { "GetTexLevelParameteriv", nullptr } },
  1095                 { nullptr, { nullptr } },
  1096         };
  1097         bool warnOnFailures = DebugMode();
  1098         LoadSymbols(&auxSymbols[0], trygl, prefix, warnOnFailures);
  1101     if (mInitialized) {
  1102         raw_fGetIntegerv(LOCAL_GL_VIEWPORT, mViewportRect);
  1103         raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mScissorRect);
  1104         raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
  1105         raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
  1106         raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
  1108 #ifdef XP_MACOSX
  1109         if (mWorkAroundDriverBugs) {
  1110             if (mVendor == GLVendor::Intel) {
  1111                 // see bug 737182 for 2D textures, bug 684882 for cube map textures.
  1112                 mMaxTextureSize        = std::min(mMaxTextureSize,        4096);
  1113                 mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 512);
  1114                 // for good measure, we align renderbuffers on what we do for 2D textures
  1115                 mMaxRenderbufferSize   = std::min(mMaxRenderbufferSize,   4096);
  1116                 mNeedsTextureSizeChecks = true;
  1117             } else if (mVendor == GLVendor::NVIDIA) {
  1118                 if (nsCocoaFeatures::OnMountainLionOrLater()) {
  1119                     // See bug 879656.  8192 fails, 8191 works.
  1120                     mMaxTextureSize = std::min(mMaxTextureSize, 8191);
  1121                     mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 8191);
  1123                 else {
  1124                     // See bug 877949.
  1125                     mMaxTextureSize = std::min(mMaxTextureSize, 4096);
  1126                     mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096);
  1129                 // Part of the bug 879656, but it also doesn't hurt the 877949
  1130                 mNeedsTextureSizeChecks = true;
  1133 #endif
  1134 #ifdef MOZ_X11
  1135         if (mWorkAroundDriverBugs &&
  1136             mVendor == GLVendor::Nouveau) {
  1137             // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau.
  1138             mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 2048);
  1139             mNeedsTextureSizeChecks = true;
  1141 #endif
  1143         mMaxTextureImageSize = mMaxTextureSize;
  1145         mMaxSamples = 0;
  1146         if (IsSupported(GLFeature::framebuffer_multisample)) {
  1147             fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples);
  1150         // We're ready for final setup.
  1151         fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
  1153         if (mCaps.any)
  1154             DetermineCaps();
  1156         UpdatePixelFormat();
  1157         UpdateGLFormats(mCaps);
  1159         mTexGarbageBin = new TextureGarbageBin(this);
  1161         MOZ_ASSERT(IsCurrent());
  1164     if (mInitialized)
  1165         reporter.SetSuccessful();
  1166     else {
  1167         // if initialization fails, ensure all symbols are zero, to avoid hard-to-understand bugs
  1168         mSymbols.Zero();
  1169         NS_WARNING("InitWithPrefix failed!");
  1172     mVersionString = nsPrintfCString("%u.%u.%u", mVersion / 100, (mVersion / 10) % 10, mVersion % 10);
  1174     return mInitialized;
  1177 void
  1178 GLContext::InitExtensions()
  1180     MakeCurrent();
  1181     const char* extensions = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
  1182     if (!extensions)
  1183         return;
  1185 #ifdef DEBUG
  1186     static bool firstRun = true;
  1187 #else
  1188     // Non-DEBUG, so never spew.
  1189     const bool firstRun = false;
  1190 #endif
  1192     InitializeExtensionsBitSet(mAvailableExtensions, extensions, sExtensionNames, firstRun && DebugMode());
  1194     if (WorkAroundDriverBugs() &&
  1195         Vendor() == GLVendor::Qualcomm) {
  1197         // Some Adreno drivers do not report GL_OES_EGL_sync, but they really do support it.
  1198         MarkExtensionSupported(OES_EGL_sync);
  1201     if (WorkAroundDriverBugs() &&
  1202         Renderer() == GLRenderer::AndroidEmulator) {
  1203         // the Android emulator, which we use to run B2G reftests on,
  1204         // doesn't expose the OES_rgb8_rgba8 extension, but it seems to
  1205         // support it (tautologically, as it only runs on desktop GL).
  1206         MarkExtensionSupported(OES_rgb8_rgba8);
  1209     if (WorkAroundDriverBugs() &&
  1210         Vendor() == GLVendor::VMware &&
  1211         Renderer() == GLRenderer::GalliumLlvmpipe)
  1213         // The llvmpipe driver that is used on linux try servers appears to have
  1214         // buggy support for s3tc/dxt1 compressed textures.
  1215         // See Bug 975824.
  1216         MarkExtensionUnsupported(EXT_texture_compression_s3tc);
  1217         MarkExtensionUnsupported(EXT_texture_compression_dxt1);
  1218         MarkExtensionUnsupported(ANGLE_texture_compression_dxt3);
  1219         MarkExtensionUnsupported(ANGLE_texture_compression_dxt5);
  1222 #ifdef DEBUG
  1223     firstRun = false;
  1224 #endif
  1227 void
  1228 GLContext::PlatformStartup()
  1230   RegisterStrongMemoryReporter(new GfxTexturesReporter());
  1233 // Common code for checking for both GL extensions and GLX extensions.
  1234 bool
  1235 GLContext::ListHasExtension(const GLubyte *extensions, const char *extension)
  1237     // fix bug 612572 - we were crashing as we were calling this function with extensions==null
  1238     if (extensions == nullptr || extension == nullptr)
  1239         return false;
  1241     const GLubyte *start;
  1242     GLubyte *where, *terminator;
  1244     /* Extension names should not have spaces. */
  1245     where = (GLubyte *) strchr(extension, ' ');
  1246     if (where || *extension == '\0')
  1247         return false;
  1249     /*
  1250      * It takes a bit of care to be fool-proof about parsing the
  1251      * OpenGL extensions string. Don't be fooled by sub-strings,
  1252      * etc.
  1253      */
  1254     start = extensions;
  1255     for (;;) {
  1256         where = (GLubyte *) strstr((const char *) start, extension);
  1257         if (!where) {
  1258             break;
  1260         terminator = where + strlen(extension);
  1261         if (where == start || *(where - 1) == ' ') {
  1262             if (*terminator == ' ' || *terminator == '\0') {
  1263                 return true;
  1266         start = terminator;
  1268     return false;
  1271 void
  1272 GLContext::DetermineCaps()
  1274     PixelBufferFormat format = QueryPixelFormat();
  1276     SurfaceCaps caps;
  1277     caps.color = !!format.red && !!format.green && !!format.blue;
  1278     caps.bpp16 = caps.color && format.ColorBits() == 16;
  1279     caps.alpha = !!format.alpha;
  1280     caps.depth = !!format.depth;
  1281     caps.stencil = !!format.stencil;
  1282     caps.antialias = format.samples > 1;
  1283     caps.preserve = true;
  1285     mCaps = caps;
  1288 PixelBufferFormat
  1289 GLContext::QueryPixelFormat()
  1291     PixelBufferFormat format;
  1293     ScopedBindFramebuffer autoFB(this, 0);
  1295     fGetIntegerv(LOCAL_GL_RED_BITS  , &format.red  );
  1296     fGetIntegerv(LOCAL_GL_GREEN_BITS, &format.green);
  1297     fGetIntegerv(LOCAL_GL_BLUE_BITS , &format.blue );
  1298     fGetIntegerv(LOCAL_GL_ALPHA_BITS, &format.alpha);
  1300     fGetIntegerv(LOCAL_GL_DEPTH_BITS, &format.depth);
  1301     fGetIntegerv(LOCAL_GL_STENCIL_BITS, &format.stencil);
  1303     fGetIntegerv(LOCAL_GL_SAMPLES, &format.samples);
  1305     return format;
  1308 void
  1309 GLContext::UpdatePixelFormat()
  1311     PixelBufferFormat format = QueryPixelFormat();
  1312 #ifdef DEBUG
  1313     const SurfaceCaps& caps = Caps();
  1314     MOZ_ASSERT(!caps.any, "Did you forget to DetermineCaps()?");
  1316     MOZ_ASSERT(caps.color == !!format.red);
  1317     MOZ_ASSERT(caps.color == !!format.green);
  1318     MOZ_ASSERT(caps.color == !!format.blue);
  1320     MOZ_ASSERT(caps.alpha == !!format.alpha);
  1322     // These we either must have if they're requested, or
  1323     // we can have if they're not.
  1324     MOZ_ASSERT(caps.depth == !!format.depth || !caps.depth);
  1325     MOZ_ASSERT(caps.stencil == !!format.stencil || !caps.stencil);
  1327     MOZ_ASSERT(caps.antialias == (format.samples > 1));
  1328 #endif
  1329     mPixelFormat = new PixelBufferFormat(format);
  1332 GLFormats
  1333 GLContext::ChooseGLFormats(const SurfaceCaps& caps) const
  1335     GLFormats formats;
  1337     // If we're on ES2 hardware and we have an explicit request for 16 bits of color or less
  1338     // OR we don't support full 8-bit color, return a 4444 or 565 format.
  1339     bool bpp16 = caps.bpp16;
  1340     if (IsGLES()) {
  1341         if (!IsExtensionSupported(OES_rgb8_rgba8))
  1342             bpp16 = true;
  1343     } else {
  1344         // RGB565 is uncommon on desktop, requiring ARB_ES2_compatibility.
  1345         // Since it's also vanishingly useless there, let's not support it.
  1346         bpp16 = false;
  1349     if (bpp16) {
  1350         MOZ_ASSERT(IsGLES());
  1351         if (caps.alpha) {
  1352             formats.color_texInternalFormat = LOCAL_GL_RGBA;
  1353             formats.color_texFormat = LOCAL_GL_RGBA;
  1354             formats.color_texType   = LOCAL_GL_UNSIGNED_SHORT_4_4_4_4;
  1355             formats.color_rbFormat  = LOCAL_GL_RGBA4;
  1356         } else {
  1357             formats.color_texInternalFormat = LOCAL_GL_RGB;
  1358             formats.color_texFormat = LOCAL_GL_RGB;
  1359             formats.color_texType   = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
  1360             formats.color_rbFormat  = LOCAL_GL_RGB565;
  1362     } else {
  1363         formats.color_texType = LOCAL_GL_UNSIGNED_BYTE;
  1365         if (caps.alpha) {
  1366             formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGBA : LOCAL_GL_RGBA8;
  1367             formats.color_texFormat = LOCAL_GL_RGBA;
  1368             formats.color_rbFormat  = LOCAL_GL_RGBA8;
  1369         } else {
  1370             formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGB : LOCAL_GL_RGB8;
  1371             formats.color_texFormat = LOCAL_GL_RGB;
  1372             formats.color_rbFormat  = LOCAL_GL_RGB8;
  1376     uint32_t msaaLevel = gfxPrefs::MSAALevel();
  1377     GLsizei samples = msaaLevel * msaaLevel;
  1378     samples = std::min(samples, mMaxSamples);
  1380     // Bug 778765.
  1381     if (WorkAroundDriverBugs() && samples == 1) {
  1382         samples = 0;
  1384     formats.samples = samples;
  1387     // Be clear that these are 0 if unavailable.
  1388     formats.depthStencil = 0;
  1389     if (!IsGLES() || IsExtensionSupported(OES_packed_depth_stencil)) {
  1390         formats.depthStencil = LOCAL_GL_DEPTH24_STENCIL8;
  1393     formats.depth = 0;
  1394     if (IsGLES()) {
  1395         if (IsExtensionSupported(OES_depth24)) {
  1396             formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
  1397         } else {
  1398             formats.depth = LOCAL_GL_DEPTH_COMPONENT16;
  1400     } else {
  1401         formats.depth = LOCAL_GL_DEPTH_COMPONENT24;
  1404     formats.stencil = LOCAL_GL_STENCIL_INDEX8;
  1406     return formats;
  1409 bool
  1410 GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus)
  1412     MOZ_ASSERT(fb);
  1414     ScopedBindFramebuffer autoFB(this, fb);
  1415     MOZ_ASSERT(fIsFramebuffer(fb));
  1417     GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
  1418     if (pStatus)
  1419         *pStatus = status;
  1421     return status == LOCAL_GL_FRAMEBUFFER_COMPLETE;
  1424 void
  1425 GLContext::AttachBuffersToFB(GLuint colorTex, GLuint colorRB,
  1426                              GLuint depthRB, GLuint stencilRB,
  1427                              GLuint fb, GLenum target)
  1429     MOZ_ASSERT(fb);
  1430     MOZ_ASSERT( !(colorTex && colorRB) );
  1432     ScopedBindFramebuffer autoFB(this, fb);
  1433     MOZ_ASSERT(fIsFramebuffer(fb)); // It only counts after being bound.
  1435     if (colorTex) {
  1436         MOZ_ASSERT(fIsTexture(colorTex));
  1437         MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
  1438                    target == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
  1439         fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
  1440                               LOCAL_GL_COLOR_ATTACHMENT0,
  1441                               target,
  1442                               colorTex,
  1443                               0);
  1444     } else if (colorRB) {
  1445         MOZ_ASSERT(fIsRenderbuffer(colorRB));
  1446         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
  1447                                  LOCAL_GL_COLOR_ATTACHMENT0,
  1448                                  LOCAL_GL_RENDERBUFFER,
  1449                                  colorRB);
  1452     if (depthRB) {
  1453         MOZ_ASSERT(fIsRenderbuffer(depthRB));
  1454         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
  1455                                  LOCAL_GL_DEPTH_ATTACHMENT,
  1456                                  LOCAL_GL_RENDERBUFFER,
  1457                                  depthRB);
  1460     if (stencilRB) {
  1461         MOZ_ASSERT(fIsRenderbuffer(stencilRB));
  1462         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
  1463                                  LOCAL_GL_STENCIL_ATTACHMENT,
  1464                                  LOCAL_GL_RENDERBUFFER,
  1465                                  stencilRB);
  1469 bool
  1470 GLContext::AssembleOffscreenFBs(const GLuint colorMSRB,
  1471                                 const GLuint depthRB,
  1472                                 const GLuint stencilRB,
  1473                                 const GLuint texture,
  1474                                 GLuint* drawFB_out,
  1475                                 GLuint* readFB_out)
  1477     if (!colorMSRB && !texture) {
  1478         MOZ_ASSERT(!depthRB && !stencilRB);
  1480         if (drawFB_out)
  1481             *drawFB_out = 0;
  1482         if (readFB_out)
  1483             *readFB_out = 0;
  1485         return true;
  1488     ScopedBindFramebuffer autoFB(this);
  1490     GLuint drawFB = 0;
  1491     GLuint readFB = 0;
  1493     if (texture) {
  1494         readFB = 0;
  1495         fGenFramebuffers(1, &readFB);
  1496         BindFB(readFB);
  1497         fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
  1498                               LOCAL_GL_COLOR_ATTACHMENT0,
  1499                               LOCAL_GL_TEXTURE_2D,
  1500                               texture,
  1501                               0);
  1504     if (colorMSRB) {
  1505         drawFB = 0;
  1506         fGenFramebuffers(1, &drawFB);
  1507         BindFB(drawFB);
  1508         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
  1509                                  LOCAL_GL_COLOR_ATTACHMENT0,
  1510                                  LOCAL_GL_RENDERBUFFER,
  1511                                  colorMSRB);
  1512     } else {
  1513         drawFB = readFB;
  1515     MOZ_ASSERT(GetFB() == drawFB);
  1517     if (depthRB) {
  1518         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
  1519                                  LOCAL_GL_DEPTH_ATTACHMENT,
  1520                                  LOCAL_GL_RENDERBUFFER,
  1521                                  depthRB);
  1524     if (stencilRB) {
  1525         fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
  1526                                  LOCAL_GL_STENCIL_ATTACHMENT,
  1527                                  LOCAL_GL_RENDERBUFFER,
  1528                                  stencilRB);
  1531     // We should be all resized.  Check for framebuffer completeness.
  1532     GLenum status;
  1533     bool isComplete = true;
  1535     if (!IsFramebufferComplete(drawFB, &status)) {
  1536         NS_WARNING("DrawFBO: Incomplete");
  1537   #ifdef DEBUG
  1538         if (DebugMode()) {
  1539             printf_stderr("Framebuffer status: %X\n", status);
  1541   #endif
  1542         isComplete = false;
  1545     if (!IsFramebufferComplete(readFB, &status)) {
  1546         NS_WARNING("ReadFBO: Incomplete");
  1547   #ifdef DEBUG
  1548         if (DebugMode()) {
  1549             printf_stderr("Framebuffer status: %X\n", status);
  1551   #endif
  1552         isComplete = false;
  1555     if (drawFB_out) {
  1556         *drawFB_out = drawFB;
  1557     } else if (drawFB) {
  1558         NS_RUNTIMEABORT("drawFB created when not requested!");
  1561     if (readFB_out) {
  1562         *readFB_out = readFB;
  1563     } else if (readFB) {
  1564         NS_RUNTIMEABORT("readFB created when not requested!");
  1567     return isComplete;
  1572 bool
  1573 GLContext::PublishFrame()
  1575     MOZ_ASSERT(mScreen);
  1577     if (!mScreen->PublishFrame(OffscreenSize()))
  1578         return false;
  1580     return true;
  1583 SharedSurface_GL*
  1584 GLContext::RequestFrame()
  1586     MOZ_ASSERT(mScreen);
  1588     SharedSurface* ret = mScreen->Stream()->SwapConsumer();
  1589     if (!ret)
  1590         return nullptr;
  1592     return SharedSurface_GL::Cast(ret);
  1597 void
  1598 GLContext::ClearSafely()
  1600     // bug 659349 --- we must be very careful here: clearing a GL framebuffer is nontrivial, relies on a lot of state,
  1601     // and in the case of the backbuffer of a WebGL context, state is exposed to scripts.
  1602     //
  1603     // The code here is taken from WebGLContext::ForceClearFramebufferWithDefaultValues, but I didn't find a good way of
  1604     // sharing code with it. WebGL's code is somewhat performance-critical as it is typically called on every frame, so
  1605     // WebGL keeps track of GL state to avoid having to query it everytime, and also tries to only do work for actually
  1606     // present buffers (e.g. stencil buffer). Doing that here seems like premature optimization,
  1607     // as ClearSafely() is called only when e.g. a canvas is resized, not on every animation frame.
  1609     realGLboolean scissorTestEnabled;
  1610     realGLboolean ditherEnabled;
  1611     realGLboolean colorWriteMask[4];
  1612     realGLboolean depthWriteMask;
  1613     GLint stencilWriteMaskFront, stencilWriteMaskBack;
  1614     GLfloat colorClearValue[4];
  1615     GLfloat depthClearValue;
  1616     GLint stencilClearValue;
  1618     // save current GL state
  1619     fGetBooleanv(LOCAL_GL_SCISSOR_TEST, &scissorTestEnabled);
  1620     fGetBooleanv(LOCAL_GL_DITHER, &ditherEnabled);
  1621     fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
  1622     fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
  1623     fGetIntegerv(LOCAL_GL_STENCIL_WRITEMASK, &stencilWriteMaskFront);
  1624     fGetIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK, &stencilWriteMaskBack);
  1625     fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);
  1626     fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
  1627     fGetIntegerv(LOCAL_GL_STENCIL_CLEAR_VALUE, &stencilClearValue);
  1629     // prepare GL state for clearing
  1630     fDisable(LOCAL_GL_SCISSOR_TEST);
  1631     fDisable(LOCAL_GL_DITHER);
  1633     fColorMask(1, 1, 1, 1);
  1634     fClearColor(0.f, 0.f, 0.f, 0.f);
  1636     fDepthMask(1);
  1637     fClearDepth(1.0f);
  1639     fStencilMask(0xffffffff);
  1640     fClearStencil(0);
  1642     // do clear
  1643     fClear(LOCAL_GL_COLOR_BUFFER_BIT |
  1644            LOCAL_GL_DEPTH_BUFFER_BIT |
  1645            LOCAL_GL_STENCIL_BUFFER_BIT);
  1647     // restore GL state after clearing
  1648     fColorMask(colorWriteMask[0],
  1649                colorWriteMask[1],
  1650                colorWriteMask[2],
  1651                colorWriteMask[3]);
  1652     fClearColor(colorClearValue[0],
  1653                 colorClearValue[1],
  1654                 colorClearValue[2],
  1655                 colorClearValue[3]);
  1657     fDepthMask(depthWriteMask);
  1658     fClearDepth(depthClearValue);
  1660     fStencilMaskSeparate(LOCAL_GL_FRONT, stencilWriteMaskFront);
  1661     fStencilMaskSeparate(LOCAL_GL_BACK, stencilWriteMaskBack);
  1662     fClearStencil(stencilClearValue);
  1664     if (ditherEnabled)
  1665         fEnable(LOCAL_GL_DITHER);
  1666     else
  1667         fDisable(LOCAL_GL_DITHER);
  1669     if (scissorTestEnabled)
  1670         fEnable(LOCAL_GL_SCISSOR_TEST);
  1671     else
  1672         fDisable(LOCAL_GL_SCISSOR_TEST);
  1676 void
  1677 GLContext::MarkDestroyed()
  1679     if (IsDestroyed())
  1680         return;
  1682     if (MakeCurrent()) {
  1683         DestroyScreenBuffer();
  1685         mBlitHelper = nullptr;
  1686         mBlitTextureImageHelper = nullptr;
  1687         mReadTexImageHelper = nullptr;
  1689         mTexGarbageBin->GLContextTeardown();
  1690     } else {
  1691         NS_WARNING("MakeCurrent() failed during MarkDestroyed! Skipping GL object teardown.");
  1694     mSymbols.Zero();
  1697 #ifdef MOZ_ENABLE_GL_TRACKING
  1698 void
  1699 GLContext::CreatedProgram(GLContext *aOrigin, GLuint aName)
  1701     mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName));
  1704 void
  1705 GLContext::CreatedShader(GLContext *aOrigin, GLuint aName)
  1707     mTrackedShaders.AppendElement(NamedResource(aOrigin, aName));
  1710 void
  1711 GLContext::CreatedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
  1713     for (GLsizei i = 0; i < aCount; ++i) {
  1714         mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
  1718 void
  1719 GLContext::CreatedQueries(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
  1721     for (GLsizei i = 0; i < aCount; ++i) {
  1722         mTrackedQueries.AppendElement(NamedResource(aOrigin, aNames[i]));
  1726 void
  1727 GLContext::CreatedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
  1729     for (GLsizei i = 0; i < aCount; ++i) {
  1730         mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i]));
  1734 void
  1735 GLContext::CreatedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
  1737     for (GLsizei i = 0; i < aCount; ++i) {
  1738         mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
  1742 void
  1743 GLContext::CreatedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames)
  1745     for (GLsizei i = 0; i < aCount; ++i) {
  1746         mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
  1750 static void
  1751 RemoveNamesFromArray(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames, nsTArray<GLContext::NamedResource>& aArray)
  1753     for (GLsizei j = 0; j < aCount; ++j) {
  1754         GLuint name = aNames[j];
  1755         // name 0 can be ignored
  1756         if (name == 0)
  1757             continue;
  1759         for (uint32_t i = 0; i < aArray.Length(); ++i) {
  1760             if (aArray[i].name == name) {
  1761                 aArray.RemoveElementAt(i);
  1762                 break;
  1768 void
  1769 GLContext::DeletedProgram(GLContext *aOrigin, GLuint aName)
  1771     RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms);
  1774 void
  1775 GLContext::DeletedShader(GLContext *aOrigin, GLuint aName)
  1777     RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders);
  1780 void
  1781 GLContext::DeletedBuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
  1783     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers);
  1786 void
  1787 GLContext::DeletedQueries(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
  1789     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedQueries);
  1792 void
  1793 GLContext::DeletedTextures(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
  1795     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures);
  1798 void
  1799 GLContext::DeletedFramebuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
  1801     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers);
  1804 void
  1805 GLContext::DeletedRenderbuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames)
  1807     RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers);
  1810 static void
  1811 MarkContextDestroyedInArray(GLContext *aContext, nsTArray<GLContext::NamedResource>& aArray)
  1813     for (uint32_t i = 0; i < aArray.Length(); ++i) {
  1814         if (aArray[i].origin == aContext)
  1815             aArray[i].originDeleted = true;
  1819 void
  1820 GLContext::SharedContextDestroyed(GLContext *aChild)
  1822     MarkContextDestroyedInArray(aChild, mTrackedPrograms);
  1823     MarkContextDestroyedInArray(aChild, mTrackedShaders);
  1824     MarkContextDestroyedInArray(aChild, mTrackedTextures);
  1825     MarkContextDestroyedInArray(aChild, mTrackedFramebuffers);
  1826     MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers);
  1827     MarkContextDestroyedInArray(aChild, mTrackedBuffers);
  1828     MarkContextDestroyedInArray(aChild, mTrackedQueries);
  1831 static void
  1832 ReportArrayContents(const char *title, const nsTArray<GLContext::NamedResource>& aArray)
  1834     if (aArray.Length() == 0)
  1835         return;
  1837     printf_stderr("%s:\n", title);
  1839     nsTArray<GLContext::NamedResource> copy(aArray);
  1840     copy.Sort();
  1842     GLContext *lastContext = nullptr;
  1843     for (uint32_t i = 0; i < copy.Length(); ++i) {
  1844         if (lastContext != copy[i].origin) {
  1845             if (lastContext)
  1846                 printf_stderr("\n");
  1847             printf_stderr("  [%p - %s] ", copy[i].origin, copy[i].originDeleted ? "deleted" : "live");
  1848             lastContext = copy[i].origin;
  1850         printf_stderr("%d ", copy[i].name);
  1852     printf_stderr("\n");
  1855 void
  1856 GLContext::ReportOutstandingNames()
  1858     if (!DebugMode())
  1859         return;
  1861     printf_stderr("== GLContext %p Outstanding ==\n", this);
  1863     ReportArrayContents("Outstanding Textures", mTrackedTextures);
  1864     ReportArrayContents("Outstanding Buffers", mTrackedBuffers);
  1865     ReportArrayContents("Outstanding Queries", mTrackedQueries);
  1866     ReportArrayContents("Outstanding Programs", mTrackedPrograms);
  1867     ReportArrayContents("Outstanding Shaders", mTrackedShaders);
  1868     ReportArrayContents("Outstanding Framebuffers", mTrackedFramebuffers);
  1869     ReportArrayContents("Outstanding Renderbuffers", mTrackedRenderbuffers);
  1872 #endif /* DEBUG */
  1875 void
  1876 GLContext::GuaranteeResolve()
  1878     if (mScreen) {
  1879         mScreen->AssureBlitted();
  1881     fFinish();
  1884 const gfx::IntSize&
  1885 GLContext::OffscreenSize() const
  1887     MOZ_ASSERT(IsOffscreen());
  1888     return mScreen->Size();
  1891 bool
  1892 GLContext::CreateScreenBufferImpl(const IntSize& size, const SurfaceCaps& caps)
  1894     GLScreenBuffer* newScreen = GLScreenBuffer::Create(this, size, caps);
  1895     if (!newScreen)
  1896         return false;
  1898     if (!newScreen->Resize(size)) {
  1899         delete newScreen;
  1900         return false;
  1903     DestroyScreenBuffer();
  1905     // This will rebind to 0 (Screen) if needed when
  1906     // it falls out of scope.
  1907     ScopedBindFramebuffer autoFB(this);
  1909     mScreen = newScreen;
  1911     return true;
  1914 bool
  1915 GLContext::ResizeScreenBuffer(const IntSize& size)
  1917     if (!IsOffscreenSizeAllowed(size))
  1918         return false;
  1920     return mScreen->Resize(size);
  1924 void
  1925 GLContext::DestroyScreenBuffer()
  1927     delete mScreen;
  1928     mScreen = nullptr;
  1931 void
  1932 GLContext::ForceDirtyScreen()
  1934     ScopedBindFramebuffer autoFB(0);
  1936     BeforeGLDrawCall();
  1937     // no-op; just pretend we did something
  1938     AfterGLDrawCall();
  1941 void
  1942 GLContext::CleanDirtyScreen()
  1944     ScopedBindFramebuffer autoFB(0);
  1946     BeforeGLReadCall();
  1947     // no-op; we just want to make sure the Read FBO is updated if it needs to be
  1948     AfterGLReadCall();
  1951 void
  1952 GLContext::EmptyTexGarbageBin()
  1954    TexGarbageBin()->EmptyGarbage();
  1957 bool
  1958 GLContext::IsOffscreenSizeAllowed(const IntSize& aSize) const {
  1959   int32_t biggerDimension = std::max(aSize.width, aSize.height);
  1960   int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize);
  1961   return biggerDimension <= maxAllowed;
  1964 bool
  1965 GLContext::IsOwningThreadCurrent()
  1967   return NS_GetCurrentThread() == mOwningThread;
  1970 void
  1971 GLContext::DispatchToOwningThread(nsIRunnable *event)
  1973     // Before dispatching, we need to ensure we're not in the middle of
  1974     // shutting down. Dispatching runnables in the middle of shutdown
  1975     // (that is, when the main thread is no longer get-able) can cause them
  1976     // to leak. See Bug 741319, and Bug 744115.
  1977     nsCOMPtr<nsIThread> mainThread;
  1978     if (NS_SUCCEEDED(NS_GetMainThread(getter_AddRefs(mainThread)))) {
  1979         mOwningThread->Dispatch(event, NS_DISPATCH_NORMAL);
  1983 GLBlitHelper*
  1984 GLContext::BlitHelper()
  1986     if (!mBlitHelper) {
  1987         mBlitHelper = new GLBlitHelper(this);
  1990     return mBlitHelper;
  1993 GLBlitTextureImageHelper*
  1994 GLContext::BlitTextureImageHelper()
  1996     if (!mBlitTextureImageHelper) {
  1997         mBlitTextureImageHelper = new GLBlitTextureImageHelper(this);
  2000     return mBlitTextureImageHelper;
  2003 GLReadTexImageHelper*
  2004 GLContext::ReadTexImageHelper()
  2006     if (!mReadTexImageHelper) {
  2007         mReadTexImageHelper = new GLReadTexImageHelper(this);
  2010     return mReadTexImageHelper;
  2013 bool
  2014 DoesStringMatch(const char* aString, const char *aWantedString)
  2016     if (!aString || !aWantedString)
  2017         return false;
  2019     const char *occurrence = strstr(aString, aWantedString);
  2021     // aWanted not found
  2022     if (!occurrence)
  2023         return false;
  2025     // aWantedString preceded by alpha character
  2026     if (occurrence != aString && isalpha(*(occurrence-1)))
  2027         return false;
  2029     // aWantedVendor followed by alpha character
  2030     const char *afterOccurrence = occurrence + strlen(aWantedString);
  2031     if (isalpha(*afterOccurrence))
  2032         return false;
  2034     return true;
  2037 } /* namespace gl */
  2038 } /* namespace mozilla */

mercurial