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