1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 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 #if defined(XP_LINUX) && !defined(ANDROID)
20 // For MesaMemoryLeakWorkaround
21 #  include <dlfcn.h>
22 #  include <link.h>
23 #endif
24 
25 #include "GLBlitHelper.h"
26 #include "GLReadTexImageHelper.h"
27 #include "GLScreenBuffer.h"
28 
29 #include "gfxCrashReporterUtils.h"
30 #include "gfxEnv.h"
31 #include "gfxUtils.h"
32 #include "GLContextProvider.h"
33 #include "GLLibraryLoader.h"
34 #include "GLTextureImage.h"
35 #include "nsPrintfCString.h"
36 #include "nsThreadUtils.h"
37 #include "prenv.h"
38 #include "prlink.h"
39 #include "ScopedGLHelpers.h"
40 #include "SharedSurfaceGL.h"
41 #include "GfxTexturesReporter.h"
42 #include "gfx2DGlue.h"
43 #include "mozilla/StaticPrefs_gfx.h"
44 #include "mozilla/StaticPrefs_gl.h"
45 #include "mozilla/IntegerPrintfMacros.h"
46 #include "mozilla/gfx/Logging.h"
47 #include "mozilla/layers/BuildConstants.h"
48 #include "mozilla/layers/TextureForwarder.h"  // for LayersIPCChannel
49 
50 #include "OGLShaderProgram.h"  // for ShaderProgramType
51 
52 #include "mozilla/DebugOnly.h"
53 #include "mozilla/Maybe.h"
54 
55 #ifdef XP_MACOSX
56 #  include <CoreServices/CoreServices.h>
57 #endif
58 
59 #if defined(MOZ_WIDGET_COCOA)
60 #  include "nsCocoaFeatures.h"
61 #endif
62 
63 #ifdef MOZ_WIDGET_ANDROID
64 #  include "mozilla/jni/Utils.h"
65 #endif
66 
67 namespace mozilla {
68 namespace gl {
69 
70 using namespace mozilla::gfx;
71 using namespace mozilla::layers;
72 
73 MOZ_THREAD_LOCAL(uintptr_t) GLContext::sCurrentContext;
74 
75 // If adding defines, don't forget to undefine symbols. See #undef block below.
76 // clang-format off
77 #define CORE_SYMBOL(x) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x }} }
78 #define CORE_EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x, "gl" #x #y, "gl" #x #z }} }
79 #define EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x #y, "gl" #x #z }} }
80 #define EXT_SYMBOL3(x,y,z,w) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x #y, "gl" #x #z, "gl" #x #w }} }
81 #define END_SYMBOLS { nullptr, {} }
82 // clang-format on
83 
84 // should match the order of GLExtensions, and be null-terminated.
85 static const char* const sExtensionNames[] = {
86     "NO_EXTENSION",
87     "GL_AMD_compressed_ATC_texture",
88     "GL_ANGLE_depth_texture",
89     "GL_ANGLE_framebuffer_blit",
90     "GL_ANGLE_framebuffer_multisample",
91     "GL_ANGLE_instanced_arrays",
92     "GL_ANGLE_multiview",
93     "GL_ANGLE_texture_compression_dxt3",
94     "GL_ANGLE_texture_compression_dxt5",
95     "GL_ANGLE_timer_query",
96     "GL_APPLE_client_storage",
97     "GL_APPLE_fence",
98     "GL_APPLE_framebuffer_multisample",
99     "GL_APPLE_sync",
100     "GL_APPLE_texture_range",
101     "GL_APPLE_vertex_array_object",
102     "GL_ARB_ES2_compatibility",
103     "GL_ARB_ES3_compatibility",
104     "GL_ARB_color_buffer_float",
105     "GL_ARB_compatibility",
106     "GL_ARB_copy_buffer",
107     "GL_ARB_depth_texture",
108     "GL_ARB_draw_buffers",
109     "GL_ARB_draw_instanced",
110     "GL_ARB_framebuffer_object",
111     "GL_ARB_framebuffer_sRGB",
112     "GL_ARB_geometry_shader4",
113     "GL_ARB_half_float_pixel",
114     "GL_ARB_instanced_arrays",
115     "GL_ARB_internalformat_query",
116     "GL_ARB_invalidate_subdata",
117     "GL_ARB_map_buffer_range",
118     "GL_ARB_occlusion_query2",
119     "GL_ARB_pixel_buffer_object",
120     "GL_ARB_robust_buffer_access_behavior",
121     "GL_ARB_robustness",
122     "GL_ARB_sampler_objects",
123     "GL_ARB_seamless_cube_map",
124     "GL_ARB_shader_texture_lod",
125     "GL_ARB_sync",
126     "GL_ARB_texture_compression",
127     "GL_ARB_texture_compression_bptc",
128     "GL_ARB_texture_compression_rgtc",
129     "GL_ARB_texture_float",
130     "GL_ARB_texture_non_power_of_two",
131     "GL_ARB_texture_rectangle",
132     "GL_ARB_texture_rg",
133     "GL_ARB_texture_storage",
134     "GL_ARB_texture_swizzle",
135     "GL_ARB_timer_query",
136     "GL_ARB_transform_feedback2",
137     "GL_ARB_uniform_buffer_object",
138     "GL_ARB_vertex_array_object",
139     "GL_CHROMIUM_color_buffer_float_rgb",
140     "GL_CHROMIUM_color_buffer_float_rgba",
141     "GL_EXT_bgra",
142     "GL_EXT_blend_minmax",
143     "GL_EXT_color_buffer_float",
144     "GL_EXT_color_buffer_half_float",
145     "GL_EXT_copy_texture",
146     "GL_EXT_disjoint_timer_query",
147     "GL_EXT_draw_buffers",
148     "GL_EXT_draw_buffers2",
149     "GL_EXT_draw_instanced",
150     "GL_EXT_float_blend",
151     "GL_EXT_frag_depth",
152     "GL_EXT_framebuffer_blit",
153     "GL_EXT_framebuffer_multisample",
154     "GL_EXT_framebuffer_object",
155     "GL_EXT_framebuffer_sRGB",
156     "GL_EXT_gpu_shader4",
157     "GL_EXT_map_buffer_range",
158     "GL_EXT_multisampled_render_to_texture",
159     "GL_EXT_occlusion_query_boolean",
160     "GL_EXT_packed_depth_stencil",
161     "GL_EXT_read_format_bgra",
162     "GL_EXT_robustness",
163     "GL_EXT_sRGB",
164     "GL_EXT_sRGB_write_control",
165     "GL_EXT_shader_texture_lod",
166     "GL_EXT_texture_compression_bptc",
167     "GL_EXT_texture_compression_dxt1",
168     "GL_EXT_texture_compression_rgtc",
169     "GL_EXT_texture_compression_s3tc",
170     "GL_EXT_texture_compression_s3tc_srgb",
171     "GL_EXT_texture_filter_anisotropic",
172     "GL_EXT_texture_format_BGRA8888",
173     "GL_EXT_texture_norm16",
174     "GL_EXT_texture_sRGB",
175     "GL_EXT_texture_storage",
176     "GL_EXT_timer_query",
177     "GL_EXT_transform_feedback",
178     "GL_EXT_unpack_subimage",
179     "GL_IMG_read_format",
180     "GL_IMG_texture_compression_pvrtc",
181     "GL_IMG_texture_npot",
182     "GL_KHR_debug",
183     "GL_KHR_parallel_shader_compile",
184     "GL_KHR_robust_buffer_access_behavior",
185     "GL_KHR_robustness",
186     "GL_KHR_texture_compression_astc_hdr",
187     "GL_KHR_texture_compression_astc_ldr",
188     "GL_NV_draw_instanced",
189     "GL_NV_fence",
190     "GL_NV_framebuffer_blit",
191     "GL_NV_geometry_program4",
192     "GL_NV_half_float",
193     "GL_NV_instanced_arrays",
194     "GL_NV_primitive_restart",
195     "GL_NV_texture_barrier",
196     "GL_NV_transform_feedback",
197     "GL_NV_transform_feedback2",
198     "GL_OES_EGL_image",
199     "GL_OES_EGL_image_external",
200     "GL_OES_EGL_sync",
201     "GL_OES_compressed_ETC1_RGB8_texture",
202     "GL_OES_depth24",
203     "GL_OES_depth32",
204     "GL_OES_depth_texture",
205     "GL_OES_draw_buffers_indexed",
206     "GL_OES_element_index_uint",
207     "GL_OES_fbo_render_mipmap",
208     "GL_OES_framebuffer_object",
209     "GL_OES_packed_depth_stencil",
210     "GL_OES_rgb8_rgba8",
211     "GL_OES_standard_derivatives",
212     "GL_OES_stencil8",
213     "GL_OES_texture_3D",
214     "GL_OES_texture_float",
215     "GL_OES_texture_float_linear",
216     "GL_OES_texture_half_float",
217     "GL_OES_texture_half_float_linear",
218     "GL_OES_texture_npot",
219     "GL_OES_vertex_array_object",
220     "GL_OVR_multiview2"};
221 
ShouldUseTLSIsCurrent(bool useTLSIsCurrent)222 static bool ShouldUseTLSIsCurrent(bool useTLSIsCurrent) {
223   if (StaticPrefs::gl_use_tls_is_current() == 0) {
224     return useTLSIsCurrent;
225   }
226 
227   return StaticPrefs::gl_use_tls_is_current() > 0;
228 }
229 
ParseVersion(const std::string & versionStr,uint32_t * const out_major,uint32_t * const out_minor)230 static bool ParseVersion(const std::string& versionStr,
231                          uint32_t* const out_major, uint32_t* const out_minor) {
232   static const std::regex kVersionRegex("([0-9]+)\\.([0-9]+)");
233   std::smatch match;
234   if (!std::regex_search(versionStr, match, kVersionRegex)) return false;
235 
236   const auto& majorStr = match.str(1);
237   const auto& minorStr = match.str(2);
238   *out_major = atoi(majorStr.c_str());
239   *out_minor = atoi(minorStr.c_str());
240   return true;
241 }
242 
243 /*static*/
ChooseDebugFlags(const CreateContextFlags createFlags)244 uint8_t GLContext::ChooseDebugFlags(const CreateContextFlags createFlags) {
245   uint8_t debugFlags = 0;
246 
247 #ifdef MOZ_GL_DEBUG
248   if (gfxEnv::GlDebug()) {
249     debugFlags |= GLContext::DebugFlagEnabled;
250   }
251 
252   // Enables extra verbose output, informing of the start and finish of every GL
253   // call. Useful e.g. to record information to investigate graphics system
254   // crashes/lockups
255   if (gfxEnv::GlDebugVerbose()) {
256     debugFlags |= GLContext::DebugFlagTrace;
257   }
258 
259   // Aborts on GL error. Can be useful to debug quicker code that is known not
260   // to generate any GL error in principle.
261   bool abortOnError = false;
262 
263   if (createFlags & CreateContextFlags::NO_VALIDATION) {
264     abortOnError = true;
265 
266     const auto fnStringsMatch = [](const char* a, const char* b) {
267       return strcmp(a, b) == 0;
268     };
269 
270     const char* envAbortOnError = PR_GetEnv("MOZ_GL_DEBUG_ABORT_ON_ERROR");
271     if (envAbortOnError && fnStringsMatch(envAbortOnError, "0")) {
272       abortOnError = false;
273     }
274   }
275 
276   if (abortOnError) {
277     debugFlags |= GLContext::DebugFlagAbortOnError;
278   }
279 #endif
280 
281   return debugFlags;
282 }
283 
GLContext(const GLContextDesc & desc,GLContext * sharedContext,bool useTLSIsCurrent)284 GLContext::GLContext(const GLContextDesc& desc, GLContext* sharedContext,
285                      bool useTLSIsCurrent)
286     : mDesc(desc),
287       mUseTLSIsCurrent(ShouldUseTLSIsCurrent(useTLSIsCurrent)),
288       mDebugFlags(ChooseDebugFlags(mDesc.flags)),
289       mSharedContext(sharedContext),
290       mWorkAroundDriverBugs(
291           StaticPrefs::gfx_work_around_driver_bugs_AtStartup()) {
292   mOwningThreadId = PlatformThread::CurrentId();
293   MOZ_ALWAYS_TRUE(sCurrentContext.init());
294   sCurrentContext.set(0);
295 }
296 
~GLContext()297 GLContext::~GLContext() {
298   NS_ASSERTION(
299       IsDestroyed(),
300       "GLContext implementation must call MarkDestroyed in destructor!");
301 #ifdef MOZ_GL_DEBUG
302   if (mSharedContext) {
303     GLContext* tip = mSharedContext;
304     while (tip->mSharedContext) tip = tip->mSharedContext;
305     tip->SharedContextDestroyed(this);
306     tip->ReportOutstandingNames();
307   } else {
308     ReportOutstandingNames();
309   }
310 #endif
311 }
312 
313 /*static*/
StaticDebugCallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const GLvoid * userParam)314 void GLContext::StaticDebugCallback(GLenum source, GLenum type, GLuint id,
315                                     GLenum severity, GLsizei length,
316                                     const GLchar* message,
317                                     const GLvoid* userParam) {
318   GLContext* gl = (GLContext*)userParam;
319   gl->DebugCallback(source, type, id, severity, length, message);
320 }
321 
Init()322 bool GLContext::Init() {
323   MOZ_RELEASE_ASSERT(!mSymbols.fBindFramebuffer,
324                      "GFX: GLContext::Init should only be called once.");
325 
326   ScopedGfxFeatureReporter reporter("GL Context");
327 
328   if (!InitImpl()) {
329     // If initialization fails, zero the symbols to avoid hard-to-understand
330     // bugs.
331     mSymbols = {};
332     NS_WARNING("GLContext::InitWithPrefix failed!");
333     return false;
334   }
335 
336   reporter.SetSuccessful();
337   return true;
338 }
339 
LoadSymbolsWithDesc(const SymbolLoader & loader,const SymLoadStruct * list,const char * desc)340 static bool LoadSymbolsWithDesc(const SymbolLoader& loader,
341                                 const SymLoadStruct* list, const char* desc) {
342   const auto warnOnFailure = bool(desc);
343   if (loader.LoadSymbols(list, warnOnFailure)) return true;
344 
345   ClearSymbols(list);
346 
347   if (desc) {
348     const nsPrintfCString err("Failed to load symbols for %s.", desc);
349     NS_ERROR(err.BeginReading());
350   }
351   return false;
352 }
353 
LoadExtSymbols(const SymbolLoader & loader,const SymLoadStruct * list,GLExtensions ext)354 bool GLContext::LoadExtSymbols(const SymbolLoader& loader,
355                                const SymLoadStruct* list, GLExtensions ext) {
356   const char* extName = sExtensionNames[size_t(ext)];
357   if (!LoadSymbolsWithDesc(loader, list, extName)) {
358     MarkExtensionUnsupported(ext);
359     return false;
360   }
361   return true;
362 };
363 
LoadFeatureSymbols(const SymbolLoader & loader,const SymLoadStruct * list,GLFeature feature)364 bool GLContext::LoadFeatureSymbols(const SymbolLoader& loader,
365                                    const SymLoadStruct* list,
366                                    GLFeature feature) {
367   const char* featureName = GetFeatureName(feature);
368   if (!LoadSymbolsWithDesc(loader, list, featureName)) {
369     MarkUnsupported(feature);
370     return false;
371   }
372   return true;
373 };
374 
InitImpl()375 bool GLContext::InitImpl() {
376   if (!MakeCurrent(true)) return false;
377 
378   const auto loader = GetSymbolLoader();
379   if (!loader) return false;
380 
381   const auto fnLoadSymbols = [&](const SymLoadStruct* const list,
382                                  const char* const desc) {
383     return LoadSymbolsWithDesc(*loader, list, desc);
384   };
385 
386   // clang-format off
387     const SymLoadStruct coreSymbols[] = {
388         { (PRFuncPtr*) &mSymbols.fActiveTexture, {{ "glActiveTexture", "glActiveTextureARB" }} },
389         { (PRFuncPtr*) &mSymbols.fAttachShader, {{ "glAttachShader", "glAttachShaderARB" }} },
390         { (PRFuncPtr*) &mSymbols.fBindAttribLocation, {{ "glBindAttribLocation", "glBindAttribLocationARB" }} },
391         { (PRFuncPtr*) &mSymbols.fBindBuffer, {{ "glBindBuffer", "glBindBufferARB" }} },
392         { (PRFuncPtr*) &mSymbols.fBindTexture, {{ "glBindTexture", "glBindTextureARB" }} },
393         { (PRFuncPtr*) &mSymbols.fBlendColor, {{ "glBlendColor" }} },
394         { (PRFuncPtr*) &mSymbols.fBlendEquation, {{ "glBlendEquation" }} },
395         { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, {{ "glBlendEquationSeparate", "glBlendEquationSeparateEXT" }} },
396         { (PRFuncPtr*) &mSymbols.fBlendFunc, {{ "glBlendFunc" }} },
397         { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, {{ "glBlendFuncSeparate", "glBlendFuncSeparateEXT" }} },
398         { (PRFuncPtr*) &mSymbols.fBufferData, {{ "glBufferData" }} },
399         { (PRFuncPtr*) &mSymbols.fBufferSubData, {{ "glBufferSubData" }} },
400         { (PRFuncPtr*) &mSymbols.fClear, {{ "glClear" }} },
401         { (PRFuncPtr*) &mSymbols.fClearColor, {{ "glClearColor" }} },
402         { (PRFuncPtr*) &mSymbols.fClearStencil, {{ "glClearStencil" }} },
403         { (PRFuncPtr*) &mSymbols.fColorMask, {{ "glColorMask" }} },
404         { (PRFuncPtr*) &mSymbols.fCompressedTexImage2D, {{ "glCompressedTexImage2D" }} },
405         { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage2D, {{ "glCompressedTexSubImage2D" }} },
406         { (PRFuncPtr*) &mSymbols.fCullFace, {{ "glCullFace" }} },
407         { (PRFuncPtr*) &mSymbols.fDetachShader, {{ "glDetachShader", "glDetachShaderARB" }} },
408         { (PRFuncPtr*) &mSymbols.fDepthFunc, {{ "glDepthFunc" }} },
409         { (PRFuncPtr*) &mSymbols.fDepthMask, {{ "glDepthMask" }} },
410         { (PRFuncPtr*) &mSymbols.fDisable, {{ "glDisable" }} },
411         { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, {{ "glDisableVertexAttribArray", "glDisableVertexAttribArrayARB" }} },
412         { (PRFuncPtr*) &mSymbols.fDrawArrays, {{ "glDrawArrays" }} },
413         { (PRFuncPtr*) &mSymbols.fDrawElements, {{ "glDrawElements" }} },
414         { (PRFuncPtr*) &mSymbols.fEnable, {{ "glEnable" }} },
415         { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, {{ "glEnableVertexAttribArray", "glEnableVertexAttribArrayARB" }} },
416         { (PRFuncPtr*) &mSymbols.fFinish, {{ "glFinish" }} },
417         { (PRFuncPtr*) &mSymbols.fFlush, {{ "glFlush" }} },
418         { (PRFuncPtr*) &mSymbols.fFrontFace, {{ "glFrontFace" }} },
419         { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, {{ "glGetActiveAttrib", "glGetActiveAttribARB" }} },
420         { (PRFuncPtr*) &mSymbols.fGetActiveUniform, {{ "glGetActiveUniform", "glGetActiveUniformARB" }} },
421         { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, {{ "glGetAttachedShaders", "glGetAttachedShadersARB" }} },
422         { (PRFuncPtr*) &mSymbols.fGetAttribLocation, {{ "glGetAttribLocation", "glGetAttribLocationARB" }} },
423         { (PRFuncPtr*) &mSymbols.fGetIntegerv, {{ "glGetIntegerv" }} },
424         { (PRFuncPtr*) &mSymbols.fGetFloatv, {{ "glGetFloatv" }} },
425         { (PRFuncPtr*) &mSymbols.fGetBooleanv, {{ "glGetBooleanv" }} },
426         { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, {{ "glGetBufferParameteriv", "glGetBufferParameterivARB" }} },
427         { (PRFuncPtr*) &mSymbols.fGetError, {{ "glGetError" }} },
428         { (PRFuncPtr*) &mSymbols.fGetProgramiv, {{ "glGetProgramiv", "glGetProgramivARB" }} },
429         { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, {{ "glGetProgramInfoLog", "glGetProgramInfoLogARB" }} },
430         { (PRFuncPtr*) &mSymbols.fTexParameteri, {{ "glTexParameteri" }} },
431         { (PRFuncPtr*) &mSymbols.fTexParameteriv, {{ "glTexParameteriv" }} },
432         { (PRFuncPtr*) &mSymbols.fTexParameterf, {{ "glTexParameterf" }} },
433         { (PRFuncPtr*) &mSymbols.fGetString, {{ "glGetString" }} },
434         { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, {{ "glGetTexParameterfv" }} },
435         { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, {{ "glGetTexParameteriv" }} },
436         { (PRFuncPtr*) &mSymbols.fGetUniformfv, {{ "glGetUniformfv", "glGetUniformfvARB" }} },
437         { (PRFuncPtr*) &mSymbols.fGetUniformiv, {{ "glGetUniformiv", "glGetUniformivARB" }} },
438         { (PRFuncPtr*) &mSymbols.fGetUniformLocation, {{ "glGetUniformLocation", "glGetUniformLocationARB" }} },
439         { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, {{ "glGetVertexAttribfv", "glGetVertexAttribfvARB" }} },
440         { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, {{ "glGetVertexAttribiv", "glGetVertexAttribivARB" }} },
441         { (PRFuncPtr*) &mSymbols.fGetVertexAttribPointerv, {{ "glGetVertexAttribPointerv" }} },
442         { (PRFuncPtr*) &mSymbols.fHint, {{ "glHint" }} },
443         { (PRFuncPtr*) &mSymbols.fIsBuffer, {{ "glIsBuffer", "glIsBufferARB" }} },
444         { (PRFuncPtr*) &mSymbols.fIsEnabled, {{ "glIsEnabled" }} },
445         { (PRFuncPtr*) &mSymbols.fIsProgram, {{ "glIsProgram", "glIsProgramARB" }} },
446         { (PRFuncPtr*) &mSymbols.fIsShader, {{ "glIsShader", "glIsShaderARB" }} },
447         { (PRFuncPtr*) &mSymbols.fIsTexture, {{ "glIsTexture", "glIsTextureARB" }} },
448         { (PRFuncPtr*) &mSymbols.fLineWidth, {{ "glLineWidth" }} },
449         { (PRFuncPtr*) &mSymbols.fLinkProgram, {{ "glLinkProgram", "glLinkProgramARB" }} },
450         { (PRFuncPtr*) &mSymbols.fPixelStorei, {{ "glPixelStorei" }} },
451         { (PRFuncPtr*) &mSymbols.fPolygonOffset, {{ "glPolygonOffset" }} },
452         { (PRFuncPtr*) &mSymbols.fReadPixels, {{ "glReadPixels" }} },
453         { (PRFuncPtr*) &mSymbols.fSampleCoverage, {{ "glSampleCoverage" }} },
454         { (PRFuncPtr*) &mSymbols.fScissor, {{ "glScissor" }} },
455         { (PRFuncPtr*) &mSymbols.fStencilFunc, {{ "glStencilFunc" }} },
456         { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, {{ "glStencilFuncSeparate", "glStencilFuncSeparateEXT" }} },
457         { (PRFuncPtr*) &mSymbols.fStencilMask, {{ "glStencilMask" }} },
458         { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, {{ "glStencilMaskSeparate", "glStencilMaskSeparateEXT" }} },
459         { (PRFuncPtr*) &mSymbols.fStencilOp, {{ "glStencilOp" }} },
460         { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, {{ "glStencilOpSeparate", "glStencilOpSeparateEXT" }} },
461         { (PRFuncPtr*) &mSymbols.fTexImage2D, {{ "glTexImage2D" }} },
462         { (PRFuncPtr*) &mSymbols.fTexSubImage2D, {{ "glTexSubImage2D" }} },
463         { (PRFuncPtr*) &mSymbols.fUniform1f, {{ "glUniform1f" }} },
464         { (PRFuncPtr*) &mSymbols.fUniform1fv, {{ "glUniform1fv" }} },
465         { (PRFuncPtr*) &mSymbols.fUniform1i, {{ "glUniform1i" }} },
466         { (PRFuncPtr*) &mSymbols.fUniform1iv, {{ "glUniform1iv" }} },
467         { (PRFuncPtr*) &mSymbols.fUniform2f, {{ "glUniform2f" }} },
468         { (PRFuncPtr*) &mSymbols.fUniform2fv, {{ "glUniform2fv" }} },
469         { (PRFuncPtr*) &mSymbols.fUniform2i, {{ "glUniform2i" }} },
470         { (PRFuncPtr*) &mSymbols.fUniform2iv, {{ "glUniform2iv" }} },
471         { (PRFuncPtr*) &mSymbols.fUniform3f, {{ "glUniform3f" }} },
472         { (PRFuncPtr*) &mSymbols.fUniform3fv, {{ "glUniform3fv" }} },
473         { (PRFuncPtr*) &mSymbols.fUniform3i, {{ "glUniform3i" }} },
474         { (PRFuncPtr*) &mSymbols.fUniform3iv, {{ "glUniform3iv" }} },
475         { (PRFuncPtr*) &mSymbols.fUniform4f, {{ "glUniform4f" }} },
476         { (PRFuncPtr*) &mSymbols.fUniform4fv, {{ "glUniform4fv" }} },
477         { (PRFuncPtr*) &mSymbols.fUniform4i, {{ "glUniform4i" }} },
478         { (PRFuncPtr*) &mSymbols.fUniform4iv, {{ "glUniform4iv" }} },
479         { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, {{ "glUniformMatrix2fv" }} },
480         { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, {{ "glUniformMatrix3fv" }} },
481         { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, {{ "glUniformMatrix4fv" }} },
482         { (PRFuncPtr*) &mSymbols.fUseProgram, {{ "glUseProgram" }} },
483         { (PRFuncPtr*) &mSymbols.fValidateProgram, {{ "glValidateProgram" }} },
484         { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, {{ "glVertexAttribPointer" }} },
485         { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, {{ "glVertexAttrib1f" }} },
486         { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, {{ "glVertexAttrib2f" }} },
487         { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, {{ "glVertexAttrib3f" }} },
488         { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, {{ "glVertexAttrib4f" }} },
489         { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, {{ "glVertexAttrib1fv" }} },
490         { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, {{ "glVertexAttrib2fv" }} },
491         { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, {{ "glVertexAttrib3fv" }} },
492         { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, {{ "glVertexAttrib4fv" }} },
493         { (PRFuncPtr*) &mSymbols.fViewport, {{ "glViewport" }} },
494         { (PRFuncPtr*) &mSymbols.fCompileShader, {{ "glCompileShader" }} },
495         { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, {{ "glCopyTexImage2D" }} },
496         { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, {{ "glCopyTexSubImage2D" }} },
497         { (PRFuncPtr*) &mSymbols.fGetShaderiv, {{ "glGetShaderiv" }} },
498         { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, {{ "glGetShaderInfoLog" }} },
499         { (PRFuncPtr*) &mSymbols.fGetShaderSource, {{ "glGetShaderSource" }} },
500         { (PRFuncPtr*) &mSymbols.fShaderSource, {{ "glShaderSource" }} },
501         { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, {{ "glVertexAttribPointer" }} },
502 
503         { (PRFuncPtr*) &mSymbols.fGenBuffers, {{ "glGenBuffers", "glGenBuffersARB" }} },
504         { (PRFuncPtr*) &mSymbols.fGenTextures, {{ "glGenTextures" }} },
505         { (PRFuncPtr*) &mSymbols.fCreateProgram, {{ "glCreateProgram", "glCreateProgramARB" }} },
506         { (PRFuncPtr*) &mSymbols.fCreateShader, {{ "glCreateShader", "glCreateShaderARB" }} },
507 
508         { (PRFuncPtr*) &mSymbols.fDeleteBuffers, {{ "glDeleteBuffers", "glDeleteBuffersARB" }} },
509         { (PRFuncPtr*) &mSymbols.fDeleteTextures, {{ "glDeleteTextures", "glDeleteTexturesARB" }} },
510         { (PRFuncPtr*) &mSymbols.fDeleteProgram, {{ "glDeleteProgram", "glDeleteProgramARB" }} },
511         { (PRFuncPtr*) &mSymbols.fDeleteShader, {{ "glDeleteShader", "glDeleteShaderARB" }} },
512 
513         END_SYMBOLS
514     };
515   // clang-format on
516 
517   if (!fnLoadSymbols(coreSymbols, "GL")) return false;
518 
519   {
520     const SymLoadStruct symbols[] = {
521         {(PRFuncPtr*)&mSymbols.fGetGraphicsResetStatus,
522          {{"glGetGraphicsResetStatus", "glGetGraphicsResetStatusARB",
523            "glGetGraphicsResetStatusKHR", "glGetGraphicsResetStatusEXT"}}},
524         END_SYMBOLS};
525     (void)fnLoadSymbols(symbols, nullptr);
526 
527     // We need to call the fGetError symbol directly here because if there is an
528     // unflushed reset status, we don't want to mark the context as lost. That
529     // would prevent us from recovering.
530     auto err = mSymbols.fGetError();
531     if (err == LOCAL_GL_CONTEXT_LOST) {
532       MOZ_ASSERT(mSymbols.fGetGraphicsResetStatus);
533       const auto status = fGetGraphicsResetStatus();
534       if (status) {
535         printf_stderr("Unflushed glGetGraphicsResetStatus: 0x%04x\n", status);
536       }
537       err = fGetError();
538       MOZ_ASSERT(!err);
539     }
540     if (err) {
541       MOZ_ASSERT(false);
542       return false;
543     }
544   }
545 
546   ////////////////
547 
548   const auto* const versionRawStr = (const char*)fGetString(LOCAL_GL_VERSION);
549   if (!versionRawStr || !*versionRawStr) {
550     // This can happen with Pernosco.
551     NS_WARNING("Empty GL version string");
552     return false;
553   }
554 
555   const std::string versionStr = versionRawStr;
556   if (versionStr.find("OpenGL ES") == 0) {
557     mProfile = ContextProfile::OpenGLES;
558   }
559 
560   uint32_t majorVer, minorVer;
561   if (!ParseVersion(versionStr, &majorVer, &minorVer)) {
562     MOZ_ASSERT(false, "Failed to parse GL_VERSION");
563     return false;
564   }
565   MOZ_ASSERT(majorVer < 10);
566   MOZ_ASSERT(minorVer < 10);
567   mVersion = majorVer * 100 + minorVer * 10;
568   if (mVersion < 200) return false;
569 
570   ////
571 
572   const auto glslVersionStr =
573       (const char*)fGetString(LOCAL_GL_SHADING_LANGUAGE_VERSION);
574   if (!glslVersionStr) {
575     // This happens on the Android emulators. We'll just return 100
576     mShadingLanguageVersion = 100;
577   } else if (ParseVersion(glslVersionStr, &majorVer, &minorVer)) {
578     MOZ_ASSERT(majorVer < 10);
579     MOZ_ASSERT(minorVer < 100);
580     mShadingLanguageVersion = majorVer * 100 + minorVer;
581   } else {
582     MOZ_ASSERT(false, "Failed to parse GL_SHADING_LANGUAGE_VERSION");
583     return false;
584   }
585 
586   if (ShouldSpew()) {
587     printf_stderr("GL version detected: %u\n", mVersion);
588     printf_stderr("GLSL version detected: %u\n", mShadingLanguageVersion);
589     printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR));
590     printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER));
591   }
592 
593   ////////////////
594 
595   // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
596   if (mProfile == ContextProfile::OpenGLES) {
597     const SymLoadStruct symbols[] = {CORE_SYMBOL(GetShaderPrecisionFormat),
598                                      CORE_SYMBOL(ClearDepthf),
599                                      CORE_SYMBOL(DepthRangef), END_SYMBOLS};
600 
601     if (!fnLoadSymbols(symbols, "OpenGL ES")) return false;
602   } else {
603     const SymLoadStruct symbols[] = {
604         CORE_SYMBOL(ClearDepth), CORE_SYMBOL(DepthRange),
605         CORE_SYMBOL(ReadBuffer), CORE_SYMBOL(MapBuffer),
606         CORE_SYMBOL(UnmapBuffer), CORE_SYMBOL(PointParameterf),
607         CORE_SYMBOL(DrawBuffer),
608         // The following functions are only used by Skia/GL in desktop mode.
609         // Other parts of Gecko should avoid using these
610         CORE_SYMBOL(DrawBuffers), CORE_SYMBOL(ClientActiveTexture),
611         CORE_SYMBOL(DisableClientState), CORE_SYMBOL(EnableClientState),
612         CORE_SYMBOL(LoadIdentity), CORE_SYMBOL(LoadMatrixf),
613         CORE_SYMBOL(MatrixMode), CORE_SYMBOL(PolygonMode), CORE_SYMBOL(TexGeni),
614         CORE_SYMBOL(TexGenf), CORE_SYMBOL(TexGenfv), CORE_SYMBOL(VertexPointer),
615         END_SYMBOLS};
616 
617     if (!fnLoadSymbols(symbols, "Desktop OpenGL")) return false;
618   }
619 
620   ////////////////
621 
622   const char* glVendorString = (const char*)fGetString(LOCAL_GL_VENDOR);
623   const char* glRendererString = (const char*)fGetString(LOCAL_GL_RENDERER);
624   if (!glVendorString || !glRendererString) return false;
625 
626   // The order of these strings must match up with the order of the enum
627   // defined in GLContext.h for vendor IDs.
628   const char* vendorMatchStrings[size_t(GLVendor::Other) + 1] = {
629       "Intel",   "NVIDIA",  "ATI",          "Qualcomm", "Imagination",
630       "nouveau", "Vivante", "VMware, Inc.", "ARM",      "Unknown"};
631 
632   mVendor = GLVendor::Other;
633   for (size_t i = 0; i < size_t(GLVendor::Other); ++i) {
634     if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
635       mVendor = GLVendor(i);
636       break;
637     }
638   }
639 
640   // The order of these strings must match up with the order of the enum
641   // defined in GLContext.h for renderer IDs.
642   const char* rendererMatchStrings[size_t(GLRenderer::Other) + 1] = {
643       "Adreno 200",
644       "Adreno 205",
645       "Adreno (TM) 200",
646       "Adreno (TM) 205",
647       "Adreno (TM) 305",
648       "Adreno (TM) 320",
649       "Adreno (TM) 330",
650       "Adreno (TM) 420",
651       "Mali-400 MP",
652       "Mali-450 MP",
653       "PowerVR SGX 530",
654       "PowerVR SGX 540",
655       "PowerVR SGX 544MP",
656       "NVIDIA Tegra",
657       "Android Emulator",
658       "Gallium 0.4 on llvmpipe",
659       "Intel HD Graphics 3000 OpenGL Engine",
660       "Microsoft Basic Render Driver",
661       "Unknown"};
662 
663   mRenderer = GLRenderer::Other;
664   for (size_t i = 0; i < size_t(GLRenderer::Other); ++i) {
665     if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) {
666       mRenderer = GLRenderer(i);
667       break;
668     }
669   }
670 
671   {
672     const auto versionStr = (const char*)fGetString(LOCAL_GL_VERSION);
673     if (strstr(versionStr, "Mesa")) {
674       mIsMesa = true;
675     }
676   }
677 
678   const auto Once = []() {
679     static bool did = false;
680     if (did) return false;
681     did = true;
682     return true;
683   };
684 
685   bool printRenderer = ShouldSpew();
686   printRenderer |= (kIsDebug && Once());
687   if (printRenderer) {
688     printf_stderr("GL_VENDOR: %s\n", glVendorString);
689     printf_stderr("mVendor: %s\n", vendorMatchStrings[size_t(mVendor)]);
690     printf_stderr("GL_RENDERER: %s\n", glRendererString);
691     printf_stderr("mRenderer: %s\n", rendererMatchStrings[size_t(mRenderer)]);
692     printf_stderr("mIsMesa: %i\n", int(mIsMesa));
693   }
694 
695   ////////////////
696 
697   if (mVersion >= 300) {  // Both GL3 and ES3.
698     const SymLoadStruct symbols[] = {
699         {(PRFuncPtr*)&mSymbols.fGetStringi, {{"glGetStringi"}}}, END_SYMBOLS};
700 
701     if (!fnLoadSymbols(symbols, "GetStringi")) {
702       MOZ_RELEASE_ASSERT(false, "GFX: GetStringi is required!");
703       return false;
704     }
705   }
706 
707   InitExtensions();
708   if (mProfile != ContextProfile::OpenGLES) {
709     if (mVersion >= 310 && !IsExtensionSupported(ARB_compatibility)) {
710       mProfile = ContextProfile::OpenGLCore;
711     } else {
712       mProfile = ContextProfile::OpenGLCompatibility;
713     }
714   }
715   MOZ_ASSERT(mProfile != ContextProfile::Unknown);
716 
717   if (ShouldSpew()) {
718     const char* profileStr = "";
719     if (mProfile == ContextProfile::OpenGLES) {
720       profileStr = " es";
721     } else if (mProfile == ContextProfile::OpenGLCore) {
722       profileStr = " core";
723     }
724     printf_stderr("Detected profile: %u%s\n", mVersion, profileStr);
725   }
726 
727   InitFeatures();
728 
729   ////
730 
731   // Disable extensions with partial or incorrect support.
732   if (WorkAroundDriverBugs()) {
733     if (Renderer() == GLRenderer::AdrenoTM320) {
734       MarkUnsupported(GLFeature::standard_derivatives);
735     }
736 
737     if (Renderer() == GLRenderer::AndroidEmulator) {
738       // Bug 1665300
739       mSymbols.fGetGraphicsResetStatus = 0;
740     }
741 
742     if (Vendor() == GLVendor::Vivante) {
743       // bug 958256
744       MarkUnsupported(GLFeature::standard_derivatives);
745     }
746 
747     if (Renderer() == GLRenderer::MicrosoftBasicRenderDriver) {
748       // Bug 978966: on Microsoft's "Basic Render Driver" (software renderer)
749       // multisampling hardcodes blending with the default blendfunc, which
750       // breaks WebGL.
751       MarkUnsupported(GLFeature::framebuffer_multisample);
752     }
753 
754     if (IsMesa()) {
755       // DrawElementsInstanced hangs the driver.
756       MarkUnsupported(GLFeature::robust_buffer_access_behavior);
757     }
758   }
759 
760   if (IsExtensionSupported(GLContext::ARB_pixel_buffer_object)) {
761     MOZ_ASSERT(
762         (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
763         "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer"
764         " being available!");
765   }
766 
767   ////////////////////////////////////////////////////////////////////////////
768 
769   const auto fnLoadForFeature = [&](const SymLoadStruct* list,
770                                     GLFeature feature) {
771     return this->LoadFeatureSymbols(*loader, list, feature);
772   };
773 
774   // Check for ARB_framebuffer_objects
775   if (IsSupported(GLFeature::framebuffer_object)) {
776     // https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
777     const SymLoadStruct symbols[] = {
778         CORE_SYMBOL(IsRenderbuffer),
779         CORE_SYMBOL(BindRenderbuffer),
780         CORE_SYMBOL(DeleteRenderbuffers),
781         CORE_SYMBOL(GenRenderbuffers),
782         CORE_SYMBOL(RenderbufferStorage),
783         CORE_SYMBOL(RenderbufferStorageMultisample),
784         CORE_SYMBOL(GetRenderbufferParameteriv),
785         CORE_SYMBOL(IsFramebuffer),
786         CORE_SYMBOL(BindFramebuffer),
787         CORE_SYMBOL(DeleteFramebuffers),
788         CORE_SYMBOL(GenFramebuffers),
789         CORE_SYMBOL(CheckFramebufferStatus),
790         CORE_SYMBOL(FramebufferTexture2D),
791         CORE_SYMBOL(FramebufferTextureLayer),
792         CORE_SYMBOL(FramebufferRenderbuffer),
793         CORE_SYMBOL(GetFramebufferAttachmentParameteriv),
794         CORE_SYMBOL(BlitFramebuffer),
795         CORE_SYMBOL(GenerateMipmap),
796         END_SYMBOLS};
797     fnLoadForFeature(symbols, GLFeature::framebuffer_object);
798   }
799 
800   if (!IsSupported(GLFeature::framebuffer_object)) {
801     // Check for aux symbols based on extensions
802     if (IsSupported(GLFeature::framebuffer_object_EXT_OES)) {
803       const SymLoadStruct symbols[] = {
804           CORE_EXT_SYMBOL2(IsRenderbuffer, EXT, OES),
805           CORE_EXT_SYMBOL2(BindRenderbuffer, EXT, OES),
806           CORE_EXT_SYMBOL2(DeleteRenderbuffers, EXT, OES),
807           CORE_EXT_SYMBOL2(GenRenderbuffers, EXT, OES),
808           CORE_EXT_SYMBOL2(RenderbufferStorage, EXT, OES),
809           CORE_EXT_SYMBOL2(GetRenderbufferParameteriv, EXT, OES),
810           CORE_EXT_SYMBOL2(IsFramebuffer, EXT, OES),
811           CORE_EXT_SYMBOL2(BindFramebuffer, EXT, OES),
812           CORE_EXT_SYMBOL2(DeleteFramebuffers, EXT, OES),
813           CORE_EXT_SYMBOL2(GenFramebuffers, EXT, OES),
814           CORE_EXT_SYMBOL2(CheckFramebufferStatus, EXT, OES),
815           CORE_EXT_SYMBOL2(FramebufferTexture2D, EXT, OES),
816           CORE_EXT_SYMBOL2(FramebufferRenderbuffer, EXT, OES),
817           CORE_EXT_SYMBOL2(GetFramebufferAttachmentParameteriv, EXT, OES),
818           CORE_EXT_SYMBOL2(GenerateMipmap, EXT, OES),
819           END_SYMBOLS};
820       fnLoadForFeature(symbols, GLFeature::framebuffer_object_EXT_OES);
821     }
822 
823     if (IsSupported(GLFeature::framebuffer_blit)) {
824       const SymLoadStruct symbols[] = {
825           EXT_SYMBOL3(BlitFramebuffer, ANGLE, EXT, NV), END_SYMBOLS};
826       fnLoadForFeature(symbols, GLFeature::framebuffer_blit);
827     }
828 
829     if (IsSupported(GLFeature::framebuffer_multisample)) {
830       const SymLoadStruct symbols[] = {
831           EXT_SYMBOL3(RenderbufferStorageMultisample, ANGLE, APPLE, EXT),
832           END_SYMBOLS};
833       fnLoadForFeature(symbols, GLFeature::framebuffer_multisample);
834     }
835 
836     if (IsExtensionSupported(GLContext::ARB_geometry_shader4) ||
837         IsExtensionSupported(GLContext::NV_geometry_program4)) {
838       const SymLoadStruct symbols[] = {
839           EXT_SYMBOL2(FramebufferTextureLayer, ARB, EXT), END_SYMBOLS};
840       if (!fnLoadSymbols(symbols,
841                          "ARB_geometry_shader4/NV_geometry_program4")) {
842         MarkExtensionUnsupported(GLContext::ARB_geometry_shader4);
843         MarkExtensionUnsupported(GLContext::NV_geometry_program4);
844       }
845     }
846   }
847 
848   if (!IsSupported(GLFeature::framebuffer_object) &&
849       !IsSupported(GLFeature::framebuffer_object_EXT_OES)) {
850     NS_ERROR("GLContext requires support for framebuffer objects.");
851     return false;
852   }
853   MOZ_RELEASE_ASSERT(mSymbols.fBindFramebuffer,
854                      "GFX: mSymbols.fBindFramebuffer zero or not set.");
855 
856   ////////////////
857 
858   const auto err = fGetError();
859   MOZ_RELEASE_ASSERT(!IsBadCallError(err));
860   if (err) return false;
861 
862   LoadMoreSymbols(*loader);
863 
864   ////////////////////////////////////////////////////////////////////////////
865 
866   raw_fGetIntegerv(LOCAL_GL_VIEWPORT, mViewportRect);
867   raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mScissorRect);
868   raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
869   raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
870   raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
871   raw_fGetIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
872 
873   if (mWorkAroundDriverBugs) {
874     int maxTexSize = INT32_MAX;
875     int maxCubeSize = INT32_MAX;
876 #ifdef XP_MACOSX
877     if (!nsCocoaFeatures::IsAtLeastVersion(10, 12)) {
878       if (mVendor == GLVendor::Intel) {
879         // see bug 737182 for 2D textures, bug 684882 for cube map textures.
880         maxTexSize = 4096;
881         maxCubeSize = 512;
882       } else if (mVendor == GLVendor::NVIDIA) {
883         // See bug 879656.  8192 fails, 8191 works.
884         maxTexSize = 8191;
885       }
886     } else {
887       // https://bugzilla.mozilla.org/show_bug.cgi?id=1544446
888       // Mojave exposes 16k textures, but gives FRAMEBUFFER_UNSUPPORTED for any
889       // 16k*16k FB except rgba8 without depth/stencil.
890       // The max supported sizes changes based on involved formats.
891       // (RGBA32F more restrictive than RGBA16F)
892       maxTexSize = 8192;
893     }
894 #endif
895 #ifdef MOZ_X11
896     if (mVendor == GLVendor::Nouveau) {
897       // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau.
898       maxCubeSize = 2048;
899     } else if (mVendor == GLVendor::Intel) {
900       // Bug 1199923. Driver seems to report a larger max size than
901       // actually supported.
902       maxTexSize = mMaxTextureSize / 2;
903     }
904     // Bug 1367570. Explicitly set vertex attributes [1,3] to opaque
905     // black because Nvidia doesn't do it for us.
906     if (mVendor == GLVendor::NVIDIA) {
907       for (size_t i = 1; i <= 3; ++i) {
908         mSymbols.fVertexAttrib4f(i, 0, 0, 0, 1);
909       }
910     }
911 #endif
912     if (Renderer() == GLRenderer::AdrenoTM420) {
913       // see bug 1194923. Calling glFlush before glDeleteFramebuffers
914       // prevents occasional driver crash.
915       mNeedsFlushBeforeDeleteFB = true;
916     }
917 #ifdef MOZ_WIDGET_ANDROID
918     if ((Renderer() == GLRenderer::AdrenoTM305 ||
919          Renderer() == GLRenderer::AdrenoTM320 ||
920          Renderer() == GLRenderer::AdrenoTM330) &&
921         jni::GetAPIVersion() < 21) {
922       // Bug 1164027. Driver crashes when functions such as
923       // glTexImage2D fail due to virtual memory exhaustion.
924       mTextureAllocCrashesOnMapFailure = true;
925     }
926 #endif
927 #if MOZ_WIDGET_ANDROID
928     if (Renderer() == GLRenderer::SGX540 && jni::GetAPIVersion() <= 15) {
929       // Bug 1288446. Driver sometimes crashes when uploading data to a
930       // texture if the render target has changed since the texture was
931       // rendered from. Calling glCheckFramebufferStatus after
932       // glFramebufferTexture2D prevents the crash.
933       mNeedsCheckAfterAttachTextureToFb = true;
934     }
935 #endif
936 
937     // -
938 
939     const auto fnLimit = [&](int* const driver, const int limit) {
940       if (*driver > limit) {
941         *driver = limit;
942         mNeedsTextureSizeChecks = true;
943       }
944     };
945 
946     fnLimit(&mMaxTextureSize, maxTexSize);
947     fnLimit(&mMaxRenderbufferSize, maxTexSize);
948 
949     maxCubeSize = std::min(maxCubeSize, maxTexSize);
950     fnLimit(&mMaxCubeMapTextureSize, maxCubeSize);
951   }
952 
953   if (IsSupported(GLFeature::framebuffer_multisample)) {
954     fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples);
955   }
956 
957   mMaxTexOrRbSize = std::min(mMaxTextureSize, mMaxRenderbufferSize);
958 
959   ////////////////////////////////////////////////////////////////////////////
960 
961   // We're ready for final setup.
962   fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
963   MOZ_GL_ASSERT(this, IsCurrent());
964 
965   if (ShouldSpew() && IsExtensionSupported(KHR_debug)) {
966     fEnable(LOCAL_GL_DEBUG_OUTPUT);
967     fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS);
968     fDebugMessageCallback(&StaticDebugCallback, (void*)this);
969     fDebugMessageControl(LOCAL_GL_DONT_CARE, LOCAL_GL_DONT_CARE,
970                          LOCAL_GL_DONT_CARE, 0, nullptr, true);
971   }
972 
973   return true;
974 }
975 
LoadMoreSymbols(const SymbolLoader & loader)976 void GLContext::LoadMoreSymbols(const SymbolLoader& loader) {
977   const auto fnLoadForExt = [&](const SymLoadStruct* list, GLExtensions ext) {
978     return this->LoadExtSymbols(loader, list, ext);
979   };
980 
981   const auto fnLoadForFeature = [&](const SymLoadStruct* list,
982                                     GLFeature feature) {
983     return this->LoadFeatureSymbols(loader, list, feature);
984   };
985 
986   const auto fnLoadFeatureByCore = [&](const SymLoadStruct* coreList,
987                                        const SymLoadStruct* extList,
988                                        GLFeature feature) {
989     const bool useCore = this->IsFeatureProvidedByCoreSymbols(feature);
990     const auto list = useCore ? coreList : extList;
991     return fnLoadForFeature(list, feature);
992   };
993 
994   if (IsSupported(GLFeature::robustness)) {
995     const auto resetStrategy =
996         GetIntAs<GLuint>(LOCAL_GL_RESET_NOTIFICATION_STRATEGY);
997     if (resetStrategy != LOCAL_GL_LOSE_CONTEXT_ON_RESET) {
998       NS_WARNING(
999           "Robustness supported, strategy is not LOSE_CONTEXT_ON_RESET!");
1000       if (ShouldSpew()) {
1001         const bool isDisabled =
1002             (resetStrategy == LOCAL_GL_NO_RESET_NOTIFICATION);
1003         printf_stderr("Strategy: %s (0x%04x)",
1004                       (isDisabled ? "disabled" : "unrecognized"),
1005                       resetStrategy);
1006       }
1007       MarkUnsupported(GLFeature::robustness);
1008     }
1009   }
1010 
1011   if (IsSupported(GLFeature::sync)) {
1012     const SymLoadStruct symbols[] = {
1013         CORE_SYMBOL(FenceSync),  CORE_SYMBOL(IsSync),
1014         CORE_SYMBOL(DeleteSync), CORE_SYMBOL(ClientWaitSync),
1015         CORE_SYMBOL(WaitSync),   CORE_SYMBOL(GetInteger64v),
1016         CORE_SYMBOL(GetSynciv),  END_SYMBOLS};
1017     fnLoadForFeature(symbols, GLFeature::sync);
1018   }
1019 
1020   if (IsExtensionSupported(OES_EGL_image)) {
1021     const SymLoadStruct symbols[] = {
1022         {(PRFuncPtr*)&mSymbols.fEGLImageTargetTexture2D,
1023          {{"glEGLImageTargetTexture2DOES"}}},
1024         {(PRFuncPtr*)&mSymbols.fEGLImageTargetRenderbufferStorage,
1025          {{"glEGLImageTargetRenderbufferStorageOES"}}},
1026         END_SYMBOLS};
1027     fnLoadForExt(symbols, OES_EGL_image);
1028   }
1029 
1030   if (IsExtensionSupported(APPLE_texture_range)) {
1031     const SymLoadStruct symbols[] = {CORE_SYMBOL(TextureRangeAPPLE),
1032                                      END_SYMBOLS};
1033     fnLoadForExt(symbols, APPLE_texture_range);
1034   }
1035 
1036   if (IsExtensionSupported(APPLE_fence)) {
1037     const SymLoadStruct symbols[] = {CORE_SYMBOL(FinishObjectAPPLE),
1038                                      CORE_SYMBOL(TestObjectAPPLE), END_SYMBOLS};
1039     fnLoadForExt(symbols, APPLE_fence);
1040   }
1041 
1042   // clang-format off
1043 
1044     if (IsSupported(GLFeature::vertex_array_object)) {
1045         const SymLoadStruct coreSymbols[] = {
1046             { (PRFuncPtr*) &mSymbols.fIsVertexArray, {{ "glIsVertexArray" }} },
1047             { (PRFuncPtr*) &mSymbols.fGenVertexArrays, {{ "glGenVertexArrays" }} },
1048             { (PRFuncPtr*) &mSymbols.fBindVertexArray, {{ "glBindVertexArray" }} },
1049             { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, {{ "glDeleteVertexArrays" }} },
1050             END_SYMBOLS
1051         };
1052         const SymLoadStruct extSymbols[] = {
1053             { (PRFuncPtr*) &mSymbols.fIsVertexArray, {{ "glIsVertexArrayARB", "glIsVertexArrayOES", "glIsVertexArrayAPPLE" }} },
1054             { (PRFuncPtr*) &mSymbols.fGenVertexArrays, {{ "glGenVertexArraysARB", "glGenVertexArraysOES", "glGenVertexArraysAPPLE" }} },
1055             { (PRFuncPtr*) &mSymbols.fBindVertexArray, {{ "glBindVertexArrayARB", "glBindVertexArrayOES", "glBindVertexArrayAPPLE" }} },
1056             { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, {{ "glDeleteVertexArraysARB", "glDeleteVertexArraysOES", "glDeleteVertexArraysAPPLE" }} },
1057             END_SYMBOLS
1058         };
1059         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::vertex_array_object);
1060     }
1061 
1062     if (IsSupported(GLFeature::draw_instanced)) {
1063         const SymLoadStruct coreSymbols[] = {
1064             { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, {{ "glDrawArraysInstanced" }} },
1065             { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, {{ "glDrawElementsInstanced" }} },
1066             END_SYMBOLS
1067         };
1068         const SymLoadStruct extSymbols[] = {
1069             { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, {{ "glDrawArraysInstancedARB", "glDrawArraysInstancedEXT", "glDrawArraysInstancedNV", "glDrawArraysInstancedANGLE" }} },
1070             { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, {{ "glDrawElementsInstancedARB", "glDrawElementsInstancedEXT", "glDrawElementsInstancedNV", "glDrawElementsInstancedANGLE" }}
1071             },
1072             END_SYMBOLS
1073         };
1074         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_instanced);
1075     }
1076 
1077     if (IsSupported(GLFeature::instanced_arrays)) {
1078         const SymLoadStruct coreSymbols[] = {
1079             { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, {{ "glVertexAttribDivisor" }} },
1080             END_SYMBOLS
1081         };
1082         const SymLoadStruct extSymbols[] = {
1083             { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, {{ "glVertexAttribDivisorARB", "glVertexAttribDivisorNV", "glVertexAttribDivisorANGLE" }} },
1084             END_SYMBOLS
1085         };
1086         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::instanced_arrays);
1087     }
1088 
1089     if (IsSupported(GLFeature::texture_storage)) {
1090         const SymLoadStruct coreSymbols[] = {
1091             { (PRFuncPtr*) &mSymbols.fTexStorage2D, {{ "glTexStorage2D" }} },
1092             { (PRFuncPtr*) &mSymbols.fTexStorage3D, {{ "glTexStorage3D" }} },
1093             END_SYMBOLS
1094         };
1095         const SymLoadStruct extSymbols[] = {
1096             { (PRFuncPtr*) &mSymbols.fTexStorage2D, {{ "glTexStorage2DEXT" }} },
1097             { (PRFuncPtr*) &mSymbols.fTexStorage3D, {{ "glTexStorage3DEXT" }} },
1098             END_SYMBOLS
1099         };
1100         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_storage);
1101     }
1102 
1103     if (IsSupported(GLFeature::sampler_objects)) {
1104         const SymLoadStruct symbols[] = {
1105             { (PRFuncPtr*) &mSymbols.fGenSamplers, {{ "glGenSamplers" }} },
1106             { (PRFuncPtr*) &mSymbols.fDeleteSamplers, {{ "glDeleteSamplers" }} },
1107             { (PRFuncPtr*) &mSymbols.fIsSampler, {{ "glIsSampler" }} },
1108             { (PRFuncPtr*) &mSymbols.fBindSampler, {{ "glBindSampler" }} },
1109             { (PRFuncPtr*) &mSymbols.fSamplerParameteri, {{ "glSamplerParameteri" }} },
1110             { (PRFuncPtr*) &mSymbols.fSamplerParameteriv, {{ "glSamplerParameteriv" }} },
1111             { (PRFuncPtr*) &mSymbols.fSamplerParameterf, {{ "glSamplerParameterf" }} },
1112             { (PRFuncPtr*) &mSymbols.fSamplerParameterfv, {{ "glSamplerParameterfv" }} },
1113             { (PRFuncPtr*) &mSymbols.fGetSamplerParameteriv, {{ "glGetSamplerParameteriv" }} },
1114             { (PRFuncPtr*) &mSymbols.fGetSamplerParameterfv, {{ "glGetSamplerParameterfv" }} },
1115             END_SYMBOLS
1116         };
1117         fnLoadForFeature(symbols, GLFeature::sampler_objects);
1118     }
1119 
1120     // ARB_transform_feedback2/NV_transform_feedback2 is a
1121     // superset of EXT_transform_feedback/NV_transform_feedback
1122     // and adds glPauseTransformFeedback &
1123     // glResumeTransformFeedback, which are required for WebGL2.
1124     if (IsSupported(GLFeature::transform_feedback2)) {
1125         const SymLoadStruct coreSymbols[] = {
1126             { (PRFuncPtr*) &mSymbols.fBindBufferBase, {{ "glBindBufferBase" }} },
1127             { (PRFuncPtr*) &mSymbols.fBindBufferRange, {{ "glBindBufferRange" }} },
1128             { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, {{ "glGenTransformFeedbacks" }} },
1129             { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, {{ "glBindTransformFeedback" }} },
1130             { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, {{ "glDeleteTransformFeedbacks" }} },
1131             { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, {{ "glIsTransformFeedback" }} },
1132             { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, {{ "glBeginTransformFeedback" }} },
1133             { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, {{ "glEndTransformFeedback" }} },
1134             { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, {{ "glTransformFeedbackVaryings" }} },
1135             { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, {{ "glGetTransformFeedbackVarying" }} },
1136             { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, {{ "glPauseTransformFeedback" }} },
1137             { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, {{ "glResumeTransformFeedback" }} },
1138             END_SYMBOLS
1139         };
1140         const SymLoadStruct extSymbols[] = {
1141             { (PRFuncPtr*) &mSymbols.fBindBufferBase, {{ "glBindBufferBaseEXT", "glBindBufferBaseNV" }} },
1142             { (PRFuncPtr*) &mSymbols.fBindBufferRange, {{ "glBindBufferRangeEXT", "glBindBufferRangeNV" }} },
1143             { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, {{ "glGenTransformFeedbacksNV" }} },
1144             { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, {{ "glBindTransformFeedbackNV" }} },
1145             { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, {{ "glDeleteTransformFeedbacksNV" }} },
1146             { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, {{ "glIsTransformFeedbackNV" }} },
1147             { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, {{ "glBeginTransformFeedbackEXT", "glBeginTransformFeedbackNV" }} },
1148             { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, {{ "glEndTransformFeedbackEXT", "glEndTransformFeedbackNV" }} },
1149             { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, {{ "glTransformFeedbackVaryingsEXT", "glTransformFeedbackVaryingsNV" }} },
1150             { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, {{ "glGetTransformFeedbackVaryingEXT", "glGetTransformFeedbackVaryingNV" }} },
1151             { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, {{ "glPauseTransformFeedbackNV" }} },
1152             { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, {{ "glResumeTransformFeedbackNV" }} },
1153             END_SYMBOLS
1154         };
1155         if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::transform_feedback2)) {
1156             // Also mark bind_buffer_offset as unsupported.
1157             MarkUnsupported(GLFeature::bind_buffer_offset);
1158         }
1159     }
1160 
1161     if (IsSupported(GLFeature::bind_buffer_offset)) {
1162         const SymLoadStruct coreSymbols[] = {
1163             { (PRFuncPtr*) &mSymbols.fBindBufferOffset, {{ "glBindBufferOffset" }} },
1164             END_SYMBOLS
1165         };
1166         const SymLoadStruct extSymbols[] = {
1167             { (PRFuncPtr*) &mSymbols.fBindBufferOffset,
1168               {{ "glBindBufferOffsetEXT", "glBindBufferOffsetNV" }}
1169             },
1170             END_SYMBOLS
1171         };
1172         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::bind_buffer_offset);
1173     }
1174 
1175     if (IsSupported(GLFeature::query_counter)) {
1176         const SymLoadStruct coreSymbols[] = {
1177             { (PRFuncPtr*) &mSymbols.fQueryCounter, {{ "glQueryCounter" }} },
1178             END_SYMBOLS
1179         };
1180         const SymLoadStruct extSymbols[] = {
1181             { (PRFuncPtr*) &mSymbols.fQueryCounter, {{ "glQueryCounterEXT", "glQueryCounterANGLE" }} },
1182             END_SYMBOLS
1183         };
1184         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_counter);
1185     }
1186 
1187     if (IsSupported(GLFeature::query_objects)) {
1188         const SymLoadStruct coreSymbols[] = {
1189             { (PRFuncPtr*) &mSymbols.fBeginQuery, {{ "glBeginQuery" }} },
1190             { (PRFuncPtr*) &mSymbols.fGenQueries, {{ "glGenQueries" }} },
1191             { (PRFuncPtr*) &mSymbols.fDeleteQueries, {{ "glDeleteQueries" }} },
1192             { (PRFuncPtr*) &mSymbols.fEndQuery, {{ "glEndQuery" }} },
1193             { (PRFuncPtr*) &mSymbols.fGetQueryiv, {{ "glGetQueryiv" }} },
1194             { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, {{ "glGetQueryObjectuiv" }} },
1195             { (PRFuncPtr*) &mSymbols.fIsQuery, {{ "glIsQuery" }} },
1196             END_SYMBOLS
1197         };
1198         const SymLoadStruct extSymbols[] = {
1199             { (PRFuncPtr*) &mSymbols.fBeginQuery, {{ "glBeginQueryEXT", "glBeginQueryANGLE" }} },
1200             { (PRFuncPtr*) &mSymbols.fGenQueries, {{ "glGenQueriesEXT", "glGenQueriesANGLE" }} },
1201             { (PRFuncPtr*) &mSymbols.fDeleteQueries, {{ "glDeleteQueriesEXT", "glDeleteQueriesANGLE" }} },
1202             { (PRFuncPtr*) &mSymbols.fEndQuery, {{ "glEndQueryEXT", "glEndQueryANGLE" }} },
1203             { (PRFuncPtr*) &mSymbols.fGetQueryiv, {{ "glGetQueryivEXT", "glGetQueryivANGLE" }} },
1204             { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, {{ "glGetQueryObjectuivEXT", "glGetQueryObjectuivANGLE" }} },
1205             { (PRFuncPtr*) &mSymbols.fIsQuery, {{ "glIsQueryEXT", "glIsQueryANGLE" }} },
1206             END_SYMBOLS
1207         };
1208         if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_objects)) {
1209             MarkUnsupported(GLFeature::get_query_object_i64v);
1210             MarkUnsupported(GLFeature::get_query_object_iv);
1211             MarkUnsupported(GLFeature::occlusion_query);
1212             MarkUnsupported(GLFeature::occlusion_query_boolean);
1213             MarkUnsupported(GLFeature::occlusion_query2);
1214         }
1215     }
1216 
1217     if (IsSupported(GLFeature::get_query_object_i64v)) {
1218         const SymLoadStruct coreSymbols[] = {
1219             { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, {{ "glGetQueryObjecti64v" }} },
1220             { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, {{ "glGetQueryObjectui64v" }} },
1221             END_SYMBOLS
1222         };
1223         const SymLoadStruct extSymbols[] = {
1224             { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, {{ "glGetQueryObjecti64vEXT", "glGetQueryObjecti64vANGLE" }} },
1225             { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, {{ "glGetQueryObjectui64vEXT", "glGetQueryObjectui64vANGLE" }} },
1226             END_SYMBOLS
1227         };
1228         if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_i64v)) {
1229             MarkUnsupported(GLFeature::query_counter);
1230         }
1231     }
1232 
1233     if (IsSupported(GLFeature::get_query_object_iv)) {
1234         const SymLoadStruct coreSymbols[] = {
1235             { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, {{ "glGetQueryObjectiv" }} },
1236             END_SYMBOLS
1237         };
1238         const SymLoadStruct extSymbols[] = {
1239             { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, {{ "glGetQueryObjectivEXT", "glGetQueryObjectivANGLE" }} },
1240             END_SYMBOLS
1241         };
1242         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_iv);
1243     }
1244 
1245     if (IsSupported(GLFeature::clear_buffers)) {
1246         const SymLoadStruct symbols[] = {
1247             { (PRFuncPtr*) &mSymbols.fClearBufferfi,  {{ "glClearBufferfi",  }} },
1248             { (PRFuncPtr*) &mSymbols.fClearBufferfv,  {{ "glClearBufferfv",  }} },
1249             { (PRFuncPtr*) &mSymbols.fClearBufferiv,  {{ "glClearBufferiv",  }} },
1250             { (PRFuncPtr*) &mSymbols.fClearBufferuiv, {{ "glClearBufferuiv" }} },
1251             END_SYMBOLS
1252         };
1253         fnLoadForFeature(symbols, GLFeature::clear_buffers);
1254     }
1255 
1256     if (IsSupported(GLFeature::copy_buffer)) {
1257         const SymLoadStruct symbols[] = {
1258             { (PRFuncPtr*) &mSymbols.fCopyBufferSubData, {{ "glCopyBufferSubData" }} },
1259             END_SYMBOLS
1260         };
1261         fnLoadForFeature(symbols, GLFeature::copy_buffer);
1262     }
1263 
1264     if (IsSupported(GLFeature::draw_buffers)) {
1265         const SymLoadStruct coreSymbols[] = {
1266             { (PRFuncPtr*) &mSymbols.fDrawBuffers, {{ "glDrawBuffers" }} },
1267             END_SYMBOLS
1268         };
1269         const SymLoadStruct extSymbols[] = {
1270             { (PRFuncPtr*) &mSymbols.fDrawBuffers, {{ "glDrawBuffersARB", "glDrawBuffersEXT" }} },
1271             END_SYMBOLS
1272         };
1273         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers);
1274     }
1275 
1276     if (IsSupported(GLFeature::draw_buffers_indexed)) {
1277         const SymLoadStruct coreSymbols[] = {
1278             { (PRFuncPtr*) &mSymbols.fBlendEquationSeparatei, {{ "glBlendEquationSeparatei" }} },
1279             { (PRFuncPtr*) &mSymbols.fBlendFuncSeparatei, {{ "glBlendFuncSeparatei" }} },
1280             { (PRFuncPtr*) &mSymbols.fColorMaski, {{ "glColorMaski" }} },
1281             { (PRFuncPtr*) &mSymbols.fDisablei, {{ "glDisablei" }} },
1282             { (PRFuncPtr*) &mSymbols.fEnablei, {{ "glEnablei" }} },
1283             END_SYMBOLS
1284         };
1285         const SymLoadStruct extSymbols[] = {
1286             { (PRFuncPtr*) &mSymbols.fBlendEquationSeparatei, {{ "glBlendEquationSeparateiOES" }} },
1287             { (PRFuncPtr*) &mSymbols.fBlendFuncSeparatei, {{ "glBlendFuncSeparateiOES" }} },
1288             { (PRFuncPtr*) &mSymbols.fColorMaski, {{ "glColorMaskiOES" }} },
1289             { (PRFuncPtr*) &mSymbols.fDisablei, {{ "glDisableiOES" }} },
1290             { (PRFuncPtr*) &mSymbols.fEnablei, {{ "glEnableiOES" }} },
1291             END_SYMBOLS
1292         };
1293         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers_indexed);
1294     }
1295 
1296     if (IsSupported(GLFeature::get_integer_indexed)) {
1297         const SymLoadStruct coreSymbols[] = {
1298             { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, {{ "glGetIntegeri_v" }} },
1299             END_SYMBOLS
1300         };
1301         const SymLoadStruct extSymbols[] ={
1302             { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, {{ "glGetIntegerIndexedvEXT" }} },
1303             END_SYMBOLS
1304         };
1305         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_integer_indexed);
1306     }
1307 
1308     if (IsSupported(GLFeature::get_integer64_indexed)) {
1309         const SymLoadStruct symbols[] = {
1310             { (PRFuncPtr*) &mSymbols.fGetInteger64i_v, {{ "glGetInteger64i_v" }} },
1311             END_SYMBOLS
1312         };
1313         fnLoadForFeature(symbols, GLFeature::get_integer64_indexed);
1314     }
1315 
1316     if (IsSupported(GLFeature::gpu_shader4)) {
1317         const SymLoadStruct symbols[] = {
1318             { (PRFuncPtr*) &mSymbols.fGetVertexAttribIiv, {{ "glGetVertexAttribIiv", "glGetVertexAttribIivEXT" }} },
1319             { (PRFuncPtr*) &mSymbols.fGetVertexAttribIuiv, {{ "glGetVertexAttribIuiv", "glGetVertexAttribIuivEXT" }} },
1320             { (PRFuncPtr*) &mSymbols.fVertexAttribI4i, {{ "glVertexAttribI4i", "glVertexAttribI4iEXT" }} },
1321             { (PRFuncPtr*) &mSymbols.fVertexAttribI4iv, {{ "glVertexAttribI4iv", "glVertexAttribI4ivEXT" }} },
1322             { (PRFuncPtr*) &mSymbols.fVertexAttribI4ui, {{ "glVertexAttribI4ui", "glVertexAttribI4uiEXT" }} },
1323             { (PRFuncPtr*) &mSymbols.fVertexAttribI4uiv, {{ "glVertexAttribI4uiv", "glVertexAttribI4uivEXT" }} },
1324             { (PRFuncPtr*) &mSymbols.fVertexAttribIPointer, {{ "glVertexAttribIPointer", "glVertexAttribIPointerEXT" }} },
1325             { (PRFuncPtr*) &mSymbols.fUniform1ui,  {{ "glUniform1ui", "glUniform1uiEXT" }} },
1326             { (PRFuncPtr*) &mSymbols.fUniform2ui,  {{ "glUniform2ui", "glUniform2uiEXT" }} },
1327             { (PRFuncPtr*) &mSymbols.fUniform3ui,  {{ "glUniform3ui", "glUniform3uiEXT" }} },
1328             { (PRFuncPtr*) &mSymbols.fUniform4ui,  {{ "glUniform4ui", "glUniform4uiEXT" }} },
1329             { (PRFuncPtr*) &mSymbols.fUniform1uiv, {{ "glUniform1uiv", "glUniform1uivEXT" }} },
1330             { (PRFuncPtr*) &mSymbols.fUniform2uiv, {{ "glUniform2uiv", "glUniform2uivEXT" }} },
1331             { (PRFuncPtr*) &mSymbols.fUniform3uiv, {{ "glUniform3uiv", "glUniform3uivEXT" }} },
1332             { (PRFuncPtr*) &mSymbols.fUniform4uiv, {{ "glUniform4uiv", "glUniform4uivEXT" }} },
1333             { (PRFuncPtr*) &mSymbols.fGetFragDataLocation, {{ "glGetFragDataLocation", "glGetFragDataLocationEXT" }} },
1334             { (PRFuncPtr*) &mSymbols.fGetUniformuiv, {{ "glGetUniformuiv", "glGetUniformuivEXT" }} },
1335             END_SYMBOLS
1336         };
1337         fnLoadForFeature(symbols, GLFeature::gpu_shader4);
1338     }
1339 
1340     if (IsSupported(GLFeature::map_buffer_range)) {
1341         const SymLoadStruct symbols[] = {
1342             { (PRFuncPtr*) &mSymbols.fMapBufferRange, {{ "glMapBufferRange" }} },
1343             { (PRFuncPtr*) &mSymbols.fFlushMappedBufferRange, {{ "glFlushMappedBufferRange" }} },
1344             { (PRFuncPtr*) &mSymbols.fUnmapBuffer, {{ "glUnmapBuffer" }} },
1345             END_SYMBOLS
1346         };
1347         fnLoadForFeature(symbols, GLFeature::map_buffer_range);
1348     }
1349 
1350     if (IsSupported(GLFeature::texture_3D)) {
1351         const SymLoadStruct coreSymbols[] = {
1352             { (PRFuncPtr*) &mSymbols.fTexImage3D, {{ "glTexImage3D" }} },
1353             { (PRFuncPtr*) &mSymbols.fTexSubImage3D, {{ "glTexSubImage3D" }} },
1354             END_SYMBOLS
1355         };
1356         const SymLoadStruct extSymbols[] = {
1357             { (PRFuncPtr*) &mSymbols.fTexImage3D, {{ "glTexImage3DOES" }} },
1358             { (PRFuncPtr*) &mSymbols.fTexSubImage3D, {{ "glTexSubImage3DOES" }} },
1359             END_SYMBOLS
1360         };
1361         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D);
1362     }
1363 
1364     if (IsSupported(GLFeature::texture_3D_compressed)) {
1365         const SymLoadStruct coreSymbols[] = {
1366             { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, {{ "glCompressedTexImage3D" }} },
1367             { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, {{ "glCompressedTexSubImage3D" }} },
1368             END_SYMBOLS
1369         };
1370         const SymLoadStruct extSymbols[] = {
1371             { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, {{ "glCompressedTexImage3DARB", "glCompressedTexImage3DOES" }} },
1372             { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, {{ "glCompressedTexSubImage3DARB", "glCompressedTexSubImage3DOES" }} },
1373             END_SYMBOLS
1374         };
1375         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_compressed);
1376     }
1377 
1378     if (IsSupported(GLFeature::texture_3D_copy)) {
1379         const SymLoadStruct coreSymbols[] = {
1380             { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, {{ "glCopyTexSubImage3D" }} },
1381             END_SYMBOLS
1382         };
1383         const SymLoadStruct extSymbols[] = {
1384             { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, {{ "glCopyTexSubImage3DEXT", "glCopyTexSubImage3DOES" }} },
1385             END_SYMBOLS
1386         };
1387         fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_copy);
1388     }
1389 
1390     if (IsSupported(GLFeature::uniform_buffer_object)) {
1391         // Note: Don't query for glGetActiveUniformName because it is not
1392         // supported by GL ES 3.
1393         const SymLoadStruct symbols[] = {
1394             { (PRFuncPtr*) &mSymbols.fGetUniformIndices, {{ "glGetUniformIndices" }} },
1395             { (PRFuncPtr*) &mSymbols.fGetActiveUniformsiv, {{ "glGetActiveUniformsiv" }} },
1396             { (PRFuncPtr*) &mSymbols.fGetUniformBlockIndex, {{ "glGetUniformBlockIndex" }} },
1397             { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockiv, {{ "glGetActiveUniformBlockiv" }} },
1398             { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockName, {{ "glGetActiveUniformBlockName" }} },
1399             { (PRFuncPtr*) &mSymbols.fUniformBlockBinding, {{ "glUniformBlockBinding" }} },
1400             END_SYMBOLS
1401         };
1402         fnLoadForFeature(symbols, GLFeature::uniform_buffer_object);
1403     }
1404 
1405     if (IsSupported(GLFeature::uniform_matrix_nonsquare)) {
1406         const SymLoadStruct symbols[] = {
1407             { (PRFuncPtr*) &mSymbols.fUniformMatrix2x3fv, {{ "glUniformMatrix2x3fv" }} },
1408             { (PRFuncPtr*) &mSymbols.fUniformMatrix2x4fv, {{ "glUniformMatrix2x4fv" }} },
1409             { (PRFuncPtr*) &mSymbols.fUniformMatrix3x2fv, {{ "glUniformMatrix3x2fv" }} },
1410             { (PRFuncPtr*) &mSymbols.fUniformMatrix3x4fv, {{ "glUniformMatrix3x4fv" }} },
1411             { (PRFuncPtr*) &mSymbols.fUniformMatrix4x2fv, {{ "glUniformMatrix4x2fv" }} },
1412             { (PRFuncPtr*) &mSymbols.fUniformMatrix4x3fv, {{ "glUniformMatrix4x3fv" }} },
1413             END_SYMBOLS
1414         };
1415         fnLoadForFeature(symbols, GLFeature::uniform_matrix_nonsquare);
1416     }
1417 
1418     if (IsSupported(GLFeature::internalformat_query)) {
1419         const SymLoadStruct symbols[] = {
1420             CORE_SYMBOL(GetInternalformativ),
1421             END_SYMBOLS
1422         };
1423         fnLoadForFeature(symbols, GLFeature::internalformat_query);
1424     }
1425 
1426     if (IsSupported(GLFeature::invalidate_framebuffer)) {
1427         const SymLoadStruct symbols[] = {
1428             { (PRFuncPtr*) &mSymbols.fInvalidateFramebuffer,    {{ "glInvalidateFramebuffer" }} },
1429             { (PRFuncPtr*) &mSymbols.fInvalidateSubFramebuffer, {{ "glInvalidateSubFramebuffer" }} },
1430             END_SYMBOLS
1431         };
1432         fnLoadForFeature(symbols, GLFeature::invalidate_framebuffer);
1433     }
1434 
1435     if (IsSupported(GLFeature::multiview)) {
1436         const SymLoadStruct symbols[] = {
1437             { (PRFuncPtr*) &mSymbols.fFramebufferTextureMultiview, {{
1438               "glFramebufferTextureMultiviewOVR",
1439               "glFramebufferTextureMultiviewLayeredANGLE"
1440             }} },
1441             END_SYMBOLS
1442         };
1443         fnLoadForFeature(symbols, GLFeature::multiview);
1444     }
1445 
1446     if (IsSupported(GLFeature::prim_restart)) {
1447         const SymLoadStruct symbols[] = {
1448             { (PRFuncPtr*) &mSymbols.fPrimitiveRestartIndex,    {{ "glPrimitiveRestartIndex", "glPrimitiveRestartIndexNV" }} },
1449             END_SYMBOLS
1450         };
1451         fnLoadForFeature(symbols, GLFeature::prim_restart);
1452     }
1453 
1454     if (IsExtensionSupported(KHR_debug)) {
1455         const SymLoadStruct symbols[] = {
1456             { (PRFuncPtr*) &mSymbols.fDebugMessageControl,  {{ "glDebugMessageControl",  "glDebugMessageControlKHR", }} },
1457             { (PRFuncPtr*) &mSymbols.fDebugMessageInsert,   {{ "glDebugMessageInsert",   "glDebugMessageInsertKHR",  }} },
1458             { (PRFuncPtr*) &mSymbols.fDebugMessageCallback, {{ "glDebugMessageCallback", "glDebugMessageCallbackKHR" }} },
1459             { (PRFuncPtr*) &mSymbols.fGetDebugMessageLog,   {{ "glGetDebugMessageLog",   "glGetDebugMessageLogKHR",  }} },
1460             { (PRFuncPtr*) &mSymbols.fGetPointerv,          {{ "glGetPointerv",          "glGetPointervKHR",         }} },
1461             { (PRFuncPtr*) &mSymbols.fPushDebugGroup,       {{ "glPushDebugGroup",       "glPushDebugGroupKHR",      }} },
1462             { (PRFuncPtr*) &mSymbols.fPopDebugGroup,        {{ "glPopDebugGroup",        "glPopDebugGroupKHR",       }} },
1463             { (PRFuncPtr*) &mSymbols.fObjectLabel,          {{ "glObjectLabel",          "glObjectLabelKHR",         }} },
1464             { (PRFuncPtr*) &mSymbols.fGetObjectLabel,       {{ "glGetObjectLabel",       "glGetObjectLabelKHR",      }} },
1465             { (PRFuncPtr*) &mSymbols.fObjectPtrLabel,       {{ "glObjectPtrLabel",       "glObjectPtrLabelKHR",      }} },
1466             { (PRFuncPtr*) &mSymbols.fGetObjectPtrLabel,    {{ "glGetObjectPtrLabel",    "glGetObjectPtrLabelKHR",   }} },
1467             END_SYMBOLS
1468         };
1469         fnLoadForExt(symbols, KHR_debug);
1470     }
1471 
1472     if (IsExtensionSupported(NV_fence)) {
1473         const SymLoadStruct symbols[] = {
1474             { (PRFuncPtr*) &mSymbols.fGenFences,    {{ "glGenFencesNV"    }} },
1475             { (PRFuncPtr*) &mSymbols.fDeleteFences, {{ "glDeleteFencesNV" }} },
1476             { (PRFuncPtr*) &mSymbols.fSetFence,     {{ "glSetFenceNV"     }} },
1477             { (PRFuncPtr*) &mSymbols.fTestFence,    {{ "glTestFenceNV"    }} },
1478             { (PRFuncPtr*) &mSymbols.fFinishFence,  {{ "glFinishFenceNV"  }} },
1479             { (PRFuncPtr*) &mSymbols.fIsFence,      {{ "glIsFenceNV"      }} },
1480             { (PRFuncPtr*) &mSymbols.fGetFenceiv,   {{ "glGetFenceivNV"   }} },
1481             END_SYMBOLS
1482         };
1483         fnLoadForExt(symbols, NV_fence);
1484     }
1485 
1486   // clang-format on
1487 
1488   if (IsExtensionSupported(NV_texture_barrier)) {
1489     const SymLoadStruct symbols[] = {
1490         {(PRFuncPtr*)&mSymbols.fTextureBarrier, {{"glTextureBarrierNV"}}},
1491         END_SYMBOLS};
1492     fnLoadForExt(symbols, NV_texture_barrier);
1493   }
1494 
1495   if (IsSupported(GLFeature::read_buffer)) {
1496     const SymLoadStruct symbols[] = {CORE_SYMBOL(ReadBuffer), END_SYMBOLS};
1497     fnLoadForFeature(symbols, GLFeature::read_buffer);
1498   }
1499 
1500   if (IsExtensionSupported(APPLE_framebuffer_multisample)) {
1501     const SymLoadStruct symbols[] = {
1502         CORE_SYMBOL(ResolveMultisampleFramebufferAPPLE), END_SYMBOLS};
1503     fnLoadForExt(symbols, APPLE_framebuffer_multisample);
1504   }
1505 
1506   // Load developer symbols, don't fail if we can't find them.
1507   const SymLoadStruct devSymbols[] = {CORE_SYMBOL(GetTexImage),
1508                                       CORE_SYMBOL(GetTexLevelParameteriv),
1509                                       END_SYMBOLS};
1510   const bool warnOnFailures = ShouldSpew();
1511   (void)loader.LoadSymbols(devSymbols, warnOnFailures);
1512 }
1513 
1514 #undef CORE_SYMBOL
1515 #undef CORE_EXT_SYMBOL2
1516 #undef EXT_SYMBOL2
1517 #undef EXT_SYMBOL3
1518 #undef END_SYMBOLS
1519 
DebugCallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message)1520 void GLContext::DebugCallback(GLenum source, GLenum type, GLuint id,
1521                               GLenum severity, GLsizei length,
1522                               const GLchar* message) {
1523   nsAutoCString sourceStr;
1524   switch (source) {
1525     case LOCAL_GL_DEBUG_SOURCE_API:
1526       sourceStr = "SOURCE_API"_ns;
1527       break;
1528     case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1529       sourceStr = "SOURCE_WINDOW_SYSTEM"_ns;
1530       break;
1531     case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER:
1532       sourceStr = "SOURCE_SHADER_COMPILER"_ns;
1533       break;
1534     case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY:
1535       sourceStr = "SOURCE_THIRD_PARTY"_ns;
1536       break;
1537     case LOCAL_GL_DEBUG_SOURCE_APPLICATION:
1538       sourceStr = "SOURCE_APPLICATION"_ns;
1539       break;
1540     case LOCAL_GL_DEBUG_SOURCE_OTHER:
1541       sourceStr = "SOURCE_OTHER"_ns;
1542       break;
1543     default:
1544       sourceStr = nsPrintfCString("<source 0x%04x>", source);
1545       break;
1546   }
1547 
1548   nsAutoCString typeStr;
1549   switch (type) {
1550     case LOCAL_GL_DEBUG_TYPE_ERROR:
1551       typeStr = "TYPE_ERROR"_ns;
1552       break;
1553     case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1554       typeStr = "TYPE_DEPRECATED_BEHAVIOR"_ns;
1555       break;
1556     case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1557       typeStr = "TYPE_UNDEFINED_BEHAVIOR"_ns;
1558       break;
1559     case LOCAL_GL_DEBUG_TYPE_PORTABILITY:
1560       typeStr = "TYPE_PORTABILITY"_ns;
1561       break;
1562     case LOCAL_GL_DEBUG_TYPE_PERFORMANCE:
1563       typeStr = "TYPE_PERFORMANCE"_ns;
1564       break;
1565     case LOCAL_GL_DEBUG_TYPE_OTHER:
1566       typeStr = "TYPE_OTHER"_ns;
1567       break;
1568     case LOCAL_GL_DEBUG_TYPE_MARKER:
1569       typeStr = "TYPE_MARKER"_ns;
1570       break;
1571     default:
1572       typeStr = nsPrintfCString("<type 0x%04x>", type);
1573       break;
1574   }
1575 
1576   nsAutoCString sevStr;
1577   switch (severity) {
1578     case LOCAL_GL_DEBUG_SEVERITY_HIGH:
1579       sevStr = "SEVERITY_HIGH"_ns;
1580       break;
1581     case LOCAL_GL_DEBUG_SEVERITY_MEDIUM:
1582       sevStr = "SEVERITY_MEDIUM"_ns;
1583       break;
1584     case LOCAL_GL_DEBUG_SEVERITY_LOW:
1585       sevStr = "SEVERITY_LOW"_ns;
1586       break;
1587     case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION:
1588       sevStr = "SEVERITY_NOTIFICATION"_ns;
1589       break;
1590     default:
1591       sevStr = nsPrintfCString("<severity 0x%04x>", severity);
1592       break;
1593   }
1594 
1595   printf_stderr("[KHR_debug: 0x%" PRIxPTR "] ID %u: %s, %s, %s:\n    %s\n",
1596                 (uintptr_t)this, id, sourceStr.BeginReading(),
1597                 typeStr.BeginReading(), sevStr.BeginReading(), message);
1598 }
1599 
InitExtensions()1600 void GLContext::InitExtensions() {
1601   MOZ_GL_ASSERT(this, IsCurrent());
1602 
1603   std::vector<nsCString> driverExtensionList;
1604 
1605   [&]() {
1606     if (mSymbols.fGetStringi) {
1607       GLuint count = 0;
1608       if (GetPotentialInteger(LOCAL_GL_NUM_EXTENSIONS, (GLint*)&count)) {
1609         for (GLuint i = 0; i < count; i++) {
1610           // This is UTF-8.
1611           const char* rawExt = (const char*)fGetStringi(LOCAL_GL_EXTENSIONS, i);
1612 
1613           // We CANNOT use nsDependentCString here, because the spec doesn't
1614           // guarantee that the pointers returned are different, only that their
1615           // contents are. On Flame, each of these index string queries returns
1616           // the same address.
1617           driverExtensionList.push_back(nsCString(rawExt));
1618         }
1619         return;
1620       }
1621     }
1622 
1623     const char* rawExts = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
1624     if (rawExts) {
1625       nsDependentCString exts(rawExts);
1626       SplitByChar(exts, ' ', &driverExtensionList);
1627     }
1628   }();
1629   const auto err = fGetError();
1630   MOZ_ALWAYS_TRUE(!IsBadCallError(err));
1631 
1632   const bool shouldDumpExts = ShouldDumpExts();
1633   if (shouldDumpExts) {
1634     printf_stderr("%i GL driver extensions: (*: recognized)\n",
1635                   (uint32_t)driverExtensionList.size());
1636   }
1637 
1638   MarkBitfieldByStrings(driverExtensionList, shouldDumpExts, sExtensionNames,
1639                         &mAvailableExtensions);
1640 
1641   if (WorkAroundDriverBugs()) {
1642     if (Vendor() == GLVendor::Qualcomm) {
1643       // Some Adreno drivers do not report GL_OES_EGL_sync, but they really do
1644       // support it.
1645       MarkExtensionSupported(OES_EGL_sync);
1646     }
1647 
1648     if (Vendor() == GLVendor::ATI) {
1649       // ATI drivers say this extension exists, but we can't
1650       // actually find the EGLImageTargetRenderbufferStorageOES
1651       // extension function pointer in the drivers.
1652       MarkExtensionUnsupported(OES_EGL_image);
1653     }
1654 
1655     if (Vendor() == GLVendor::Imagination && Renderer() == GLRenderer::SGX540) {
1656       // Bug 980048
1657       MarkExtensionUnsupported(OES_EGL_sync);
1658     }
1659 
1660 #ifdef MOZ_WIDGET_ANDROID
1661     if (Vendor() == GLVendor::Imagination &&
1662         Renderer() == GLRenderer::SGX544MP && jni::GetAPIVersion() < 21) {
1663       // Bug 1026404
1664       MarkExtensionUnsupported(OES_EGL_image);
1665       MarkExtensionUnsupported(OES_EGL_image_external);
1666     }
1667 #endif
1668 
1669     if (Vendor() == GLVendor::ARM && (Renderer() == GLRenderer::Mali400MP ||
1670                                       Renderer() == GLRenderer::Mali450MP)) {
1671       // Bug 1264505
1672       MarkExtensionUnsupported(OES_EGL_image_external);
1673     }
1674 
1675     if (Renderer() == GLRenderer::AndroidEmulator) {
1676       // the Android emulator, which we use to run B2G reftests on,
1677       // doesn't expose the OES_rgb8_rgba8 extension, but it seems to
1678       // support it (tautologically, as it only runs on desktop GL).
1679       MarkExtensionSupported(OES_rgb8_rgba8);
1680     }
1681 
1682     if (Vendor() == GLVendor::VMware &&
1683         Renderer() == GLRenderer::GalliumLlvmpipe) {
1684       // The llvmpipe driver that is used on linux try servers appears to have
1685       // buggy support for s3tc/dxt1 compressed textures.
1686       // See Bug 975824.
1687       MarkExtensionUnsupported(EXT_texture_compression_s3tc);
1688       MarkExtensionUnsupported(EXT_texture_compression_dxt1);
1689       MarkExtensionUnsupported(ANGLE_texture_compression_dxt3);
1690       MarkExtensionUnsupported(ANGLE_texture_compression_dxt5);
1691     }
1692 
1693 #ifdef XP_MACOSX
1694     // Bug 1009642: On OSX Mavericks (10.9), the driver for Intel HD
1695     // 3000 appears to be buggy WRT updating sub-images of S3TC
1696     // textures with glCompressedTexSubImage2D. Works on Intel HD 4000
1697     // and Intel HD 5000/Iris that I tested.
1698     // Bug 1124996: Appears to be the same on OSX Yosemite (10.10)
1699     if (Renderer() == GLRenderer::IntelHD3000) {
1700       MarkExtensionUnsupported(EXT_texture_compression_s3tc);
1701     }
1702 
1703     // OSX supports EXT_texture_sRGB in Legacy contexts, but not in Core
1704     // contexts. Though EXT_texture_sRGB was included into GL2.1, it *excludes*
1705     // the interactions with s3tc. Strictly speaking, you must advertize support
1706     // for EXT_texture_sRGB in order to allow for srgb+s3tc on desktop GL. The
1707     // omission of EXT_texture_sRGB in OSX Core contexts appears to be a bug.
1708     MarkExtensionSupported(EXT_texture_sRGB);
1709 #endif
1710   }
1711 
1712   if (shouldDumpExts) {
1713     printf_stderr("\nActivated extensions:\n");
1714 
1715     for (size_t i = 0; i < mAvailableExtensions.size(); i++) {
1716       if (!mAvailableExtensions[i]) continue;
1717 
1718       const char* ext = sExtensionNames[i];
1719       printf_stderr("[%i] %s\n", (uint32_t)i, ext);
1720     }
1721   }
1722 }
1723 
PlatformStartup()1724 void GLContext::PlatformStartup() {
1725   RegisterStrongMemoryReporter(new GfxTexturesReporter());
1726 }
1727 
1728 // Common code for checking for both GL extensions and GLX extensions.
ListHasExtension(const GLubyte * extensions,const char * extension)1729 bool GLContext::ListHasExtension(const GLubyte* extensions,
1730                                  const char* extension) {
1731   // fix bug 612572 - we were crashing as we were calling this function with
1732   // extensions==null
1733   if (extensions == nullptr || extension == nullptr) return false;
1734 
1735   const GLubyte* start;
1736   GLubyte* where;
1737   GLubyte* terminator;
1738 
1739   /* Extension names should not have spaces. */
1740   where = (GLubyte*)strchr(extension, ' ');
1741   if (where || *extension == '\0') return false;
1742 
1743   /*
1744    * It takes a bit of care to be fool-proof about parsing the
1745    * OpenGL extensions string. Don't be fooled by sub-strings,
1746    * etc.
1747    */
1748   start = extensions;
1749   for (;;) {
1750     where = (GLubyte*)strstr((const char*)start, extension);
1751     if (!where) {
1752       break;
1753     }
1754     terminator = where + strlen(extension);
1755     if (where == start || *(where - 1) == ' ') {
1756       if (*terminator == ' ' || *terminator == '\0') {
1757         return true;
1758       }
1759     }
1760     start = terminator;
1761   }
1762   return false;
1763 }
1764 
IsFramebufferComplete(GLuint fb,GLenum * pStatus)1765 bool GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus) {
1766   MOZ_ASSERT(fb);
1767 
1768   ScopedBindFramebuffer autoFB(this, fb);
1769   MOZ_GL_ASSERT(this, fIsFramebuffer(fb));
1770 
1771   GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
1772   if (pStatus) *pStatus = status;
1773 
1774   return status == LOCAL_GL_FRAMEBUFFER_COMPLETE;
1775 }
1776 
AttachBuffersToFB(GLuint colorTex,GLuint colorRB,GLuint depthRB,GLuint stencilRB,GLuint fb,GLenum target)1777 void GLContext::AttachBuffersToFB(GLuint colorTex, GLuint colorRB,
1778                                   GLuint depthRB, GLuint stencilRB, GLuint fb,
1779                                   GLenum target) {
1780   MOZ_ASSERT(fb);
1781   MOZ_ASSERT(!(colorTex && colorRB));
1782 
1783   ScopedBindFramebuffer autoFB(this, fb);
1784   MOZ_GL_ASSERT(this, fIsFramebuffer(fb));  // It only counts after being bound.
1785 
1786   if (colorTex) {
1787     MOZ_GL_ASSERT(this, fIsTexture(colorTex));
1788     MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
1789                target == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
1790     fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1791                           target, colorTex, 0);
1792   } else if (colorRB) {
1793     // On the Android 4.3 emulator, IsRenderbuffer may return false incorrectly.
1794     MOZ_GL_ASSERT(this, fIsRenderbuffer(colorRB) ||
1795                             Renderer() == GLRenderer::AndroidEmulator);
1796     fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1797                              LOCAL_GL_RENDERBUFFER, colorRB);
1798   }
1799 
1800   if (depthRB) {
1801     MOZ_GL_ASSERT(this, fIsRenderbuffer(depthRB) ||
1802                             Renderer() == GLRenderer::AndroidEmulator);
1803     fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
1804                              LOCAL_GL_RENDERBUFFER, depthRB);
1805   }
1806 
1807   if (stencilRB) {
1808     MOZ_GL_ASSERT(this, fIsRenderbuffer(stencilRB) ||
1809                             Renderer() == GLRenderer::AndroidEmulator);
1810     fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
1811                              LOCAL_GL_RENDERBUFFER, stencilRB);
1812   }
1813 }
1814 
AssembleOffscreenFBs(const GLuint colorMSRB,const GLuint depthRB,const GLuint stencilRB,const GLuint texture,GLuint * drawFB_out,GLuint * readFB_out)1815 bool GLContext::AssembleOffscreenFBs(const GLuint colorMSRB,
1816                                      const GLuint depthRB,
1817                                      const GLuint stencilRB,
1818                                      const GLuint texture, GLuint* drawFB_out,
1819                                      GLuint* readFB_out) {
1820   if (!colorMSRB && !texture) {
1821     MOZ_ASSERT(!depthRB && !stencilRB);
1822 
1823     if (drawFB_out) *drawFB_out = 0;
1824     if (readFB_out) *readFB_out = 0;
1825 
1826     return true;
1827   }
1828 
1829   ScopedBindFramebuffer autoFB(this);
1830 
1831   GLuint drawFB = 0;
1832   GLuint readFB = 0;
1833 
1834   if (texture) {
1835     readFB = 0;
1836     fGenFramebuffers(1, &readFB);
1837     BindFB(readFB);
1838     fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1839                           LOCAL_GL_TEXTURE_2D, texture, 0);
1840   }
1841 
1842   if (colorMSRB) {
1843     drawFB = 0;
1844     fGenFramebuffers(1, &drawFB);
1845     BindFB(drawFB);
1846     fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1847                              LOCAL_GL_RENDERBUFFER, colorMSRB);
1848   } else {
1849     drawFB = readFB;
1850   }
1851   MOZ_ASSERT(GetIntAs<GLuint>(LOCAL_GL_FRAMEBUFFER_BINDING) == drawFB);
1852 
1853   if (depthRB) {
1854     fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
1855                              LOCAL_GL_RENDERBUFFER, depthRB);
1856   }
1857 
1858   if (stencilRB) {
1859     fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
1860                              LOCAL_GL_RENDERBUFFER, stencilRB);
1861   }
1862 
1863   // We should be all resized.  Check for framebuffer completeness.
1864   GLenum status;
1865   bool isComplete = true;
1866 
1867   if (!IsFramebufferComplete(drawFB, &status)) {
1868     NS_WARNING("DrawFBO: Incomplete");
1869 #ifdef MOZ_GL_DEBUG
1870     if (ShouldSpew()) {
1871       printf_stderr("Framebuffer status: %X\n", status);
1872     }
1873 #endif
1874     isComplete = false;
1875   }
1876 
1877   if (!IsFramebufferComplete(readFB, &status)) {
1878     NS_WARNING("ReadFBO: Incomplete");
1879 #ifdef MOZ_GL_DEBUG
1880     if (ShouldSpew()) {
1881       printf_stderr("Framebuffer status: %X\n", status);
1882     }
1883 #endif
1884     isComplete = false;
1885   }
1886 
1887   if (drawFB_out) {
1888     *drawFB_out = drawFB;
1889   } else if (drawFB) {
1890     MOZ_CRASH("drawFB created when not requested!");
1891   }
1892 
1893   if (readFB_out) {
1894     *readFB_out = readFB;
1895   } else if (readFB) {
1896     MOZ_CRASH("readFB created when not requested!");
1897   }
1898 
1899   return isComplete;
1900 }
1901 
MarkDestroyed()1902 void GLContext::MarkDestroyed() {
1903   if (IsDestroyed()) return;
1904 
1905   OnMarkDestroyed();
1906 
1907   // Null these before they're naturally nulled after dtor, as we want GLContext
1908   // to still be alive in *their* dtors.
1909   mBlitHelper = nullptr;
1910   mReadTexImageHelper = nullptr;
1911 
1912   mContextLost = true;
1913   mSymbols = {};
1914 }
1915 
1916 // -
1917 
1918 #ifdef MOZ_GL_DEBUG
1919 /* static */
AssertNotPassingStackBufferToTheGL(const void * ptr)1920 void GLContext::AssertNotPassingStackBufferToTheGL(const void* ptr) {
1921   int somethingOnTheStack;
1922   const void* someStackPtr = &somethingOnTheStack;
1923   const int page_bits = 12;
1924   intptr_t page = reinterpret_cast<uintptr_t>(ptr) >> page_bits;
1925   intptr_t someStackPage =
1926       reinterpret_cast<uintptr_t>(someStackPtr) >> page_bits;
1927   uintptr_t pageDistance = std::abs(page - someStackPage);
1928 
1929   // Explanation for the "distance <= 1" check here as opposed to just
1930   // an equality check.
1931   //
1932   // Here we assume that pages immediately adjacent to the someStackAddress
1933   // page, are also stack pages. That allows to catch the case where the calling
1934   // frame put a buffer on the stack, and we just crossed the page boundary.
1935   // That is likely to happen, precisely, when using stack arrays. I hit that
1936   // specifically with CompositorOGL::Initialize.
1937   //
1938   // In theory we could be unlucky and wrongly assert here. If that happens,
1939   // it will only affect debug builds, and looking at stacks we'll be able to
1940   // see that this assert is wrong and revert to the conservative and safe
1941   // approach of only asserting when address and someStackAddress are
1942   // on the same page.
1943   bool isStackAddress = pageDistance <= 1;
1944   MOZ_ASSERT(!isStackAddress,
1945              "Please don't pass stack arrays to the GL. "
1946              "Consider using HeapCopyOfStackArray. "
1947              "See bug 1005658.");
1948 }
1949 
CreatedProgram(GLContext * aOrigin,GLuint aName)1950 void GLContext::CreatedProgram(GLContext* aOrigin, GLuint aName) {
1951   mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName));
1952 }
1953 
CreatedShader(GLContext * aOrigin,GLuint aName)1954 void GLContext::CreatedShader(GLContext* aOrigin, GLuint aName) {
1955   mTrackedShaders.AppendElement(NamedResource(aOrigin, aName));
1956 }
1957 
CreatedBuffers(GLContext * aOrigin,GLsizei aCount,GLuint * aNames)1958 void GLContext::CreatedBuffers(GLContext* aOrigin, GLsizei aCount,
1959                                GLuint* aNames) {
1960   for (GLsizei i = 0; i < aCount; ++i) {
1961     mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1962   }
1963 }
1964 
CreatedQueries(GLContext * aOrigin,GLsizei aCount,GLuint * aNames)1965 void GLContext::CreatedQueries(GLContext* aOrigin, GLsizei aCount,
1966                                GLuint* aNames) {
1967   for (GLsizei i = 0; i < aCount; ++i) {
1968     mTrackedQueries.AppendElement(NamedResource(aOrigin, aNames[i]));
1969   }
1970 }
1971 
CreatedTextures(GLContext * aOrigin,GLsizei aCount,GLuint * aNames)1972 void GLContext::CreatedTextures(GLContext* aOrigin, GLsizei aCount,
1973                                 GLuint* aNames) {
1974   for (GLsizei i = 0; i < aCount; ++i) {
1975     mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i]));
1976   }
1977 }
1978 
CreatedFramebuffers(GLContext * aOrigin,GLsizei aCount,GLuint * aNames)1979 void GLContext::CreatedFramebuffers(GLContext* aOrigin, GLsizei aCount,
1980                                     GLuint* aNames) {
1981   for (GLsizei i = 0; i < aCount; ++i) {
1982     mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1983   }
1984 }
1985 
CreatedRenderbuffers(GLContext * aOrigin,GLsizei aCount,GLuint * aNames)1986 void GLContext::CreatedRenderbuffers(GLContext* aOrigin, GLsizei aCount,
1987                                      GLuint* aNames) {
1988   for (GLsizei i = 0; i < aCount; ++i) {
1989     mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1990   }
1991 }
1992 
RemoveNamesFromArray(GLContext * aOrigin,GLsizei aCount,const GLuint * aNames,nsTArray<GLContext::NamedResource> & aArray)1993 static void RemoveNamesFromArray(GLContext* aOrigin, GLsizei aCount,
1994                                  const GLuint* aNames,
1995                                  nsTArray<GLContext::NamedResource>& aArray) {
1996   for (GLsizei j = 0; j < aCount; ++j) {
1997     GLuint name = aNames[j];
1998     // name 0 can be ignored
1999     if (name == 0) continue;
2000 
2001     for (uint32_t i = 0; i < aArray.Length(); ++i) {
2002       if (aArray[i].name == name) {
2003         aArray.RemoveElementAt(i);
2004         break;
2005       }
2006     }
2007   }
2008 }
2009 
DeletedProgram(GLContext * aOrigin,GLuint aName)2010 void GLContext::DeletedProgram(GLContext* aOrigin, GLuint aName) {
2011   RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms);
2012 }
2013 
DeletedShader(GLContext * aOrigin,GLuint aName)2014 void GLContext::DeletedShader(GLContext* aOrigin, GLuint aName) {
2015   RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders);
2016 }
2017 
DeletedBuffers(GLContext * aOrigin,GLsizei aCount,const GLuint * aNames)2018 void GLContext::DeletedBuffers(GLContext* aOrigin, GLsizei aCount,
2019                                const GLuint* aNames) {
2020   RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers);
2021 }
2022 
DeletedQueries(GLContext * aOrigin,GLsizei aCount,const GLuint * aNames)2023 void GLContext::DeletedQueries(GLContext* aOrigin, GLsizei aCount,
2024                                const GLuint* aNames) {
2025   RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedQueries);
2026 }
2027 
DeletedTextures(GLContext * aOrigin,GLsizei aCount,const GLuint * aNames)2028 void GLContext::DeletedTextures(GLContext* aOrigin, GLsizei aCount,
2029                                 const GLuint* aNames) {
2030   RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures);
2031 }
2032 
DeletedFramebuffers(GLContext * aOrigin,GLsizei aCount,const GLuint * aNames)2033 void GLContext::DeletedFramebuffers(GLContext* aOrigin, GLsizei aCount,
2034                                     const GLuint* aNames) {
2035   RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers);
2036 }
2037 
DeletedRenderbuffers(GLContext * aOrigin,GLsizei aCount,const GLuint * aNames)2038 void GLContext::DeletedRenderbuffers(GLContext* aOrigin, GLsizei aCount,
2039                                      const GLuint* aNames) {
2040   RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers);
2041 }
2042 
MarkContextDestroyedInArray(GLContext * aContext,nsTArray<GLContext::NamedResource> & aArray)2043 static void MarkContextDestroyedInArray(
2044     GLContext* aContext, nsTArray<GLContext::NamedResource>& aArray) {
2045   for (uint32_t i = 0; i < aArray.Length(); ++i) {
2046     if (aArray[i].origin == aContext) aArray[i].originDeleted = true;
2047   }
2048 }
2049 
SharedContextDestroyed(GLContext * aChild)2050 void GLContext::SharedContextDestroyed(GLContext* aChild) {
2051   MarkContextDestroyedInArray(aChild, mTrackedPrograms);
2052   MarkContextDestroyedInArray(aChild, mTrackedShaders);
2053   MarkContextDestroyedInArray(aChild, mTrackedTextures);
2054   MarkContextDestroyedInArray(aChild, mTrackedFramebuffers);
2055   MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers);
2056   MarkContextDestroyedInArray(aChild, mTrackedBuffers);
2057   MarkContextDestroyedInArray(aChild, mTrackedQueries);
2058 }
2059 
ReportArrayContents(const char * title,const nsTArray<GLContext::NamedResource> & aArray)2060 static void ReportArrayContents(
2061     const char* title, const nsTArray<GLContext::NamedResource>& aArray) {
2062   if (aArray.Length() == 0) return;
2063 
2064   printf_stderr("%s:\n", title);
2065 
2066   nsTArray<GLContext::NamedResource> copy(aArray.Clone());
2067   copy.Sort();
2068 
2069   GLContext* lastContext = nullptr;
2070   for (uint32_t i = 0; i < copy.Length(); ++i) {
2071     if (lastContext != copy[i].origin) {
2072       if (lastContext) printf_stderr("\n");
2073       printf_stderr("  [%p - %s] ", copy[i].origin,
2074                     copy[i].originDeleted ? "deleted" : "live");
2075       lastContext = copy[i].origin;
2076     }
2077     printf_stderr("%d ", copy[i].name);
2078   }
2079   printf_stderr("\n");
2080 }
2081 
ReportOutstandingNames()2082 void GLContext::ReportOutstandingNames() {
2083   if (!ShouldSpew()) return;
2084 
2085   printf_stderr("== GLContext %p Outstanding ==\n", this);
2086 
2087   ReportArrayContents("Outstanding Textures", mTrackedTextures);
2088   ReportArrayContents("Outstanding Buffers", mTrackedBuffers);
2089   ReportArrayContents("Outstanding Queries", mTrackedQueries);
2090   ReportArrayContents("Outstanding Programs", mTrackedPrograms);
2091   ReportArrayContents("Outstanding Shaders", mTrackedShaders);
2092   ReportArrayContents("Outstanding Framebuffers", mTrackedFramebuffers);
2093   ReportArrayContents("Outstanding Renderbuffers", mTrackedRenderbuffers);
2094 }
2095 
2096 #endif /* DEBUG */
2097 
IsOffscreenSizeAllowed(const IntSize & aSize) const2098 bool GLContext::IsOffscreenSizeAllowed(const IntSize& aSize) const {
2099   int32_t biggerDimension = std::max(aSize.width, aSize.height);
2100   int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize);
2101   return biggerDimension <= maxAllowed;
2102 }
2103 
IsOwningThreadCurrent()2104 bool GLContext::IsOwningThreadCurrent() {
2105   return PlatformThread::CurrentId() == mOwningThreadId;
2106 }
2107 
BlitHelper()2108 GLBlitHelper* GLContext::BlitHelper() {
2109   if (!mBlitHelper) {
2110     mBlitHelper.reset(new GLBlitHelper(this));
2111   }
2112 
2113   return mBlitHelper.get();
2114 }
2115 
ReadTexImageHelper()2116 GLReadTexImageHelper* GLContext::ReadTexImageHelper() {
2117   if (!mReadTexImageHelper) {
2118     mReadTexImageHelper = MakeUnique<GLReadTexImageHelper>(this);
2119   }
2120 
2121   return mReadTexImageHelper.get();
2122 }
2123 
FlushIfHeavyGLCallsSinceLastFlush()2124 void GLContext::FlushIfHeavyGLCallsSinceLastFlush() {
2125   if (!mHeavyGLCallsSinceLastFlush) {
2126     return;
2127   }
2128   if (MakeCurrent()) {
2129     fFlush();
2130   }
2131 }
2132 
2133 /*static*/
ShouldDumpExts()2134 bool GLContext::ShouldDumpExts() { return gfxEnv::GlDumpExtensions(); }
2135 
DoesStringMatch(const char * aString,const char * aWantedString)2136 bool DoesStringMatch(const char* aString, const char* aWantedString) {
2137   if (!aString || !aWantedString) return false;
2138 
2139   const char* occurrence = strstr(aString, aWantedString);
2140 
2141   // aWanted not found
2142   if (!occurrence) return false;
2143 
2144   // aWantedString preceded by alpha character
2145   if (occurrence != aString && isalpha(*(occurrence - 1))) return false;
2146 
2147   // aWantedVendor followed by alpha character
2148   const char* afterOccurrence = occurrence + strlen(aWantedString);
2149   if (isalpha(*afterOccurrence)) return false;
2150 
2151   return true;
2152 }
2153 
2154 /*static*/
ShouldSpew()2155 bool GLContext::ShouldSpew() { return gfxEnv::GlSpew(); }
2156 
SplitByChar(const nsACString & str,const char delim,std::vector<nsCString> * const out)2157 void SplitByChar(const nsACString& str, const char delim,
2158                  std::vector<nsCString>* const out) {
2159   uint32_t start = 0;
2160   while (true) {
2161     int32_t end = str.FindChar(' ', start);
2162     if (end == -1) break;
2163 
2164     uint32_t len = (uint32_t)end - start;
2165     nsDependentCSubstring substr(str, start, len);
2166     out->push_back(nsCString(substr));
2167 
2168     start = end + 1;
2169   }
2170 
2171   nsDependentCSubstring substr(str, start);
2172   out->push_back(nsCString(substr));
2173 }
2174 
fCopyTexImage2D(GLenum target,GLint level,GLenum internalformat,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)2175 void GLContext::fCopyTexImage2D(GLenum target, GLint level,
2176                                 GLenum internalformat, GLint x, GLint y,
2177                                 GLsizei width, GLsizei height, GLint border) {
2178   if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
2179     // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2180     // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2181     level = -1;
2182     width = -1;
2183     height = -1;
2184     border = -1;
2185   }
2186 
2187   BeforeGLReadCall();
2188   raw_fCopyTexImage2D(target, level, internalformat, x, y, width, height,
2189                       border);
2190   AfterGLReadCall();
2191 }
2192 
fGetIntegerv(const GLenum pname,GLint * const params) const2193 void GLContext::fGetIntegerv(const GLenum pname, GLint* const params) const {
2194   const auto AssertBinding = [&](const char* const name, const GLenum binding,
2195                                  const GLuint expected) {
2196     if (MOZ_LIKELY(!mDebugFlags)) return;
2197     GLuint actual = 0;
2198     raw_fGetIntegerv(binding, (GLint*)&actual);
2199     if (actual != expected) {
2200       gfxCriticalError() << "Misprediction: " << name << " expected "
2201                          << expected << ", was " << actual;
2202     }
2203   };
2204 
2205   switch (pname) {
2206     case LOCAL_GL_MAX_TEXTURE_SIZE:
2207       MOZ_ASSERT(mMaxTextureSize > 0);
2208       *params = mMaxTextureSize;
2209       return;
2210 
2211     case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
2212       MOZ_ASSERT(mMaxCubeMapTextureSize > 0);
2213       *params = mMaxCubeMapTextureSize;
2214       return;
2215 
2216     case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
2217       MOZ_ASSERT(mMaxRenderbufferSize > 0);
2218       *params = mMaxRenderbufferSize;
2219       return;
2220 
2221     case LOCAL_GL_VIEWPORT:
2222       for (size_t i = 0; i < 4; i++) {
2223         params[i] = mViewportRect[i];
2224       }
2225       return;
2226 
2227     case LOCAL_GL_SCISSOR_BOX:
2228       for (size_t i = 0; i < 4; i++) {
2229         params[i] = mScissorRect[i];
2230       }
2231       return;
2232 
2233     case LOCAL_GL_DRAW_FRAMEBUFFER_BINDING:
2234       if (mElideDuplicateBindFramebuffers) {
2235         static_assert(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING ==
2236                       LOCAL_GL_FRAMEBUFFER_BINDING);
2237         AssertBinding("GL_DRAW_FRAMEBUFFER_BINDING",
2238                       LOCAL_GL_DRAW_FRAMEBUFFER_BINDING, mCachedDrawFb);
2239         *params = static_cast<GLint>(mCachedDrawFb);
2240         return;
2241       }
2242       break;
2243 
2244     case LOCAL_GL_READ_FRAMEBUFFER_BINDING:
2245       if (mElideDuplicateBindFramebuffers) {
2246         if (IsSupported(GLFeature::framebuffer_blit)) {
2247           AssertBinding("GL_READ_FRAMEBUFFER_BINDING",
2248                         LOCAL_GL_READ_FRAMEBUFFER_BINDING, mCachedReadFb);
2249         }
2250         *params = static_cast<GLint>(mCachedReadFb);
2251         return;
2252       }
2253       break;
2254 
2255     default:
2256       break;
2257   }
2258   raw_fGetIntegerv(pname, params);
2259 }
2260 
fReadPixels(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels)2261 void GLContext::fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
2262                             GLenum format, GLenum type, GLvoid* pixels) {
2263   BeforeGLReadCall();
2264   raw_fReadPixels(x, y, width, height, format, type, pixels);
2265   AfterGLReadCall();
2266 
2267   // Check if GL is giving back 1.0 alpha for
2268   // RGBA reads to RGBA images from no-alpha buffers.
2269 #ifdef XP_MACOSX
2270   if (WorkAroundDriverBugs() && Vendor() == gl::GLVendor::NVIDIA &&
2271       format == LOCAL_GL_RGBA && type == LOCAL_GL_UNSIGNED_BYTE &&
2272       !IsCoreProfile() && width && height) {
2273     GLint alphaBits = 0;
2274     fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits);
2275     if (!alphaBits) {
2276       const uint32_t alphaMask = 0xff000000;
2277 
2278       uint32_t* itr = (uint32_t*)pixels;
2279       uint32_t testPixel = *itr;
2280       if ((testPixel & alphaMask) != alphaMask) {
2281         // We need to set the alpha channel to 1.0 manually.
2282         uint32_t* itrEnd =
2283             itr + width * height;  // Stride is guaranteed to be width*4.
2284 
2285         for (; itr != itrEnd; itr++) {
2286           *itr |= alphaMask;
2287         }
2288       }
2289     }
2290   }
2291 #endif
2292 }
2293 
fDeleteFramebuffers(GLsizei n,const GLuint * names)2294 void GLContext::fDeleteFramebuffers(GLsizei n, const GLuint* names) {
2295   // Avoid crash by flushing before glDeleteFramebuffers. See bug 1194923.
2296   if (mNeedsFlushBeforeDeleteFB) {
2297     fFlush();
2298   }
2299 
2300   if (n == 1 && *names == 0) {
2301     // Deleting framebuffer 0 causes hangs on the DROID. See bug 623228.
2302   } else {
2303     raw_fDeleteFramebuffers(n, names);
2304   }
2305   TRACKING_CONTEXT(DeletedFramebuffers(this, n, names));
2306 }
2307 
2308 #ifdef MOZ_WIDGET_ANDROID
2309 /**
2310  * Conservatively estimate whether there is enough available
2311  * contiguous virtual address space to map a newly allocated texture.
2312  */
WillTextureMapSucceed(GLsizei width,GLsizei height,GLenum format,GLenum type)2313 static bool WillTextureMapSucceed(GLsizei width, GLsizei height, GLenum format,
2314                                   GLenum type) {
2315   bool willSucceed = false;
2316   // Some drivers leave large gaps between textures, so require
2317   // there to be double the actual size of the texture available.
2318   size_t size = width * height * GetBytesPerTexel(format, type) * 2;
2319 
2320   void* p = mmap(nullptr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
2321   if (p != MAP_FAILED) {
2322     willSucceed = true;
2323     munmap(p, size);
2324   }
2325 
2326   return willSucceed;
2327 }
2328 #endif  // MOZ_WIDGET_ANDROID
2329 
fTexImage2D(GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const GLvoid * pixels)2330 void GLContext::fTexImage2D(GLenum target, GLint level, GLint internalformat,
2331                             GLsizei width, GLsizei height, GLint border,
2332                             GLenum format, GLenum type, const GLvoid* pixels) {
2333   if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
2334     // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2335     // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2336     level = -1;
2337     width = -1;
2338     height = -1;
2339     border = -1;
2340   }
2341 #if MOZ_WIDGET_ANDROID
2342   if (mTextureAllocCrashesOnMapFailure) {
2343     // We have no way of knowing whether this texture already has
2344     // storage allocated for it, and therefore whether this check
2345     // is necessary. We must therefore assume it does not and
2346     // always perform the check.
2347     if (!WillTextureMapSucceed(width, height, internalformat, type)) {
2348       return;
2349     }
2350   }
2351 #endif
2352   raw_fTexImage2D(target, level, internalformat, width, height, border, format,
2353                   type, pixels);
2354 }
2355 
CreateTexture(GLContext & gl,const gfx::IntSize & size)2356 UniquePtr<Texture> CreateTexture(GLContext& gl, const gfx::IntSize& size) {
2357   const GLenum target = LOCAL_GL_TEXTURE_2D;
2358   const GLenum format = LOCAL_GL_RGBA;
2359 
2360   auto tex = MakeUnique<Texture>(gl);
2361   ScopedBindTexture autoTex(&gl, tex->name, target);
2362 
2363   gl.fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
2364   gl.fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
2365   gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
2366   gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
2367 
2368   gl.fTexImage2D(target, 0, format, size.width, size.height, 0, format,
2369                  LOCAL_GL_UNSIGNED_BYTE, nullptr);
2370 
2371   return tex;
2372 }
2373 
GetBytesPerTexel(GLenum format,GLenum type)2374 uint32_t GetBytesPerTexel(GLenum format, GLenum type) {
2375   // If there is no defined format or type, we're not taking up any memory
2376   if (!format || !type) {
2377     return 0;
2378   }
2379 
2380   if (format == LOCAL_GL_DEPTH_COMPONENT) {
2381     if (type == LOCAL_GL_UNSIGNED_SHORT)
2382       return 2;
2383     else if (type == LOCAL_GL_UNSIGNED_INT)
2384       return 4;
2385   } else if (format == LOCAL_GL_DEPTH_STENCIL) {
2386     if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT) return 4;
2387   }
2388 
2389   if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT ||
2390       type == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV) {
2391     uint32_t multiplier = type == LOCAL_GL_UNSIGNED_BYTE ? 1 : 4;
2392     switch (format) {
2393       case LOCAL_GL_ALPHA:
2394       case LOCAL_GL_LUMINANCE:
2395       case LOCAL_GL_R8:
2396         return 1 * multiplier;
2397       case LOCAL_GL_LUMINANCE_ALPHA:
2398       case LOCAL_GL_R16:
2399         return 2 * multiplier;
2400       case LOCAL_GL_RGB:
2401         return 3 * multiplier;
2402       case LOCAL_GL_RGBA:
2403       case LOCAL_GL_BGRA_EXT:
2404         return 4 * multiplier;
2405       default:
2406         break;
2407     }
2408   } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
2409              type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
2410              type == LOCAL_GL_UNSIGNED_SHORT_5_6_5 ||
2411              type == LOCAL_GL_UNSIGNED_SHORT) {
2412     return 2;
2413   }
2414 
2415   gfxCriticalError() << "Unknown texture type " << type << " or format "
2416                      << format;
2417   return 0;
2418 }
2419 
MakeCurrent(bool aForce) const2420 bool GLContext::MakeCurrent(bool aForce) const {
2421   if (MOZ_UNLIKELY(IsContextLost())) return false;
2422 
2423   if (MOZ_LIKELY(!aForce)) {
2424     bool isCurrent;
2425     if (mUseTLSIsCurrent) {
2426       isCurrent = (sCurrentContext.get() == reinterpret_cast<uintptr_t>(this));
2427     } else {
2428       isCurrent = IsCurrentImpl();
2429     }
2430     if (MOZ_LIKELY(isCurrent)) {
2431       MOZ_ASSERT(IsCurrentImpl() ||
2432                  !MakeCurrentImpl());  // Might have lost context.
2433       return true;
2434     }
2435   }
2436 
2437   if (!MakeCurrentImpl()) return false;
2438 
2439   sCurrentContext.set(reinterpret_cast<uintptr_t>(this));
2440   return true;
2441 }
2442 
ResetSyncCallCount(const char * resetReason) const2443 void GLContext::ResetSyncCallCount(const char* resetReason) const {
2444   if (ShouldSpew()) {
2445     printf_stderr("On %s, mSyncGLCallCount = %" PRIu64 "\n", resetReason,
2446                   mSyncGLCallCount);
2447   }
2448 
2449   mSyncGLCallCount = 0;
2450 }
2451 
2452 // -
2453 
CheckContextLost(const GLContext * const gl)2454 bool CheckContextLost(const GLContext* const gl) {
2455   return gl->CheckContextLost();
2456 }
2457 
2458 // -
2459 
GetError() const2460 GLenum GLContext::GetError() const {
2461   if (mContextLost) return LOCAL_GL_CONTEXT_LOST;
2462 
2463   if (mImplicitMakeCurrent) {
2464     (void)MakeCurrent();
2465   }
2466 
2467   const auto fnGetError = [&]() {
2468     const auto ret = mSymbols.fGetError();
2469     if (ret == LOCAL_GL_CONTEXT_LOST) {
2470       OnContextLostError();
2471       mTopError = ret;  // Promote to top!
2472     }
2473     return ret;
2474   };
2475 
2476   auto ret = fnGetError();
2477 
2478   {
2479     auto flushedErr = ret;
2480     uint32_t i = 1;
2481     while (flushedErr && !mContextLost) {
2482       if (i == 100) {
2483         gfxCriticalError() << "Flushing glGetError still "
2484                            << gfx::hexa(flushedErr) << " after " << i
2485                            << " calls.";
2486         break;
2487       }
2488       flushedErr = fnGetError();
2489       i += 1;
2490     }
2491   }
2492 
2493   if (mTopError) {
2494     ret = mTopError;
2495     mTopError = 0;
2496   }
2497 
2498   if (mDebugFlags & DebugFlagTrace) {
2499     const auto errStr = GLErrorToString(ret);
2500     printf_stderr("[gl:%p] GetError() -> %s\n", this, errStr.c_str());
2501   }
2502   return ret;
2503 }
2504 
fGetGraphicsResetStatus() const2505 GLenum GLContext::fGetGraphicsResetStatus() const {
2506   OnSyncCall();
2507 
2508   GLenum ret = 0;
2509   if (mSymbols.fGetGraphicsResetStatus) {
2510     if (mImplicitMakeCurrent) {
2511       (void)MakeCurrent();
2512     }
2513     ret = mSymbols.fGetGraphicsResetStatus();
2514   } else {
2515     if (!MakeCurrent(true)) {
2516       ret = LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB;
2517     }
2518   }
2519 
2520   if (mDebugFlags & DebugFlagTrace) {
2521     printf_stderr("[gl:%p] GetGraphicsResetStatus() -> 0x%04x\n", this, ret);
2522   }
2523 
2524   return ret;
2525 }
2526 
OnContextLostError() const2527 void GLContext::OnContextLostError() const {
2528   if (mDebugFlags & DebugFlagTrace) {
2529     printf_stderr("[gl:%p] CONTEXT_LOST\n", this);
2530   }
2531   mContextLost = true;
2532 }
2533 
2534 // --
2535 
GLErrorToString(const GLenum err)2536 /*static*/ std::string GLContext::GLErrorToString(const GLenum err) {
2537   switch (err) {
2538     case LOCAL_GL_NO_ERROR:
2539       return "GL_NO_ERROR";
2540     case LOCAL_GL_INVALID_ENUM:
2541       return "GL_INVALID_ENUM";
2542     case LOCAL_GL_INVALID_VALUE:
2543       return "GL_INVALID_VALUE";
2544     case LOCAL_GL_INVALID_OPERATION:
2545       return "GL_INVALID_OPERATION";
2546     case LOCAL_GL_STACK_OVERFLOW:
2547       return "GL_STACK_OVERFLOW";
2548     case LOCAL_GL_STACK_UNDERFLOW:
2549       return "GL_STACK_UNDERFLOW";
2550     case LOCAL_GL_OUT_OF_MEMORY:
2551       return "GL_OUT_OF_MEMORY";
2552     case LOCAL_GL_TABLE_TOO_LARGE:
2553       return "GL_TABLE_TOO_LARGE";
2554     case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
2555       return "GL_INVALID_FRAMEBUFFER_OPERATION";
2556     case LOCAL_GL_CONTEXT_LOST:
2557       return "GL_CONTEXT_LOST";
2558   }
2559 
2560   const nsPrintfCString hex("<enum 0x%04x>", err);
2561   return hex.BeginReading();
2562 }
2563 
2564 // --
2565 
BeforeGLCall_Debug(const char * const funcName) const2566 void GLContext::BeforeGLCall_Debug(const char* const funcName) const {
2567   MOZ_ASSERT(mDebugFlags);
2568 
2569   if (mDebugFlags & DebugFlagTrace) {
2570     printf_stderr("[gl:%p] > %s\n", this, funcName);
2571   }
2572 
2573   MOZ_ASSERT(!mDebugErrorScope);
2574   mDebugErrorScope.reset(new LocalErrorScope(*this));
2575 }
2576 
AfterGLCall_Debug(const char * const funcName) const2577 void GLContext::AfterGLCall_Debug(const char* const funcName) const {
2578   MOZ_ASSERT(mDebugFlags);
2579 
2580   // calling fFinish() immediately after every GL call makes sure that if this
2581   // GL command crashes, the stack trace will actually point to it. Otherwise,
2582   // OpenGL being an asynchronous API, stack traces tend to be meaningless
2583   mSymbols.fFinish();
2584 
2585   const auto err = mDebugErrorScope->GetError();
2586   mDebugErrorScope = nullptr;
2587   if (!mTopError) {
2588     mTopError = err;
2589   }
2590 
2591   if (mDebugFlags & DebugFlagTrace) {
2592     printf_stderr("[gl:%p] < %s [%s]\n", this, funcName,
2593                   GLErrorToString(err).c_str());
2594   }
2595 
2596   if (err && !mLocalErrorScopeStack.size()) {
2597     const auto errStr = GLErrorToString(err);
2598     const auto text = nsPrintfCString("%s: Generated unexpected %s error",
2599                                       funcName, errStr.c_str());
2600     printf_stderr("[gl:%p] %s.\n", this, text.BeginReading());
2601 
2602     const bool abortOnError = mDebugFlags & DebugFlagAbortOnError;
2603     if (abortOnError && err != LOCAL_GL_CONTEXT_LOST) {
2604       gfxCriticalErrorOnce() << text.BeginReading();
2605       MOZ_CRASH(
2606           "Aborting... (Run with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)");
2607     }
2608   }
2609 }
2610 
2611 /*static*/
OnImplicitMakeCurrentFailure(const char * const funcName)2612 void GLContext::OnImplicitMakeCurrentFailure(const char* const funcName) {
2613   gfxCriticalError() << "Ignoring call to " << funcName << " with failed"
2614                      << " mImplicitMakeCurrent.";
2615 }
2616 
CreateOffscreenDefaultFb(const gfx::IntSize & size)2617 bool GLContext::CreateOffscreenDefaultFb(const gfx::IntSize& size) {
2618   mOffscreenDefaultFb = MozFramebuffer::Create(this, size, 0, true);
2619   return bool(mOffscreenDefaultFb);
2620 }
2621 
2622 // Some of Mesa's drivers allocate heap memory when loaded and don't
2623 // free it when unloaded; this causes Leak Sanitizer to detect leaks and
2624 // fail to unwind the stack, so suppressions don't work.  This
2625 // workaround leaks a reference to the driver library so that it's never
2626 // unloaded.  Because the leak isn't significant for real usage, only
2627 // ASan runs in CI, this is applied only to the software renderer.
2628 //
2629 // See bug 1702394 for more details.
MesaMemoryLeakWorkaround()2630 void MesaMemoryLeakWorkaround() {
2631 #if defined(XP_LINUX) && !defined(ANDROID)
2632   Maybe<nsAutoCString> foundPath;
2633 
2634   dl_iterate_phdr(
2635       [](dl_phdr_info* info, size_t size, void* data) {
2636         auto& foundPath = *reinterpret_cast<Maybe<nsAutoCString>*>(data);
2637         nsDependentCString thisPath(info->dlpi_name);
2638         if (StringEndsWith(thisPath, "/swrast_dri.so"_ns)) {
2639           foundPath.emplace(thisPath);
2640           return 1;
2641         }
2642         return 0;
2643       },
2644       &foundPath);
2645 
2646   if (foundPath) {
2647     // Deliberately leak to prevent unload
2648     Unused << dlopen(foundPath->get(), RTLD_LAZY);
2649   }
2650 #endif  // XP_LINUX but not ANDROID
2651 }
2652 
2653 } /* namespace gl */
2654 } /* namespace mozilla */
2655