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