Bug 1874684 - Part 28: Return DateDuration from DifferenceISODateTime. r=mgaudet
[gecko.git] / gfx / gl / GLContext.cpp
blob5eba6c58aa6c9294ba6ff3d59d14d207127abf5c
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/. */
7 #include "GLContext.h"
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
25 #include "GLBlitHelper.h"
26 #include "GLReadTexImageHelper.h"
27 #include "GLScreenBuffer.h"
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
50 #include "OGLShaderProgram.h" // for ShaderProgramType
52 #include "mozilla/DebugOnly.h"
53 #include "mozilla/Maybe.h"
55 #ifdef XP_MACOSX
56 # include <CoreServices/CoreServices.h>
57 #endif
59 #ifdef MOZ_WIDGET_ANDROID
60 # include "mozilla/jni/Utils.h"
61 #endif
63 namespace mozilla {
64 namespace gl {
66 using namespace mozilla::gfx;
67 using namespace mozilla::layers;
69 // Zero-initialized after init().
70 MOZ_THREAD_LOCAL(const GLContext*) GLContext::sCurrentContext;
72 // If adding defines, don't forget to undefine symbols. See #undef block below.
73 // clang-format off
74 #define CORE_SYMBOL(x) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x }} }
75 #define CORE_EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x, "gl" #x #y, "gl" #x #z }} }
76 #define EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x #y, "gl" #x #z }} }
77 #define EXT_SYMBOL3(x,y,z,w) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x #y, "gl" #x #z, "gl" #x #w }} }
78 #define END_SYMBOLS { nullptr, {} }
79 // clang-format on
81 // should match the order of GLExtensions, and be null-terminated.
82 static const char* const sExtensionNames[] = {
83 "NO_EXTENSION",
84 "GL_AMD_compressed_ATC_texture",
85 "GL_ANGLE_depth_texture",
86 "GL_ANGLE_framebuffer_blit",
87 "GL_ANGLE_framebuffer_multisample",
88 "GL_ANGLE_instanced_arrays",
89 "GL_ANGLE_multiview",
90 "GL_ANGLE_provoking_vertex",
91 "GL_ANGLE_texture_compression_dxt3",
92 "GL_ANGLE_texture_compression_dxt5",
93 "GL_ANGLE_timer_query",
94 "GL_APPLE_client_storage",
95 "GL_APPLE_fence",
96 "GL_APPLE_framebuffer_multisample",
97 "GL_APPLE_sync",
98 "GL_APPLE_texture_range",
99 "GL_APPLE_vertex_array_object",
100 "GL_ARB_ES2_compatibility",
101 "GL_ARB_ES3_compatibility",
102 "GL_ARB_color_buffer_float",
103 "GL_ARB_compatibility",
104 "GL_ARB_copy_buffer",
105 "GL_ARB_depth_texture",
106 "GL_ARB_draw_buffers",
107 "GL_ARB_draw_instanced",
108 "GL_ARB_framebuffer_object",
109 "GL_ARB_framebuffer_sRGB",
110 "GL_ARB_geometry_shader4",
111 "GL_ARB_half_float_pixel",
112 "GL_ARB_instanced_arrays",
113 "GL_ARB_internalformat_query",
114 "GL_ARB_invalidate_subdata",
115 "GL_ARB_map_buffer_range",
116 "GL_ARB_occlusion_query2",
117 "GL_ARB_pixel_buffer_object",
118 "GL_ARB_provoking_vertex",
119 "GL_ARB_robust_buffer_access_behavior",
120 "GL_ARB_robustness",
121 "GL_ARB_sampler_objects",
122 "GL_ARB_seamless_cube_map",
123 "GL_ARB_shader_texture_lod",
124 "GL_ARB_sync",
125 "GL_ARB_texture_compression",
126 "GL_ARB_texture_compression_bptc",
127 "GL_ARB_texture_compression_rgtc",
128 "GL_ARB_texture_float",
129 "GL_ARB_texture_non_power_of_two",
130 "GL_ARB_texture_rectangle",
131 "GL_ARB_texture_rg",
132 "GL_ARB_texture_storage",
133 "GL_ARB_texture_swizzle",
134 "GL_ARB_timer_query",
135 "GL_ARB_transform_feedback2",
136 "GL_ARB_uniform_buffer_object",
137 "GL_ARB_vertex_array_object",
138 "GL_CHROMIUM_color_buffer_float_rgb",
139 "GL_CHROMIUM_color_buffer_float_rgba",
140 "GL_EXT_bgra",
141 "GL_EXT_blend_minmax",
142 "GL_EXT_color_buffer_float",
143 "GL_EXT_color_buffer_half_float",
144 "GL_EXT_copy_texture",
145 "GL_EXT_disjoint_timer_query",
146 "GL_EXT_draw_buffers",
147 "GL_EXT_draw_buffers2",
148 "GL_EXT_draw_instanced",
149 "GL_EXT_float_blend",
150 "GL_EXT_frag_depth",
151 "GL_EXT_framebuffer_blit",
152 "GL_EXT_framebuffer_multisample",
153 "GL_EXT_framebuffer_object",
154 "GL_EXT_framebuffer_sRGB",
155 "GL_EXT_gpu_shader4",
156 "GL_EXT_map_buffer_range",
157 "GL_EXT_multisampled_render_to_texture",
158 "GL_EXT_occlusion_query_boolean",
159 "GL_EXT_packed_depth_stencil",
160 "GL_EXT_provoking_vertex",
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"};
222 static bool ShouldUseTLSIsCurrent(bool useTLSIsCurrent) {
223 if (StaticPrefs::gl_use_tls_is_current() == 0) {
224 return useTLSIsCurrent;
227 return StaticPrefs::gl_use_tls_is_current() > 0;
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;
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;
243 /*static*/
244 uint8_t GLContext::ChooseDebugFlags(const CreateContextFlags createFlags) {
245 uint8_t debugFlags = 0;
247 #ifdef MOZ_GL_DEBUG_BUILD
248 if (gfxEnv::MOZ_GL_DEBUG()) {
249 debugFlags |= GLContext::DebugFlagEnabled;
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::MOZ_GL_DEBUG_VERBOSE()) {
256 debugFlags |= GLContext::DebugFlagTrace;
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;
263 if (createFlags & CreateContextFlags::NO_VALIDATION) {
264 abortOnError = true;
266 const auto& env = gfxEnv::MOZ_GL_DEBUG_ABORT_ON_ERROR();
267 if (env.as_str == "0") {
268 abortOnError = false;
272 if (abortOnError) {
273 debugFlags |= GLContext::DebugFlagAbortOnError;
275 #endif
277 return debugFlags;
280 GLContext::GLContext(const GLContextDesc& desc, GLContext* sharedContext,
281 bool useTLSIsCurrent)
282 : mDesc(desc),
283 mUseTLSIsCurrent(ShouldUseTLSIsCurrent(useTLSIsCurrent)),
284 mDebugFlags(ChooseDebugFlags(mDesc.flags)),
285 mSharedContext(sharedContext),
286 mOwningThreadId(Some(PlatformThread::CurrentId())),
287 mWorkAroundDriverBugs(
288 StaticPrefs::gfx_work_around_driver_bugs_AtStartup()) {}
290 GLContext::~GLContext() {
291 NS_ASSERTION(
292 IsDestroyed(),
293 "GLContext implementation must call MarkDestroyed in destructor!");
294 #ifdef MOZ_GL_DEBUG_BUILD
295 if (mSharedContext) {
296 GLContext* tip = mSharedContext;
297 while (tip->mSharedContext) tip = tip->mSharedContext;
298 tip->SharedContextDestroyed(this);
299 tip->ReportOutstandingNames();
300 } else {
301 ReportOutstandingNames();
303 #endif
304 // Ensure we clear sCurrentContext if we were the last context set and avoid
305 // the memory getting reused.
306 if (sCurrentContext.init() && sCurrentContext.get() == this) {
307 sCurrentContext.set(nullptr);
311 /*static*/
312 void GLContext::InvalidateCurrentContext() {
313 if (sCurrentContext.init()) {
314 sCurrentContext.set(nullptr);
318 /*static*/
319 void GLContext::StaticDebugCallback(GLenum source, GLenum type, GLuint id,
320 GLenum severity, GLsizei length,
321 const GLchar* message,
322 const GLvoid* userParam) {
323 GLContext* gl = (GLContext*)userParam;
324 gl->DebugCallback(source, type, id, severity, length, message);
327 bool GLContext::Init() {
328 MOZ_RELEASE_ASSERT(!mSymbols.fBindFramebuffer,
329 "GFX: GLContext::Init should only be called once.");
331 ScopedGfxFeatureReporter reporter("GL Context");
333 if (!InitImpl()) {
334 // If initialization fails, zero the symbols to avoid hard-to-understand
335 // bugs.
336 mSymbols = {};
337 NS_WARNING("GLContext::InitWithPrefix failed!");
338 return false;
341 reporter.SetSuccessful();
342 return true;
345 static bool LoadSymbolsWithDesc(const SymbolLoader& loader,
346 const SymLoadStruct* list, const char* desc) {
347 const auto warnOnFailure = bool(desc);
348 if (loader.LoadSymbols(list, warnOnFailure)) return true;
350 ClearSymbols(list);
352 if (desc) {
353 const nsPrintfCString err("Failed to load symbols for %s.", desc);
354 NS_ERROR(err.BeginReading());
356 return false;
359 bool GLContext::LoadExtSymbols(const SymbolLoader& loader,
360 const SymLoadStruct* list, GLExtensions ext) {
361 const char* extName = sExtensionNames[size_t(ext)];
362 if (!LoadSymbolsWithDesc(loader, list, extName)) {
363 MarkExtensionUnsupported(ext);
364 return false;
366 return true;
369 bool GLContext::LoadFeatureSymbols(const SymbolLoader& loader,
370 const SymLoadStruct* list,
371 GLFeature feature) {
372 const char* featureName = GetFeatureName(feature);
373 if (!LoadSymbolsWithDesc(loader, list, featureName)) {
374 MarkUnsupported(feature);
375 return false;
377 return true;
380 bool GLContext::InitImpl() {
381 if (!MakeCurrent(true)) return false;
383 const auto loader = GetSymbolLoader();
384 if (!loader) return false;
386 const auto fnLoadSymbols = [&](const SymLoadStruct* const list,
387 const char* const desc) {
388 return LoadSymbolsWithDesc(*loader, list, desc);
391 // clang-format off
392 const SymLoadStruct coreSymbols[] = {
393 { (PRFuncPtr*) &mSymbols.fActiveTexture, {{ "glActiveTexture", "glActiveTextureARB" }} },
394 { (PRFuncPtr*) &mSymbols.fAttachShader, {{ "glAttachShader", "glAttachShaderARB" }} },
395 { (PRFuncPtr*) &mSymbols.fBindAttribLocation, {{ "glBindAttribLocation", "glBindAttribLocationARB" }} },
396 { (PRFuncPtr*) &mSymbols.fBindBuffer, {{ "glBindBuffer", "glBindBufferARB" }} },
397 { (PRFuncPtr*) &mSymbols.fBindTexture, {{ "glBindTexture", "glBindTextureARB" }} },
398 { (PRFuncPtr*) &mSymbols.fBlendColor, {{ "glBlendColor" }} },
399 { (PRFuncPtr*) &mSymbols.fBlendEquation, {{ "glBlendEquation" }} },
400 { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, {{ "glBlendEquationSeparate", "glBlendEquationSeparateEXT" }} },
401 { (PRFuncPtr*) &mSymbols.fBlendFunc, {{ "glBlendFunc" }} },
402 { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, {{ "glBlendFuncSeparate", "glBlendFuncSeparateEXT" }} },
403 { (PRFuncPtr*) &mSymbols.fBufferData, {{ "glBufferData" }} },
404 { (PRFuncPtr*) &mSymbols.fBufferSubData, {{ "glBufferSubData" }} },
405 { (PRFuncPtr*) &mSymbols.fClear, {{ "glClear" }} },
406 { (PRFuncPtr*) &mSymbols.fClearColor, {{ "glClearColor" }} },
407 { (PRFuncPtr*) &mSymbols.fClearStencil, {{ "glClearStencil" }} },
408 { (PRFuncPtr*) &mSymbols.fColorMask, {{ "glColorMask" }} },
409 { (PRFuncPtr*) &mSymbols.fCompressedTexImage2D, {{ "glCompressedTexImage2D" }} },
410 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage2D, {{ "glCompressedTexSubImage2D" }} },
411 { (PRFuncPtr*) &mSymbols.fCullFace, {{ "glCullFace" }} },
412 { (PRFuncPtr*) &mSymbols.fDetachShader, {{ "glDetachShader", "glDetachShaderARB" }} },
413 { (PRFuncPtr*) &mSymbols.fDepthFunc, {{ "glDepthFunc" }} },
414 { (PRFuncPtr*) &mSymbols.fDepthMask, {{ "glDepthMask" }} },
415 { (PRFuncPtr*) &mSymbols.fDisable, {{ "glDisable" }} },
416 { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, {{ "glDisableVertexAttribArray", "glDisableVertexAttribArrayARB" }} },
417 { (PRFuncPtr*) &mSymbols.fDrawArrays, {{ "glDrawArrays" }} },
418 { (PRFuncPtr*) &mSymbols.fDrawElements, {{ "glDrawElements" }} },
419 { (PRFuncPtr*) &mSymbols.fEnable, {{ "glEnable" }} },
420 { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, {{ "glEnableVertexAttribArray", "glEnableVertexAttribArrayARB" }} },
421 { (PRFuncPtr*) &mSymbols.fFinish, {{ "glFinish" }} },
422 { (PRFuncPtr*) &mSymbols.fFlush, {{ "glFlush" }} },
423 { (PRFuncPtr*) &mSymbols.fFrontFace, {{ "glFrontFace" }} },
424 { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, {{ "glGetActiveAttrib", "glGetActiveAttribARB" }} },
425 { (PRFuncPtr*) &mSymbols.fGetActiveUniform, {{ "glGetActiveUniform", "glGetActiveUniformARB" }} },
426 { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, {{ "glGetAttachedShaders", "glGetAttachedShadersARB" }} },
427 { (PRFuncPtr*) &mSymbols.fGetAttribLocation, {{ "glGetAttribLocation", "glGetAttribLocationARB" }} },
428 { (PRFuncPtr*) &mSymbols.fGetIntegerv, {{ "glGetIntegerv" }} },
429 { (PRFuncPtr*) &mSymbols.fGetFloatv, {{ "glGetFloatv" }} },
430 { (PRFuncPtr*) &mSymbols.fGetBooleanv, {{ "glGetBooleanv" }} },
431 { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, {{ "glGetBufferParameteriv", "glGetBufferParameterivARB" }} },
432 { (PRFuncPtr*) &mSymbols.fGetError, {{ "glGetError" }} },
433 { (PRFuncPtr*) &mSymbols.fGetProgramiv, {{ "glGetProgramiv", "glGetProgramivARB" }} },
434 { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, {{ "glGetProgramInfoLog", "glGetProgramInfoLogARB" }} },
435 { (PRFuncPtr*) &mSymbols.fTexParameteri, {{ "glTexParameteri" }} },
436 { (PRFuncPtr*) &mSymbols.fTexParameteriv, {{ "glTexParameteriv" }} },
437 { (PRFuncPtr*) &mSymbols.fTexParameterf, {{ "glTexParameterf" }} },
438 { (PRFuncPtr*) &mSymbols.fGetString, {{ "glGetString" }} },
439 { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, {{ "glGetTexParameterfv" }} },
440 { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, {{ "glGetTexParameteriv" }} },
441 { (PRFuncPtr*) &mSymbols.fGetUniformfv, {{ "glGetUniformfv", "glGetUniformfvARB" }} },
442 { (PRFuncPtr*) &mSymbols.fGetUniformiv, {{ "glGetUniformiv", "glGetUniformivARB" }} },
443 { (PRFuncPtr*) &mSymbols.fGetUniformLocation, {{ "glGetUniformLocation", "glGetUniformLocationARB" }} },
444 { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, {{ "glGetVertexAttribfv", "glGetVertexAttribfvARB" }} },
445 { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, {{ "glGetVertexAttribiv", "glGetVertexAttribivARB" }} },
446 { (PRFuncPtr*) &mSymbols.fGetVertexAttribPointerv, {{ "glGetVertexAttribPointerv" }} },
447 { (PRFuncPtr*) &mSymbols.fHint, {{ "glHint" }} },
448 { (PRFuncPtr*) &mSymbols.fIsBuffer, {{ "glIsBuffer", "glIsBufferARB" }} },
449 { (PRFuncPtr*) &mSymbols.fIsEnabled, {{ "glIsEnabled" }} },
450 { (PRFuncPtr*) &mSymbols.fIsProgram, {{ "glIsProgram", "glIsProgramARB" }} },
451 { (PRFuncPtr*) &mSymbols.fIsShader, {{ "glIsShader", "glIsShaderARB" }} },
452 { (PRFuncPtr*) &mSymbols.fIsTexture, {{ "glIsTexture", "glIsTextureARB" }} },
453 { (PRFuncPtr*) &mSymbols.fLineWidth, {{ "glLineWidth" }} },
454 { (PRFuncPtr*) &mSymbols.fLinkProgram, {{ "glLinkProgram", "glLinkProgramARB" }} },
455 { (PRFuncPtr*) &mSymbols.fPixelStorei, {{ "glPixelStorei" }} },
456 { (PRFuncPtr*) &mSymbols.fPolygonOffset, {{ "glPolygonOffset" }} },
457 { (PRFuncPtr*) &mSymbols.fReadPixels, {{ "glReadPixels" }} },
458 { (PRFuncPtr*) &mSymbols.fSampleCoverage, {{ "glSampleCoverage" }} },
459 { (PRFuncPtr*) &mSymbols.fScissor, {{ "glScissor" }} },
460 { (PRFuncPtr*) &mSymbols.fStencilFunc, {{ "glStencilFunc" }} },
461 { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, {{ "glStencilFuncSeparate", "glStencilFuncSeparateEXT" }} },
462 { (PRFuncPtr*) &mSymbols.fStencilMask, {{ "glStencilMask" }} },
463 { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, {{ "glStencilMaskSeparate", "glStencilMaskSeparateEXT" }} },
464 { (PRFuncPtr*) &mSymbols.fStencilOp, {{ "glStencilOp" }} },
465 { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, {{ "glStencilOpSeparate", "glStencilOpSeparateEXT" }} },
466 { (PRFuncPtr*) &mSymbols.fTexImage2D, {{ "glTexImage2D" }} },
467 { (PRFuncPtr*) &mSymbols.fTexSubImage2D, {{ "glTexSubImage2D" }} },
468 { (PRFuncPtr*) &mSymbols.fUniform1f, {{ "glUniform1f" }} },
469 { (PRFuncPtr*) &mSymbols.fUniform1fv, {{ "glUniform1fv" }} },
470 { (PRFuncPtr*) &mSymbols.fUniform1i, {{ "glUniform1i" }} },
471 { (PRFuncPtr*) &mSymbols.fUniform1iv, {{ "glUniform1iv" }} },
472 { (PRFuncPtr*) &mSymbols.fUniform2f, {{ "glUniform2f" }} },
473 { (PRFuncPtr*) &mSymbols.fUniform2fv, {{ "glUniform2fv" }} },
474 { (PRFuncPtr*) &mSymbols.fUniform2i, {{ "glUniform2i" }} },
475 { (PRFuncPtr*) &mSymbols.fUniform2iv, {{ "glUniform2iv" }} },
476 { (PRFuncPtr*) &mSymbols.fUniform3f, {{ "glUniform3f" }} },
477 { (PRFuncPtr*) &mSymbols.fUniform3fv, {{ "glUniform3fv" }} },
478 { (PRFuncPtr*) &mSymbols.fUniform3i, {{ "glUniform3i" }} },
479 { (PRFuncPtr*) &mSymbols.fUniform3iv, {{ "glUniform3iv" }} },
480 { (PRFuncPtr*) &mSymbols.fUniform4f, {{ "glUniform4f" }} },
481 { (PRFuncPtr*) &mSymbols.fUniform4fv, {{ "glUniform4fv" }} },
482 { (PRFuncPtr*) &mSymbols.fUniform4i, {{ "glUniform4i" }} },
483 { (PRFuncPtr*) &mSymbols.fUniform4iv, {{ "glUniform4iv" }} },
484 { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, {{ "glUniformMatrix2fv" }} },
485 { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, {{ "glUniformMatrix3fv" }} },
486 { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, {{ "glUniformMatrix4fv" }} },
487 { (PRFuncPtr*) &mSymbols.fUseProgram, {{ "glUseProgram" }} },
488 { (PRFuncPtr*) &mSymbols.fValidateProgram, {{ "glValidateProgram" }} },
489 { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, {{ "glVertexAttribPointer" }} },
490 { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, {{ "glVertexAttrib1f" }} },
491 { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, {{ "glVertexAttrib2f" }} },
492 { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, {{ "glVertexAttrib3f" }} },
493 { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, {{ "glVertexAttrib4f" }} },
494 { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, {{ "glVertexAttrib1fv" }} },
495 { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, {{ "glVertexAttrib2fv" }} },
496 { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, {{ "glVertexAttrib3fv" }} },
497 { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, {{ "glVertexAttrib4fv" }} },
498 { (PRFuncPtr*) &mSymbols.fViewport, {{ "glViewport" }} },
499 { (PRFuncPtr*) &mSymbols.fCompileShader, {{ "glCompileShader" }} },
500 { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, {{ "glCopyTexImage2D" }} },
501 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, {{ "glCopyTexSubImage2D" }} },
502 { (PRFuncPtr*) &mSymbols.fGetShaderiv, {{ "glGetShaderiv" }} },
503 { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, {{ "glGetShaderInfoLog" }} },
504 { (PRFuncPtr*) &mSymbols.fGetShaderSource, {{ "glGetShaderSource" }} },
505 { (PRFuncPtr*) &mSymbols.fShaderSource, {{ "glShaderSource" }} },
506 { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, {{ "glVertexAttribPointer" }} },
508 { (PRFuncPtr*) &mSymbols.fGenBuffers, {{ "glGenBuffers", "glGenBuffersARB" }} },
509 { (PRFuncPtr*) &mSymbols.fGenTextures, {{ "glGenTextures" }} },
510 { (PRFuncPtr*) &mSymbols.fCreateProgram, {{ "glCreateProgram", "glCreateProgramARB" }} },
511 { (PRFuncPtr*) &mSymbols.fCreateShader, {{ "glCreateShader", "glCreateShaderARB" }} },
513 { (PRFuncPtr*) &mSymbols.fDeleteBuffers, {{ "glDeleteBuffers", "glDeleteBuffersARB" }} },
514 { (PRFuncPtr*) &mSymbols.fDeleteTextures, {{ "glDeleteTextures", "glDeleteTexturesARB" }} },
515 { (PRFuncPtr*) &mSymbols.fDeleteProgram, {{ "glDeleteProgram", "glDeleteProgramARB" }} },
516 { (PRFuncPtr*) &mSymbols.fDeleteShader, {{ "glDeleteShader", "glDeleteShaderARB" }} },
518 END_SYMBOLS
520 // clang-format on
522 if (!fnLoadSymbols(coreSymbols, "GL")) return false;
525 const SymLoadStruct symbols[] = {
526 {(PRFuncPtr*)&mSymbols.fGetGraphicsResetStatus,
527 {{"glGetGraphicsResetStatus", "glGetGraphicsResetStatusARB",
528 "glGetGraphicsResetStatusKHR", "glGetGraphicsResetStatusEXT"}}},
529 END_SYMBOLS};
530 (void)fnLoadSymbols(symbols, nullptr);
532 // We need to call the fGetError symbol directly here because if there is an
533 // unflushed reset status, we don't want to mark the context as lost. That
534 // would prevent us from recovering.
535 auto err = mSymbols.fGetError();
536 if (err == LOCAL_GL_CONTEXT_LOST) {
537 MOZ_ASSERT(mSymbols.fGetGraphicsResetStatus);
538 const auto status = fGetGraphicsResetStatus();
539 if (status) {
540 printf_stderr("Unflushed glGetGraphicsResetStatus: 0x%04x\n", status);
542 err = fGetError();
543 MOZ_ASSERT(!err);
545 if (err) {
546 MOZ_ASSERT(false);
547 return false;
551 ////////////////
553 const auto* const versionRawStr = (const char*)fGetString(LOCAL_GL_VERSION);
554 if (!versionRawStr || !*versionRawStr) {
555 // This can happen with Pernosco.
556 NS_WARNING("Empty GL version string");
557 return false;
560 const std::string versionStr = versionRawStr;
561 if (versionStr.find("OpenGL ES") == 0) {
562 mProfile = ContextProfile::OpenGLES;
565 uint32_t majorVer, minorVer;
566 if (!ParseVersion(versionStr, &majorVer, &minorVer)) {
567 MOZ_ASSERT(false, "Failed to parse GL_VERSION");
568 return false;
570 MOZ_ASSERT(majorVer < 10);
571 MOZ_ASSERT(minorVer < 10);
572 mVersion = majorVer * 100 + minorVer * 10;
573 if (mVersion < 200) return false;
575 ////
577 const auto glslVersionStr =
578 (const char*)fGetString(LOCAL_GL_SHADING_LANGUAGE_VERSION);
579 if (!glslVersionStr) {
580 // This happens on the Android emulators. We'll just return 100
581 mShadingLanguageVersion = 100;
582 } else if (ParseVersion(glslVersionStr, &majorVer, &minorVer)) {
583 MOZ_ASSERT(majorVer < 10);
584 MOZ_ASSERT(minorVer < 100);
585 mShadingLanguageVersion = majorVer * 100 + minorVer;
586 } else {
587 MOZ_ASSERT(false, "Failed to parse GL_SHADING_LANGUAGE_VERSION");
588 return false;
591 if (ShouldSpew()) {
592 printf_stderr("GL version detected: %u\n", mVersion);
593 printf_stderr("GLSL version detected: %u\n", mShadingLanguageVersion);
594 printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR));
595 printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER));
598 ////////////////
600 // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
601 if (mProfile == ContextProfile::OpenGLES) {
602 const SymLoadStruct symbols[] = {CORE_SYMBOL(GetShaderPrecisionFormat),
603 CORE_SYMBOL(ClearDepthf),
604 CORE_SYMBOL(DepthRangef), END_SYMBOLS};
606 if (!fnLoadSymbols(symbols, "OpenGL ES")) return false;
607 } else {
608 const SymLoadStruct symbols[] = {
609 CORE_SYMBOL(ClearDepth), CORE_SYMBOL(DepthRange),
610 CORE_SYMBOL(ReadBuffer), CORE_SYMBOL(MapBuffer),
611 CORE_SYMBOL(UnmapBuffer), CORE_SYMBOL(PointParameterf),
612 CORE_SYMBOL(DrawBuffer),
613 // The following functions are only used by Skia/GL in desktop mode.
614 // Other parts of Gecko should avoid using these
615 CORE_SYMBOL(DrawBuffers), CORE_SYMBOL(ClientActiveTexture),
616 CORE_SYMBOL(DisableClientState), CORE_SYMBOL(EnableClientState),
617 CORE_SYMBOL(LoadIdentity), CORE_SYMBOL(LoadMatrixf),
618 CORE_SYMBOL(MatrixMode), CORE_SYMBOL(PolygonMode), CORE_SYMBOL(TexGeni),
619 CORE_SYMBOL(TexGenf), CORE_SYMBOL(TexGenfv), CORE_SYMBOL(VertexPointer),
620 END_SYMBOLS};
622 if (!fnLoadSymbols(symbols, "Desktop OpenGL")) return false;
625 ////////////////
627 const char* glVendorString = (const char*)fGetString(LOCAL_GL_VENDOR);
628 const char* glRendererString = (const char*)fGetString(LOCAL_GL_RENDERER);
629 if (!glVendorString || !glRendererString) return false;
631 // The order of these strings must match up with the order of the enum
632 // defined in GLContext.h for vendor IDs.
633 const char* vendorMatchStrings[size_t(GLVendor::Other) + 1] = {
634 "Intel", "NVIDIA", "ATI", "Qualcomm", "Imagination",
635 "nouveau", "Vivante", "VMware, Inc.", "ARM", "Unknown"};
637 mVendor = GLVendor::Other;
638 for (size_t i = 0; i < size_t(GLVendor::Other); ++i) {
639 if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
640 mVendor = GLVendor(i);
641 break;
645 // The order of these strings must match up with the order of the enum
646 // defined in GLContext.h for renderer IDs.
647 const char* rendererMatchStrings[size_t(GLRenderer::Other) + 1] = {
648 "Adreno 200",
649 "Adreno 205",
650 "Adreno (TM) 200",
651 "Adreno (TM) 205",
652 "Adreno (TM) 305",
653 "Adreno (TM) 320",
654 "Adreno (TM) 330",
655 "Adreno (TM) 420",
656 "Mali-400 MP",
657 "Mali-450 MP",
658 "Mali-T",
659 "PowerVR SGX 530",
660 "PowerVR SGX 540",
661 "PowerVR SGX 544MP",
662 "NVIDIA Tegra",
663 "Android Emulator",
664 "Gallium 0.4 on llvmpipe",
665 "Intel HD Graphics 3000 OpenGL Engine",
666 "Microsoft Basic Render Driver",
667 "Samsung Xclipse",
668 "Unknown"};
670 mRenderer = GLRenderer::Other;
671 for (size_t i = 0; i < size_t(GLRenderer::Other); ++i) {
672 if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) {
673 mRenderer = GLRenderer(i);
674 break;
679 const auto versionStr = (const char*)fGetString(LOCAL_GL_VERSION);
680 if (strstr(versionStr, "Mesa")) {
681 mIsMesa = true;
685 const auto Once = []() {
686 static bool did = false;
687 if (did) return false;
688 did = true;
689 return true;
692 bool printRenderer = ShouldSpew();
693 printRenderer |= (kIsDebug && Once());
694 if (printRenderer) {
695 printf_stderr("GL_VENDOR: %s\n", glVendorString);
696 printf_stderr("mVendor: %s\n", vendorMatchStrings[size_t(mVendor)]);
697 printf_stderr("GL_RENDERER: %s\n", glRendererString);
698 printf_stderr("mRenderer: %s\n", rendererMatchStrings[size_t(mRenderer)]);
699 printf_stderr("mIsMesa: %i\n", int(mIsMesa));
702 ////////////////
704 if (mVersion >= 300) { // Both GL3 and ES3.
705 const SymLoadStruct symbols[] = {
706 {(PRFuncPtr*)&mSymbols.fGetStringi, {{"glGetStringi"}}}, END_SYMBOLS};
708 if (!fnLoadSymbols(symbols, "GetStringi")) {
709 MOZ_RELEASE_ASSERT(false, "GFX: GetStringi is required!");
710 return false;
714 InitExtensions();
715 if (mProfile != ContextProfile::OpenGLES) {
716 if (mVersion >= 310 && !IsExtensionSupported(ARB_compatibility)) {
717 mProfile = ContextProfile::OpenGLCore;
718 } else {
719 mProfile = ContextProfile::OpenGLCompatibility;
722 MOZ_ASSERT(mProfile != ContextProfile::Unknown);
724 if (ShouldSpew()) {
725 const char* profileStr = "";
726 if (mProfile == ContextProfile::OpenGLES) {
727 profileStr = " es";
728 } else if (mProfile == ContextProfile::OpenGLCore) {
729 profileStr = " core";
731 printf_stderr("Detected profile: %u%s\n", mVersion, profileStr);
734 InitFeatures();
736 ////
738 // Disable extensions with partial or incorrect support.
739 if (WorkAroundDriverBugs()) {
740 if (Renderer() == GLRenderer::AdrenoTM320) {
741 MarkUnsupported(GLFeature::standard_derivatives);
744 if (Renderer() == GLRenderer::AndroidEmulator) {
745 // Bug 1665300
746 mSymbols.fGetGraphicsResetStatus = 0;
749 if (Vendor() == GLVendor::Vivante) {
750 // bug 958256
751 MarkUnsupported(GLFeature::standard_derivatives);
754 if (Renderer() == GLRenderer::MicrosoftBasicRenderDriver) {
755 // Bug 978966: on Microsoft's "Basic Render Driver" (software renderer)
756 // multisampling hardcodes blending with the default blendfunc, which
757 // breaks WebGL.
758 MarkUnsupported(GLFeature::framebuffer_multisample);
761 if (IsMesa()) {
762 // DrawElementsInstanced hangs the driver.
763 MarkUnsupported(GLFeature::robust_buffer_access_behavior);
766 if (Renderer() == GLRenderer::SamsungXclipse) {
767 MarkUnsupported(GLFeature::invalidate_framebuffer);
771 if (IsExtensionSupported(GLContext::ARB_pixel_buffer_object)) {
772 MOZ_ASSERT(
773 (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
774 "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer"
775 " being available!");
778 ////////////////////////////////////////////////////////////////////////////
780 const auto fnLoadForFeature = [&](const SymLoadStruct* list,
781 GLFeature feature) {
782 return this->LoadFeatureSymbols(*loader, list, feature);
785 // Check for ARB_framebuffer_objects
786 if (IsSupported(GLFeature::framebuffer_object)) {
787 // https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
788 const SymLoadStruct symbols[] = {
789 CORE_SYMBOL(IsRenderbuffer),
790 CORE_SYMBOL(BindRenderbuffer),
791 CORE_SYMBOL(DeleteRenderbuffers),
792 CORE_SYMBOL(GenRenderbuffers),
793 CORE_SYMBOL(RenderbufferStorage),
794 CORE_SYMBOL(RenderbufferStorageMultisample),
795 CORE_SYMBOL(GetRenderbufferParameteriv),
796 CORE_SYMBOL(IsFramebuffer),
797 CORE_SYMBOL(BindFramebuffer),
798 CORE_SYMBOL(DeleteFramebuffers),
799 CORE_SYMBOL(GenFramebuffers),
800 CORE_SYMBOL(CheckFramebufferStatus),
801 CORE_SYMBOL(FramebufferTexture2D),
802 CORE_SYMBOL(FramebufferTextureLayer),
803 CORE_SYMBOL(FramebufferRenderbuffer),
804 CORE_SYMBOL(GetFramebufferAttachmentParameteriv),
805 CORE_SYMBOL(BlitFramebuffer),
806 CORE_SYMBOL(GenerateMipmap),
807 END_SYMBOLS};
808 fnLoadForFeature(symbols, GLFeature::framebuffer_object);
811 if (!IsSupported(GLFeature::framebuffer_object)) {
812 // Check for aux symbols based on extensions
813 if (IsSupported(GLFeature::framebuffer_object_EXT_OES)) {
814 const SymLoadStruct symbols[] = {
815 CORE_EXT_SYMBOL2(IsRenderbuffer, EXT, OES),
816 CORE_EXT_SYMBOL2(BindRenderbuffer, EXT, OES),
817 CORE_EXT_SYMBOL2(DeleteRenderbuffers, EXT, OES),
818 CORE_EXT_SYMBOL2(GenRenderbuffers, EXT, OES),
819 CORE_EXT_SYMBOL2(RenderbufferStorage, EXT, OES),
820 CORE_EXT_SYMBOL2(GetRenderbufferParameteriv, EXT, OES),
821 CORE_EXT_SYMBOL2(IsFramebuffer, EXT, OES),
822 CORE_EXT_SYMBOL2(BindFramebuffer, EXT, OES),
823 CORE_EXT_SYMBOL2(DeleteFramebuffers, EXT, OES),
824 CORE_EXT_SYMBOL2(GenFramebuffers, EXT, OES),
825 CORE_EXT_SYMBOL2(CheckFramebufferStatus, EXT, OES),
826 CORE_EXT_SYMBOL2(FramebufferTexture2D, EXT, OES),
827 CORE_EXT_SYMBOL2(FramebufferRenderbuffer, EXT, OES),
828 CORE_EXT_SYMBOL2(GetFramebufferAttachmentParameteriv, EXT, OES),
829 CORE_EXT_SYMBOL2(GenerateMipmap, EXT, OES),
830 END_SYMBOLS};
831 fnLoadForFeature(symbols, GLFeature::framebuffer_object_EXT_OES);
834 if (IsSupported(GLFeature::framebuffer_blit)) {
835 const SymLoadStruct symbols[] = {
836 EXT_SYMBOL3(BlitFramebuffer, ANGLE, EXT, NV), END_SYMBOLS};
837 fnLoadForFeature(symbols, GLFeature::framebuffer_blit);
840 if (IsSupported(GLFeature::framebuffer_multisample)) {
841 const SymLoadStruct symbols[] = {
842 EXT_SYMBOL3(RenderbufferStorageMultisample, ANGLE, APPLE, EXT),
843 END_SYMBOLS};
844 fnLoadForFeature(symbols, GLFeature::framebuffer_multisample);
847 if (IsExtensionSupported(GLContext::ARB_geometry_shader4) ||
848 IsExtensionSupported(GLContext::NV_geometry_program4)) {
849 const SymLoadStruct symbols[] = {
850 EXT_SYMBOL2(FramebufferTextureLayer, ARB, EXT), END_SYMBOLS};
851 if (!fnLoadSymbols(symbols,
852 "ARB_geometry_shader4/NV_geometry_program4")) {
853 MarkExtensionUnsupported(GLContext::ARB_geometry_shader4);
854 MarkExtensionUnsupported(GLContext::NV_geometry_program4);
859 if (!IsSupported(GLFeature::framebuffer_object) &&
860 !IsSupported(GLFeature::framebuffer_object_EXT_OES)) {
861 NS_ERROR("GLContext requires support for framebuffer objects.");
862 return false;
864 MOZ_RELEASE_ASSERT(mSymbols.fBindFramebuffer,
865 "GFX: mSymbols.fBindFramebuffer zero or not set.");
867 ////////////////
869 const auto err = fGetError();
870 MOZ_RELEASE_ASSERT(!IsBadCallError(err));
871 if (err) return false;
873 LoadMoreSymbols(*loader);
875 ////////////////////////////////////////////////////////////////////////////
877 raw_fGetIntegerv(LOCAL_GL_VIEWPORT, mViewportRect);
878 raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mScissorRect);
879 raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
880 raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
881 raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
882 raw_fGetIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
884 if (mWorkAroundDriverBugs) {
885 int maxTexSize = INT32_MAX;
886 int maxCubeSize = INT32_MAX;
887 #ifdef XP_MACOSX
888 // https://bugzilla.mozilla.org/show_bug.cgi?id=1544446
889 // Mojave exposes 16k textures, but gives FRAMEBUFFER_UNSUPPORTED for any
890 // 16k*16k FB except rgba8 without depth/stencil.
891 // The max supported sizes changes based on involved formats.
892 // (RGBA32F more restrictive than RGBA16F)
893 maxTexSize = 8192;
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;
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);
911 #endif
912 if (Renderer() == GLRenderer::AdrenoTM420) {
913 // see bug 1194923. Calling glFlush before glDeleteFramebuffers
914 // prevents occasional driver crash.
915 mNeedsFlushBeforeDeleteFB = true;
918 // -
920 const auto fnLimit = [&](int* const driver, const int limit) {
921 if (*driver > limit) {
922 *driver = limit;
923 mNeedsTextureSizeChecks = true;
927 fnLimit(&mMaxTextureSize, maxTexSize);
928 fnLimit(&mMaxRenderbufferSize, maxTexSize);
930 maxCubeSize = std::min(maxCubeSize, maxTexSize);
931 fnLimit(&mMaxCubeMapTextureSize, maxCubeSize);
934 if (IsSupported(GLFeature::framebuffer_multisample)) {
935 fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples);
938 mMaxTexOrRbSize = std::min(mMaxTextureSize, mMaxRenderbufferSize);
940 ////////////////////////////////////////////////////////////////////////////
942 // We're ready for final setup.
943 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
944 MOZ_GL_ASSERT(this, IsCurrent());
946 if (ShouldSpew() && IsExtensionSupported(KHR_debug)) {
947 fEnable(LOCAL_GL_DEBUG_OUTPUT);
948 fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS);
949 fDebugMessageCallback(&StaticDebugCallback, (void*)this);
950 fDebugMessageControl(LOCAL_GL_DONT_CARE, LOCAL_GL_DONT_CARE,
951 LOCAL_GL_DONT_CARE, 0, nullptr, true);
954 return true;
957 void GLContext::LoadMoreSymbols(const SymbolLoader& loader) {
958 const auto fnLoadForExt = [&](const SymLoadStruct* list, GLExtensions ext) {
959 return this->LoadExtSymbols(loader, list, ext);
962 const auto fnLoadForFeature = [&](const SymLoadStruct* list,
963 GLFeature feature) {
964 return this->LoadFeatureSymbols(loader, list, feature);
967 const auto fnLoadFeatureByCore = [&](const SymLoadStruct* coreList,
968 const SymLoadStruct* extList,
969 GLFeature feature) {
970 const bool useCore = this->IsFeatureProvidedByCoreSymbols(feature);
971 const auto list = useCore ? coreList : extList;
972 return fnLoadForFeature(list, feature);
975 if (IsSupported(GLFeature::robustness)) {
976 const auto resetStrategy =
977 GetIntAs<GLuint>(LOCAL_GL_RESET_NOTIFICATION_STRATEGY);
978 if (resetStrategy != LOCAL_GL_LOSE_CONTEXT_ON_RESET) {
979 NS_WARNING(
980 "Robustness supported, strategy is not LOSE_CONTEXT_ON_RESET!");
981 if (ShouldSpew()) {
982 const bool isDisabled =
983 (resetStrategy == LOCAL_GL_NO_RESET_NOTIFICATION);
984 printf_stderr("Strategy: %s (0x%04x)",
985 (isDisabled ? "disabled" : "unrecognized"),
986 resetStrategy);
988 MarkUnsupported(GLFeature::robustness);
992 if (IsSupported(GLFeature::sync)) {
993 const SymLoadStruct symbols[] = {
994 CORE_SYMBOL(FenceSync), CORE_SYMBOL(IsSync),
995 CORE_SYMBOL(DeleteSync), CORE_SYMBOL(ClientWaitSync),
996 CORE_SYMBOL(WaitSync), CORE_SYMBOL(GetInteger64v),
997 CORE_SYMBOL(GetSynciv), END_SYMBOLS};
998 fnLoadForFeature(symbols, GLFeature::sync);
1001 if (IsExtensionSupported(OES_EGL_image)) {
1002 const SymLoadStruct symbols[] = {
1003 {(PRFuncPtr*)&mSymbols.fEGLImageTargetTexture2D,
1004 {{"glEGLImageTargetTexture2DOES"}}},
1005 {(PRFuncPtr*)&mSymbols.fEGLImageTargetRenderbufferStorage,
1006 {{"glEGLImageTargetRenderbufferStorageOES"}}},
1007 END_SYMBOLS};
1008 fnLoadForExt(symbols, OES_EGL_image);
1011 if (IsExtensionSupported(APPLE_texture_range)) {
1012 const SymLoadStruct symbols[] = {CORE_SYMBOL(TextureRangeAPPLE),
1013 END_SYMBOLS};
1014 fnLoadForExt(symbols, APPLE_texture_range);
1017 if (IsExtensionSupported(APPLE_fence)) {
1018 const SymLoadStruct symbols[] = {CORE_SYMBOL(FinishObjectAPPLE),
1019 CORE_SYMBOL(TestObjectAPPLE), END_SYMBOLS};
1020 fnLoadForExt(symbols, APPLE_fence);
1023 // clang-format off
1025 if (IsSupported(GLFeature::vertex_array_object)) {
1026 const SymLoadStruct coreSymbols[] = {
1027 { (PRFuncPtr*) &mSymbols.fIsVertexArray, {{ "glIsVertexArray" }} },
1028 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, {{ "glGenVertexArrays" }} },
1029 { (PRFuncPtr*) &mSymbols.fBindVertexArray, {{ "glBindVertexArray" }} },
1030 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, {{ "glDeleteVertexArrays" }} },
1031 END_SYMBOLS
1033 const SymLoadStruct extSymbols[] = {
1034 { (PRFuncPtr*) &mSymbols.fIsVertexArray, {{ "glIsVertexArrayARB", "glIsVertexArrayOES", "glIsVertexArrayAPPLE" }} },
1035 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, {{ "glGenVertexArraysARB", "glGenVertexArraysOES", "glGenVertexArraysAPPLE" }} },
1036 { (PRFuncPtr*) &mSymbols.fBindVertexArray, {{ "glBindVertexArrayARB", "glBindVertexArrayOES", "glBindVertexArrayAPPLE" }} },
1037 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, {{ "glDeleteVertexArraysARB", "glDeleteVertexArraysOES", "glDeleteVertexArraysAPPLE" }} },
1038 END_SYMBOLS
1040 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::vertex_array_object);
1043 if (IsSupported(GLFeature::draw_instanced)) {
1044 const SymLoadStruct coreSymbols[] = {
1045 { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, {{ "glDrawArraysInstanced" }} },
1046 { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, {{ "glDrawElementsInstanced" }} },
1047 END_SYMBOLS
1049 const SymLoadStruct extSymbols[] = {
1050 { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, {{ "glDrawArraysInstancedARB", "glDrawArraysInstancedEXT", "glDrawArraysInstancedNV", "glDrawArraysInstancedANGLE" }} },
1051 { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, {{ "glDrawElementsInstancedARB", "glDrawElementsInstancedEXT", "glDrawElementsInstancedNV", "glDrawElementsInstancedANGLE" }}
1053 END_SYMBOLS
1055 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_instanced);
1058 if (IsSupported(GLFeature::instanced_arrays)) {
1059 const SymLoadStruct coreSymbols[] = {
1060 { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, {{ "glVertexAttribDivisor" }} },
1061 END_SYMBOLS
1063 const SymLoadStruct extSymbols[] = {
1064 { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, {{ "glVertexAttribDivisorARB", "glVertexAttribDivisorNV", "glVertexAttribDivisorANGLE" }} },
1065 END_SYMBOLS
1067 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::instanced_arrays);
1070 if (IsSupported(GLFeature::texture_storage)) {
1071 const SymLoadStruct coreSymbols[] = {
1072 { (PRFuncPtr*) &mSymbols.fTexStorage2D, {{ "glTexStorage2D" }} },
1073 { (PRFuncPtr*) &mSymbols.fTexStorage3D, {{ "glTexStorage3D" }} },
1074 END_SYMBOLS
1076 const SymLoadStruct extSymbols[] = {
1077 { (PRFuncPtr*) &mSymbols.fTexStorage2D, {{ "glTexStorage2DEXT" }} },
1078 { (PRFuncPtr*) &mSymbols.fTexStorage3D, {{ "glTexStorage3DEXT" }} },
1079 END_SYMBOLS
1081 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_storage);
1084 if (IsSupported(GLFeature::sampler_objects)) {
1085 const SymLoadStruct symbols[] = {
1086 { (PRFuncPtr*) &mSymbols.fGenSamplers, {{ "glGenSamplers" }} },
1087 { (PRFuncPtr*) &mSymbols.fDeleteSamplers, {{ "glDeleteSamplers" }} },
1088 { (PRFuncPtr*) &mSymbols.fIsSampler, {{ "glIsSampler" }} },
1089 { (PRFuncPtr*) &mSymbols.fBindSampler, {{ "glBindSampler" }} },
1090 { (PRFuncPtr*) &mSymbols.fSamplerParameteri, {{ "glSamplerParameteri" }} },
1091 { (PRFuncPtr*) &mSymbols.fSamplerParameteriv, {{ "glSamplerParameteriv" }} },
1092 { (PRFuncPtr*) &mSymbols.fSamplerParameterf, {{ "glSamplerParameterf" }} },
1093 { (PRFuncPtr*) &mSymbols.fSamplerParameterfv, {{ "glSamplerParameterfv" }} },
1094 { (PRFuncPtr*) &mSymbols.fGetSamplerParameteriv, {{ "glGetSamplerParameteriv" }} },
1095 { (PRFuncPtr*) &mSymbols.fGetSamplerParameterfv, {{ "glGetSamplerParameterfv" }} },
1096 END_SYMBOLS
1098 fnLoadForFeature(symbols, GLFeature::sampler_objects);
1101 // ARB_transform_feedback2/NV_transform_feedback2 is a
1102 // superset of EXT_transform_feedback/NV_transform_feedback
1103 // and adds glPauseTransformFeedback &
1104 // glResumeTransformFeedback, which are required for WebGL2.
1105 if (IsSupported(GLFeature::transform_feedback2)) {
1106 const SymLoadStruct coreSymbols[] = {
1107 { (PRFuncPtr*) &mSymbols.fBindBufferBase, {{ "glBindBufferBase" }} },
1108 { (PRFuncPtr*) &mSymbols.fBindBufferRange, {{ "glBindBufferRange" }} },
1109 { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, {{ "glGenTransformFeedbacks" }} },
1110 { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, {{ "glBindTransformFeedback" }} },
1111 { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, {{ "glDeleteTransformFeedbacks" }} },
1112 { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, {{ "glIsTransformFeedback" }} },
1113 { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, {{ "glBeginTransformFeedback" }} },
1114 { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, {{ "glEndTransformFeedback" }} },
1115 { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, {{ "glTransformFeedbackVaryings" }} },
1116 { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, {{ "glGetTransformFeedbackVarying" }} },
1117 { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, {{ "glPauseTransformFeedback" }} },
1118 { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, {{ "glResumeTransformFeedback" }} },
1119 END_SYMBOLS
1121 const SymLoadStruct extSymbols[] = {
1122 { (PRFuncPtr*) &mSymbols.fBindBufferBase, {{ "glBindBufferBaseEXT", "glBindBufferBaseNV" }} },
1123 { (PRFuncPtr*) &mSymbols.fBindBufferRange, {{ "glBindBufferRangeEXT", "glBindBufferRangeNV" }} },
1124 { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, {{ "glGenTransformFeedbacksNV" }} },
1125 { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, {{ "glBindTransformFeedbackNV" }} },
1126 { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, {{ "glDeleteTransformFeedbacksNV" }} },
1127 { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, {{ "glIsTransformFeedbackNV" }} },
1128 { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, {{ "glBeginTransformFeedbackEXT", "glBeginTransformFeedbackNV" }} },
1129 { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, {{ "glEndTransformFeedbackEXT", "glEndTransformFeedbackNV" }} },
1130 { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, {{ "glTransformFeedbackVaryingsEXT", "glTransformFeedbackVaryingsNV" }} },
1131 { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, {{ "glGetTransformFeedbackVaryingEXT", "glGetTransformFeedbackVaryingNV" }} },
1132 { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, {{ "glPauseTransformFeedbackNV" }} },
1133 { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, {{ "glResumeTransformFeedbackNV" }} },
1134 END_SYMBOLS
1136 if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::transform_feedback2)) {
1137 // Also mark bind_buffer_offset as unsupported.
1138 MarkUnsupported(GLFeature::bind_buffer_offset);
1142 if (IsSupported(GLFeature::bind_buffer_offset)) {
1143 const SymLoadStruct coreSymbols[] = {
1144 { (PRFuncPtr*) &mSymbols.fBindBufferOffset, {{ "glBindBufferOffset" }} },
1145 END_SYMBOLS
1147 const SymLoadStruct extSymbols[] = {
1148 { (PRFuncPtr*) &mSymbols.fBindBufferOffset,
1149 {{ "glBindBufferOffsetEXT", "glBindBufferOffsetNV" }}
1151 END_SYMBOLS
1153 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::bind_buffer_offset);
1156 if (IsSupported(GLFeature::query_counter)) {
1157 const SymLoadStruct coreSymbols[] = {
1158 { (PRFuncPtr*) &mSymbols.fQueryCounter, {{ "glQueryCounter" }} },
1159 END_SYMBOLS
1161 const SymLoadStruct extSymbols[] = {
1162 { (PRFuncPtr*) &mSymbols.fQueryCounter, {{ "glQueryCounterEXT", "glQueryCounterANGLE" }} },
1163 END_SYMBOLS
1165 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_counter);
1168 if (IsSupported(GLFeature::query_objects)) {
1169 const SymLoadStruct coreSymbols[] = {
1170 { (PRFuncPtr*) &mSymbols.fBeginQuery, {{ "glBeginQuery" }} },
1171 { (PRFuncPtr*) &mSymbols.fGenQueries, {{ "glGenQueries" }} },
1172 { (PRFuncPtr*) &mSymbols.fDeleteQueries, {{ "glDeleteQueries" }} },
1173 { (PRFuncPtr*) &mSymbols.fEndQuery, {{ "glEndQuery" }} },
1174 { (PRFuncPtr*) &mSymbols.fGetQueryiv, {{ "glGetQueryiv" }} },
1175 { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, {{ "glGetQueryObjectuiv" }} },
1176 { (PRFuncPtr*) &mSymbols.fIsQuery, {{ "glIsQuery" }} },
1177 END_SYMBOLS
1179 const SymLoadStruct extSymbols[] = {
1180 { (PRFuncPtr*) &mSymbols.fBeginQuery, {{ "glBeginQueryEXT", "glBeginQueryANGLE" }} },
1181 { (PRFuncPtr*) &mSymbols.fGenQueries, {{ "glGenQueriesEXT", "glGenQueriesANGLE" }} },
1182 { (PRFuncPtr*) &mSymbols.fDeleteQueries, {{ "glDeleteQueriesEXT", "glDeleteQueriesANGLE" }} },
1183 { (PRFuncPtr*) &mSymbols.fEndQuery, {{ "glEndQueryEXT", "glEndQueryANGLE" }} },
1184 { (PRFuncPtr*) &mSymbols.fGetQueryiv, {{ "glGetQueryivEXT", "glGetQueryivANGLE" }} },
1185 { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, {{ "glGetQueryObjectuivEXT", "glGetQueryObjectuivANGLE" }} },
1186 { (PRFuncPtr*) &mSymbols.fIsQuery, {{ "glIsQueryEXT", "glIsQueryANGLE" }} },
1187 END_SYMBOLS
1189 if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_objects)) {
1190 MarkUnsupported(GLFeature::get_query_object_i64v);
1191 MarkUnsupported(GLFeature::get_query_object_iv);
1192 MarkUnsupported(GLFeature::occlusion_query);
1193 MarkUnsupported(GLFeature::occlusion_query_boolean);
1194 MarkUnsupported(GLFeature::occlusion_query2);
1198 if (IsSupported(GLFeature::get_query_object_i64v)) {
1199 const SymLoadStruct coreSymbols[] = {
1200 { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, {{ "glGetQueryObjecti64v" }} },
1201 { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, {{ "glGetQueryObjectui64v" }} },
1202 END_SYMBOLS
1204 const SymLoadStruct extSymbols[] = {
1205 { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, {{ "glGetQueryObjecti64vEXT", "glGetQueryObjecti64vANGLE" }} },
1206 { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, {{ "glGetQueryObjectui64vEXT", "glGetQueryObjectui64vANGLE" }} },
1207 END_SYMBOLS
1209 if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_i64v)) {
1210 MarkUnsupported(GLFeature::query_counter);
1214 if (IsSupported(GLFeature::get_query_object_iv)) {
1215 const SymLoadStruct coreSymbols[] = {
1216 { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, {{ "glGetQueryObjectiv" }} },
1217 END_SYMBOLS
1219 const SymLoadStruct extSymbols[] = {
1220 { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, {{ "glGetQueryObjectivEXT", "glGetQueryObjectivANGLE" }} },
1221 END_SYMBOLS
1223 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_iv);
1226 if (IsSupported(GLFeature::clear_buffers)) {
1227 const SymLoadStruct symbols[] = {
1228 { (PRFuncPtr*) &mSymbols.fClearBufferfi, {{ "glClearBufferfi", }} },
1229 { (PRFuncPtr*) &mSymbols.fClearBufferfv, {{ "glClearBufferfv", }} },
1230 { (PRFuncPtr*) &mSymbols.fClearBufferiv, {{ "glClearBufferiv", }} },
1231 { (PRFuncPtr*) &mSymbols.fClearBufferuiv, {{ "glClearBufferuiv" }} },
1232 END_SYMBOLS
1234 fnLoadForFeature(symbols, GLFeature::clear_buffers);
1237 if (IsSupported(GLFeature::copy_buffer)) {
1238 const SymLoadStruct symbols[] = {
1239 { (PRFuncPtr*) &mSymbols.fCopyBufferSubData, {{ "glCopyBufferSubData" }} },
1240 END_SYMBOLS
1242 fnLoadForFeature(symbols, GLFeature::copy_buffer);
1245 if (IsSupported(GLFeature::draw_buffers)) {
1246 const SymLoadStruct coreSymbols[] = {
1247 { (PRFuncPtr*) &mSymbols.fDrawBuffers, {{ "glDrawBuffers" }} },
1248 END_SYMBOLS
1250 const SymLoadStruct extSymbols[] = {
1251 { (PRFuncPtr*) &mSymbols.fDrawBuffers, {{ "glDrawBuffersARB", "glDrawBuffersEXT" }} },
1252 END_SYMBOLS
1254 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers);
1257 if (IsSupported(GLFeature::draw_buffers_indexed)) {
1258 const SymLoadStruct coreSymbols[] = {
1259 { (PRFuncPtr*) &mSymbols.fBlendEquationSeparatei, {{ "glBlendEquationSeparatei" }} },
1260 { (PRFuncPtr*) &mSymbols.fBlendFuncSeparatei, {{ "glBlendFuncSeparatei" }} },
1261 { (PRFuncPtr*) &mSymbols.fColorMaski, {{ "glColorMaski" }} },
1262 { (PRFuncPtr*) &mSymbols.fDisablei, {{ "glDisablei" }} },
1263 { (PRFuncPtr*) &mSymbols.fEnablei, {{ "glEnablei" }} },
1264 END_SYMBOLS
1266 const SymLoadStruct extSymbols[] = {
1267 { (PRFuncPtr*) &mSymbols.fBlendEquationSeparatei, {{ "glBlendEquationSeparateiOES" }} },
1268 { (PRFuncPtr*) &mSymbols.fBlendFuncSeparatei, {{ "glBlendFuncSeparateiOES" }} },
1269 { (PRFuncPtr*) &mSymbols.fColorMaski, {{ "glColorMaskiOES" }} },
1270 { (PRFuncPtr*) &mSymbols.fDisablei, {{ "glDisableiOES" }} },
1271 { (PRFuncPtr*) &mSymbols.fEnablei, {{ "glEnableiOES" }} },
1272 END_SYMBOLS
1274 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers_indexed);
1277 if (IsSupported(GLFeature::get_integer_indexed)) {
1278 const SymLoadStruct coreSymbols[] = {
1279 { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, {{ "glGetIntegeri_v" }} },
1280 END_SYMBOLS
1282 const SymLoadStruct extSymbols[] ={
1283 { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, {{ "glGetIntegerIndexedvEXT" }} },
1284 END_SYMBOLS
1286 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_integer_indexed);
1289 if (IsSupported(GLFeature::get_integer64_indexed)) {
1290 const SymLoadStruct symbols[] = {
1291 { (PRFuncPtr*) &mSymbols.fGetInteger64i_v, {{ "glGetInteger64i_v" }} },
1292 END_SYMBOLS
1294 fnLoadForFeature(symbols, GLFeature::get_integer64_indexed);
1297 if (IsSupported(GLFeature::gpu_shader4)) {
1298 const SymLoadStruct symbols[] = {
1299 { (PRFuncPtr*) &mSymbols.fGetVertexAttribIiv, {{ "glGetVertexAttribIiv", "glGetVertexAttribIivEXT" }} },
1300 { (PRFuncPtr*) &mSymbols.fGetVertexAttribIuiv, {{ "glGetVertexAttribIuiv", "glGetVertexAttribIuivEXT" }} },
1301 { (PRFuncPtr*) &mSymbols.fVertexAttribI4i, {{ "glVertexAttribI4i", "glVertexAttribI4iEXT" }} },
1302 { (PRFuncPtr*) &mSymbols.fVertexAttribI4iv, {{ "glVertexAttribI4iv", "glVertexAttribI4ivEXT" }} },
1303 { (PRFuncPtr*) &mSymbols.fVertexAttribI4ui, {{ "glVertexAttribI4ui", "glVertexAttribI4uiEXT" }} },
1304 { (PRFuncPtr*) &mSymbols.fVertexAttribI4uiv, {{ "glVertexAttribI4uiv", "glVertexAttribI4uivEXT" }} },
1305 { (PRFuncPtr*) &mSymbols.fVertexAttribIPointer, {{ "glVertexAttribIPointer", "glVertexAttribIPointerEXT" }} },
1306 { (PRFuncPtr*) &mSymbols.fUniform1ui, {{ "glUniform1ui", "glUniform1uiEXT" }} },
1307 { (PRFuncPtr*) &mSymbols.fUniform2ui, {{ "glUniform2ui", "glUniform2uiEXT" }} },
1308 { (PRFuncPtr*) &mSymbols.fUniform3ui, {{ "glUniform3ui", "glUniform3uiEXT" }} },
1309 { (PRFuncPtr*) &mSymbols.fUniform4ui, {{ "glUniform4ui", "glUniform4uiEXT" }} },
1310 { (PRFuncPtr*) &mSymbols.fUniform1uiv, {{ "glUniform1uiv", "glUniform1uivEXT" }} },
1311 { (PRFuncPtr*) &mSymbols.fUniform2uiv, {{ "glUniform2uiv", "glUniform2uivEXT" }} },
1312 { (PRFuncPtr*) &mSymbols.fUniform3uiv, {{ "glUniform3uiv", "glUniform3uivEXT" }} },
1313 { (PRFuncPtr*) &mSymbols.fUniform4uiv, {{ "glUniform4uiv", "glUniform4uivEXT" }} },
1314 { (PRFuncPtr*) &mSymbols.fGetFragDataLocation, {{ "glGetFragDataLocation", "glGetFragDataLocationEXT" }} },
1315 { (PRFuncPtr*) &mSymbols.fGetUniformuiv, {{ "glGetUniformuiv", "glGetUniformuivEXT" }} },
1316 END_SYMBOLS
1318 fnLoadForFeature(symbols, GLFeature::gpu_shader4);
1321 if (IsSupported(GLFeature::map_buffer_range)) {
1322 const SymLoadStruct symbols[] = {
1323 { (PRFuncPtr*) &mSymbols.fMapBufferRange, {{ "glMapBufferRange" }} },
1324 { (PRFuncPtr*) &mSymbols.fFlushMappedBufferRange, {{ "glFlushMappedBufferRange" }} },
1325 { (PRFuncPtr*) &mSymbols.fUnmapBuffer, {{ "glUnmapBuffer" }} },
1326 END_SYMBOLS
1328 fnLoadForFeature(symbols, GLFeature::map_buffer_range);
1331 if (IsSupported(GLFeature::texture_3D)) {
1332 const SymLoadStruct coreSymbols[] = {
1333 { (PRFuncPtr*) &mSymbols.fTexImage3D, {{ "glTexImage3D" }} },
1334 { (PRFuncPtr*) &mSymbols.fTexSubImage3D, {{ "glTexSubImage3D" }} },
1335 END_SYMBOLS
1337 const SymLoadStruct extSymbols[] = {
1338 { (PRFuncPtr*) &mSymbols.fTexImage3D, {{ "glTexImage3DOES" }} },
1339 { (PRFuncPtr*) &mSymbols.fTexSubImage3D, {{ "glTexSubImage3DOES" }} },
1340 END_SYMBOLS
1342 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D);
1345 if (IsSupported(GLFeature::texture_3D_compressed)) {
1346 const SymLoadStruct coreSymbols[] = {
1347 { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, {{ "glCompressedTexImage3D" }} },
1348 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, {{ "glCompressedTexSubImage3D" }} },
1349 END_SYMBOLS
1351 const SymLoadStruct extSymbols[] = {
1352 { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, {{ "glCompressedTexImage3DARB", "glCompressedTexImage3DOES" }} },
1353 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, {{ "glCompressedTexSubImage3DARB", "glCompressedTexSubImage3DOES" }} },
1354 END_SYMBOLS
1356 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_compressed);
1359 if (IsSupported(GLFeature::texture_3D_copy)) {
1360 const SymLoadStruct coreSymbols[] = {
1361 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, {{ "glCopyTexSubImage3D" }} },
1362 END_SYMBOLS
1364 const SymLoadStruct extSymbols[] = {
1365 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, {{ "glCopyTexSubImage3DEXT", "glCopyTexSubImage3DOES" }} },
1366 END_SYMBOLS
1368 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_copy);
1371 if (IsSupported(GLFeature::uniform_buffer_object)) {
1372 // Note: Don't query for glGetActiveUniformName because it is not
1373 // supported by GL ES 3.
1374 const SymLoadStruct symbols[] = {
1375 { (PRFuncPtr*) &mSymbols.fGetUniformIndices, {{ "glGetUniformIndices" }} },
1376 { (PRFuncPtr*) &mSymbols.fGetActiveUniformsiv, {{ "glGetActiveUniformsiv" }} },
1377 { (PRFuncPtr*) &mSymbols.fGetUniformBlockIndex, {{ "glGetUniformBlockIndex" }} },
1378 { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockiv, {{ "glGetActiveUniformBlockiv" }} },
1379 { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockName, {{ "glGetActiveUniformBlockName" }} },
1380 { (PRFuncPtr*) &mSymbols.fUniformBlockBinding, {{ "glUniformBlockBinding" }} },
1381 END_SYMBOLS
1383 fnLoadForFeature(symbols, GLFeature::uniform_buffer_object);
1386 if (IsSupported(GLFeature::uniform_matrix_nonsquare)) {
1387 const SymLoadStruct symbols[] = {
1388 { (PRFuncPtr*) &mSymbols.fUniformMatrix2x3fv, {{ "glUniformMatrix2x3fv" }} },
1389 { (PRFuncPtr*) &mSymbols.fUniformMatrix2x4fv, {{ "glUniformMatrix2x4fv" }} },
1390 { (PRFuncPtr*) &mSymbols.fUniformMatrix3x2fv, {{ "glUniformMatrix3x2fv" }} },
1391 { (PRFuncPtr*) &mSymbols.fUniformMatrix3x4fv, {{ "glUniformMatrix3x4fv" }} },
1392 { (PRFuncPtr*) &mSymbols.fUniformMatrix4x2fv, {{ "glUniformMatrix4x2fv" }} },
1393 { (PRFuncPtr*) &mSymbols.fUniformMatrix4x3fv, {{ "glUniformMatrix4x3fv" }} },
1394 END_SYMBOLS
1396 fnLoadForFeature(symbols, GLFeature::uniform_matrix_nonsquare);
1399 if (IsSupported(GLFeature::internalformat_query)) {
1400 const SymLoadStruct symbols[] = {
1401 CORE_SYMBOL(GetInternalformativ),
1402 END_SYMBOLS
1404 fnLoadForFeature(symbols, GLFeature::internalformat_query);
1407 if (IsSupported(GLFeature::invalidate_framebuffer)) {
1408 const SymLoadStruct symbols[] = {
1409 { (PRFuncPtr*) &mSymbols.fInvalidateFramebuffer, {{ "glInvalidateFramebuffer" }} },
1410 { (PRFuncPtr*) &mSymbols.fInvalidateSubFramebuffer, {{ "glInvalidateSubFramebuffer" }} },
1411 END_SYMBOLS
1413 fnLoadForFeature(symbols, GLFeature::invalidate_framebuffer);
1416 if (IsSupported(GLFeature::multiview)) {
1417 const SymLoadStruct symbols[] = {
1418 { (PRFuncPtr*) &mSymbols.fFramebufferTextureMultiview, {{
1419 "glFramebufferTextureMultiviewOVR",
1420 "glFramebufferTextureMultiviewLayeredANGLE"
1421 }} },
1422 END_SYMBOLS
1424 fnLoadForFeature(symbols, GLFeature::multiview);
1427 if (IsSupported(GLFeature::prim_restart)) {
1428 const SymLoadStruct symbols[] = {
1429 { (PRFuncPtr*) &mSymbols.fPrimitiveRestartIndex, {{ "glPrimitiveRestartIndex", "glPrimitiveRestartIndexNV" }} },
1430 END_SYMBOLS
1432 fnLoadForFeature(symbols, GLFeature::prim_restart);
1435 if (IsExtensionSupported(KHR_debug)) {
1436 const SymLoadStruct symbols[] = {
1437 { (PRFuncPtr*) &mSymbols.fDebugMessageControl, {{ "glDebugMessageControl", "glDebugMessageControlKHR", }} },
1438 { (PRFuncPtr*) &mSymbols.fDebugMessageInsert, {{ "glDebugMessageInsert", "glDebugMessageInsertKHR", }} },
1439 { (PRFuncPtr*) &mSymbols.fDebugMessageCallback, {{ "glDebugMessageCallback", "glDebugMessageCallbackKHR" }} },
1440 { (PRFuncPtr*) &mSymbols.fGetDebugMessageLog, {{ "glGetDebugMessageLog", "glGetDebugMessageLogKHR", }} },
1441 { (PRFuncPtr*) &mSymbols.fGetPointerv, {{ "glGetPointerv", "glGetPointervKHR", }} },
1442 { (PRFuncPtr*) &mSymbols.fPushDebugGroup, {{ "glPushDebugGroup", "glPushDebugGroupKHR", }} },
1443 { (PRFuncPtr*) &mSymbols.fPopDebugGroup, {{ "glPopDebugGroup", "glPopDebugGroupKHR", }} },
1444 { (PRFuncPtr*) &mSymbols.fObjectLabel, {{ "glObjectLabel", "glObjectLabelKHR", }} },
1445 { (PRFuncPtr*) &mSymbols.fGetObjectLabel, {{ "glGetObjectLabel", "glGetObjectLabelKHR", }} },
1446 { (PRFuncPtr*) &mSymbols.fObjectPtrLabel, {{ "glObjectPtrLabel", "glObjectPtrLabelKHR", }} },
1447 { (PRFuncPtr*) &mSymbols.fGetObjectPtrLabel, {{ "glGetObjectPtrLabel", "glGetObjectPtrLabelKHR", }} },
1448 END_SYMBOLS
1450 fnLoadForExt(symbols, KHR_debug);
1453 if (IsExtensionSupported(NV_fence)) {
1454 const SymLoadStruct symbols[] = {
1455 { (PRFuncPtr*) &mSymbols.fGenFences, {{ "glGenFencesNV" }} },
1456 { (PRFuncPtr*) &mSymbols.fDeleteFences, {{ "glDeleteFencesNV" }} },
1457 { (PRFuncPtr*) &mSymbols.fSetFence, {{ "glSetFenceNV" }} },
1458 { (PRFuncPtr*) &mSymbols.fTestFence, {{ "glTestFenceNV" }} },
1459 { (PRFuncPtr*) &mSymbols.fFinishFence, {{ "glFinishFenceNV" }} },
1460 { (PRFuncPtr*) &mSymbols.fIsFence, {{ "glIsFenceNV" }} },
1461 { (PRFuncPtr*) &mSymbols.fGetFenceiv, {{ "glGetFenceivNV" }} },
1462 END_SYMBOLS
1464 fnLoadForExt(symbols, NV_fence);
1467 // clang-format on
1469 if (IsExtensionSupported(NV_texture_barrier)) {
1470 const SymLoadStruct symbols[] = {
1471 {(PRFuncPtr*)&mSymbols.fTextureBarrier, {{"glTextureBarrierNV"}}},
1472 END_SYMBOLS};
1473 fnLoadForExt(symbols, NV_texture_barrier);
1476 if (IsSupported(GLFeature::read_buffer)) {
1477 const SymLoadStruct symbols[] = {CORE_SYMBOL(ReadBuffer), END_SYMBOLS};
1478 fnLoadForFeature(symbols, GLFeature::read_buffer);
1481 if (IsExtensionSupported(APPLE_framebuffer_multisample)) {
1482 const SymLoadStruct symbols[] = {
1483 CORE_SYMBOL(ResolveMultisampleFramebufferAPPLE), END_SYMBOLS};
1484 fnLoadForExt(symbols, APPLE_framebuffer_multisample);
1487 if (IsSupported(GLFeature::provoking_vertex)) {
1488 const SymLoadStruct symbols[] = {{(PRFuncPtr*)&mSymbols.fProvokingVertex,
1490 "glProvokingVertex",
1491 "glProvokingVertexANGLE",
1492 "glProvokingVertexEXT",
1493 }}},
1494 END_SYMBOLS};
1495 fnLoadForFeature(symbols, GLFeature::provoking_vertex);
1498 // Load developer symbols, don't fail if we can't find them.
1499 const SymLoadStruct devSymbols[] = {CORE_SYMBOL(GetTexImage),
1500 CORE_SYMBOL(GetTexLevelParameteriv),
1501 END_SYMBOLS};
1502 const bool warnOnFailures = ShouldSpew();
1503 (void)loader.LoadSymbols(devSymbols, warnOnFailures);
1506 #undef CORE_SYMBOL
1507 #undef CORE_EXT_SYMBOL2
1508 #undef EXT_SYMBOL2
1509 #undef EXT_SYMBOL3
1510 #undef END_SYMBOLS
1512 void GLContext::DebugCallback(GLenum source, GLenum type, GLuint id,
1513 GLenum severity, GLsizei length,
1514 const GLchar* message) {
1515 nsAutoCString sourceStr;
1516 switch (source) {
1517 case LOCAL_GL_DEBUG_SOURCE_API:
1518 sourceStr = "SOURCE_API"_ns;
1519 break;
1520 case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1521 sourceStr = "SOURCE_WINDOW_SYSTEM"_ns;
1522 break;
1523 case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER:
1524 sourceStr = "SOURCE_SHADER_COMPILER"_ns;
1525 break;
1526 case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY:
1527 sourceStr = "SOURCE_THIRD_PARTY"_ns;
1528 break;
1529 case LOCAL_GL_DEBUG_SOURCE_APPLICATION:
1530 sourceStr = "SOURCE_APPLICATION"_ns;
1531 break;
1532 case LOCAL_GL_DEBUG_SOURCE_OTHER:
1533 sourceStr = "SOURCE_OTHER"_ns;
1534 break;
1535 default:
1536 sourceStr = nsPrintfCString("<source 0x%04x>", source);
1537 break;
1540 nsAutoCString typeStr;
1541 switch (type) {
1542 case LOCAL_GL_DEBUG_TYPE_ERROR:
1543 typeStr = "TYPE_ERROR"_ns;
1544 break;
1545 case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1546 typeStr = "TYPE_DEPRECATED_BEHAVIOR"_ns;
1547 break;
1548 case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1549 typeStr = "TYPE_UNDEFINED_BEHAVIOR"_ns;
1550 break;
1551 case LOCAL_GL_DEBUG_TYPE_PORTABILITY:
1552 typeStr = "TYPE_PORTABILITY"_ns;
1553 break;
1554 case LOCAL_GL_DEBUG_TYPE_PERFORMANCE:
1555 typeStr = "TYPE_PERFORMANCE"_ns;
1556 break;
1557 case LOCAL_GL_DEBUG_TYPE_OTHER:
1558 typeStr = "TYPE_OTHER"_ns;
1559 break;
1560 case LOCAL_GL_DEBUG_TYPE_MARKER:
1561 typeStr = "TYPE_MARKER"_ns;
1562 break;
1563 default:
1564 typeStr = nsPrintfCString("<type 0x%04x>", type);
1565 break;
1568 nsAutoCString sevStr;
1569 switch (severity) {
1570 case LOCAL_GL_DEBUG_SEVERITY_HIGH:
1571 sevStr = "SEVERITY_HIGH"_ns;
1572 break;
1573 case LOCAL_GL_DEBUG_SEVERITY_MEDIUM:
1574 sevStr = "SEVERITY_MEDIUM"_ns;
1575 break;
1576 case LOCAL_GL_DEBUG_SEVERITY_LOW:
1577 sevStr = "SEVERITY_LOW"_ns;
1578 break;
1579 case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION:
1580 sevStr = "SEVERITY_NOTIFICATION"_ns;
1581 break;
1582 default:
1583 sevStr = nsPrintfCString("<severity 0x%04x>", severity);
1584 break;
1587 printf_stderr("[KHR_debug: 0x%" PRIxPTR "] ID %u: %s, %s, %s:\n %s\n",
1588 (uintptr_t)this, id, sourceStr.BeginReading(),
1589 typeStr.BeginReading(), sevStr.BeginReading(), message);
1592 void GLContext::InitExtensions() {
1593 MOZ_GL_ASSERT(this, IsCurrent());
1595 std::vector<nsCString> driverExtensionList;
1597 [&]() {
1598 if (mSymbols.fGetStringi) {
1599 GLuint count = 0;
1600 if (GetPotentialInteger(LOCAL_GL_NUM_EXTENSIONS, (GLint*)&count)) {
1601 for (GLuint i = 0; i < count; i++) {
1602 // This is UTF-8.
1603 const char* rawExt = (const char*)fGetStringi(LOCAL_GL_EXTENSIONS, i);
1605 // We CANNOT use nsDependentCString here, because the spec doesn't
1606 // guarantee that the pointers returned are different, only that their
1607 // contents are. On Flame, each of these index string queries returns
1608 // the same address.
1609 driverExtensionList.push_back(nsCString(rawExt));
1611 return;
1615 const char* rawExts = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
1616 if (rawExts) {
1617 nsDependentCString exts(rawExts);
1618 SplitByChar(exts, ' ', &driverExtensionList);
1620 }();
1621 const auto err = fGetError();
1622 MOZ_ALWAYS_TRUE(!IsBadCallError(err));
1624 const bool shouldDumpExts = ShouldDumpExts();
1625 if (shouldDumpExts) {
1626 printf_stderr("%i GL driver extensions: (*: recognized)\n",
1627 (uint32_t)driverExtensionList.size());
1630 MarkBitfieldByStrings(driverExtensionList, shouldDumpExts, sExtensionNames,
1631 &mAvailableExtensions);
1633 if (WorkAroundDriverBugs()) {
1634 if (Vendor() == GLVendor::Qualcomm) {
1635 // Some Adreno drivers do not report GL_OES_EGL_sync, but they really do
1636 // support it.
1637 MarkExtensionSupported(OES_EGL_sync);
1640 if (Vendor() == GLVendor::ATI) {
1641 // ATI drivers say this extension exists, but we can't
1642 // actually find the EGLImageTargetRenderbufferStorageOES
1643 // extension function pointer in the drivers.
1644 MarkExtensionUnsupported(OES_EGL_image);
1647 if (Vendor() == GLVendor::Imagination && Renderer() == GLRenderer::SGX540) {
1648 // Bug 980048
1649 MarkExtensionUnsupported(OES_EGL_sync);
1652 if (Vendor() == GLVendor::ARM && (Renderer() == GLRenderer::Mali400MP ||
1653 Renderer() == GLRenderer::Mali450MP)) {
1654 // Bug 1264505
1655 MarkExtensionUnsupported(OES_EGL_image_external);
1658 if (Renderer() == GLRenderer::AndroidEmulator) {
1659 // the Android emulator, which we use to run B2G reftests on,
1660 // doesn't expose the OES_rgb8_rgba8 extension, but it seems to
1661 // support it (tautologically, as it only runs on desktop GL).
1662 MarkExtensionSupported(OES_rgb8_rgba8);
1665 if (Vendor() == GLVendor::VMware &&
1666 Renderer() == GLRenderer::GalliumLlvmpipe) {
1667 // The llvmpipe driver that is used on linux try servers appears to have
1668 // buggy support for s3tc/dxt1 compressed textures.
1669 // See Bug 975824.
1670 MarkExtensionUnsupported(EXT_texture_compression_s3tc);
1671 MarkExtensionUnsupported(EXT_texture_compression_dxt1);
1672 MarkExtensionUnsupported(ANGLE_texture_compression_dxt3);
1673 MarkExtensionUnsupported(ANGLE_texture_compression_dxt5);
1676 #ifdef XP_MACOSX
1677 // Bug 1009642: On OSX Mavericks (10.9), the driver for Intel HD
1678 // 3000 appears to be buggy WRT updating sub-images of S3TC
1679 // textures with glCompressedTexSubImage2D. Works on Intel HD 4000
1680 // and Intel HD 5000/Iris that I tested.
1681 // Bug 1124996: Appears to be the same on OSX Yosemite (10.10)
1682 if (Renderer() == GLRenderer::IntelHD3000) {
1683 MarkExtensionUnsupported(EXT_texture_compression_s3tc);
1686 // OSX supports EXT_texture_sRGB in Legacy contexts, but not in Core
1687 // contexts. Though EXT_texture_sRGB was included into GL2.1, it *excludes*
1688 // the interactions with s3tc. Strictly speaking, you must advertize support
1689 // for EXT_texture_sRGB in order to allow for srgb+s3tc on desktop GL. The
1690 // omission of EXT_texture_sRGB in OSX Core contexts appears to be a bug.
1691 MarkExtensionSupported(EXT_texture_sRGB);
1692 #endif
1695 if (shouldDumpExts) {
1696 printf_stderr("\nActivated extensions:\n");
1698 for (size_t i = 0; i < mAvailableExtensions.size(); i++) {
1699 if (!mAvailableExtensions[i]) continue;
1701 const char* ext = sExtensionNames[i];
1702 printf_stderr("[%i] %s\n", (uint32_t)i, ext);
1707 void GLContext::PlatformStartup() {
1708 RegisterStrongMemoryReporter(new GfxTexturesReporter());
1711 // Common code for checking for both GL extensions and GLX extensions.
1712 bool GLContext::ListHasExtension(const GLubyte* extensions,
1713 const char* extension) {
1714 // fix bug 612572 - we were crashing as we were calling this function with
1715 // extensions==null
1716 if (extensions == nullptr || extension == nullptr) return false;
1718 const GLubyte* start;
1719 GLubyte* where;
1720 GLubyte* terminator;
1722 /* Extension names should not have spaces. */
1723 where = (GLubyte*)strchr(extension, ' ');
1724 if (where || *extension == '\0') return false;
1727 * It takes a bit of care to be fool-proof about parsing the
1728 * OpenGL extensions string. Don't be fooled by sub-strings,
1729 * etc.
1731 start = extensions;
1732 for (;;) {
1733 where = (GLubyte*)strstr((const char*)start, extension);
1734 if (!where) {
1735 break;
1737 terminator = where + strlen(extension);
1738 if (where == start || *(where - 1) == ' ') {
1739 if (*terminator == ' ' || *terminator == '\0') {
1740 return true;
1743 start = terminator;
1745 return false;
1748 bool GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus) {
1749 MOZ_ASSERT(fb);
1751 ScopedBindFramebuffer autoFB(this, fb);
1752 MOZ_GL_ASSERT(this, fIsFramebuffer(fb));
1754 GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
1755 if (pStatus) *pStatus = status;
1757 return status == LOCAL_GL_FRAMEBUFFER_COMPLETE;
1760 void GLContext::AttachBuffersToFB(GLuint colorTex, GLuint colorRB,
1761 GLuint depthRB, GLuint stencilRB, GLuint fb,
1762 GLenum target) {
1763 MOZ_ASSERT(fb);
1764 MOZ_ASSERT(!(colorTex && colorRB));
1766 ScopedBindFramebuffer autoFB(this, fb);
1767 MOZ_GL_ASSERT(this, fIsFramebuffer(fb)); // It only counts after being bound.
1769 if (colorTex) {
1770 MOZ_GL_ASSERT(this, fIsTexture(colorTex));
1771 MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
1772 target == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
1773 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1774 target, colorTex, 0);
1775 } else if (colorRB) {
1776 // On the Android 4.3 emulator, IsRenderbuffer may return false incorrectly.
1777 MOZ_GL_ASSERT(this, fIsRenderbuffer(colorRB) ||
1778 Renderer() == GLRenderer::AndroidEmulator);
1779 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1780 LOCAL_GL_RENDERBUFFER, colorRB);
1783 if (depthRB) {
1784 MOZ_GL_ASSERT(this, fIsRenderbuffer(depthRB) ||
1785 Renderer() == GLRenderer::AndroidEmulator);
1786 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
1787 LOCAL_GL_RENDERBUFFER, depthRB);
1790 if (stencilRB) {
1791 MOZ_GL_ASSERT(this, fIsRenderbuffer(stencilRB) ||
1792 Renderer() == GLRenderer::AndroidEmulator);
1793 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
1794 LOCAL_GL_RENDERBUFFER, stencilRB);
1798 bool GLContext::AssembleOffscreenFBs(const GLuint colorMSRB,
1799 const GLuint depthRB,
1800 const GLuint stencilRB,
1801 const GLuint texture, GLuint* drawFB_out,
1802 GLuint* readFB_out) {
1803 if (!colorMSRB && !texture) {
1804 MOZ_ASSERT(!depthRB && !stencilRB);
1806 if (drawFB_out) *drawFB_out = 0;
1807 if (readFB_out) *readFB_out = 0;
1809 return true;
1812 ScopedBindFramebuffer autoFB(this);
1814 GLuint drawFB = 0;
1815 GLuint readFB = 0;
1817 if (texture) {
1818 readFB = 0;
1819 fGenFramebuffers(1, &readFB);
1820 BindFB(readFB);
1821 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1822 LOCAL_GL_TEXTURE_2D, texture, 0);
1825 if (colorMSRB) {
1826 drawFB = 0;
1827 fGenFramebuffers(1, &drawFB);
1828 BindFB(drawFB);
1829 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1830 LOCAL_GL_RENDERBUFFER, colorMSRB);
1831 } else {
1832 drawFB = readFB;
1834 MOZ_ASSERT(GetIntAs<GLuint>(LOCAL_GL_FRAMEBUFFER_BINDING) == drawFB);
1836 if (depthRB) {
1837 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
1838 LOCAL_GL_RENDERBUFFER, depthRB);
1841 if (stencilRB) {
1842 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
1843 LOCAL_GL_RENDERBUFFER, stencilRB);
1846 // We should be all resized. Check for framebuffer completeness.
1847 GLenum status;
1848 bool isComplete = true;
1850 if (!IsFramebufferComplete(drawFB, &status)) {
1851 NS_WARNING("DrawFBO: Incomplete");
1852 #ifdef MOZ_GL_DEBUG_BUILD
1853 if (ShouldSpew()) {
1854 printf_stderr("Framebuffer status: %X\n", status);
1856 #endif
1857 isComplete = false;
1860 if (!IsFramebufferComplete(readFB, &status)) {
1861 NS_WARNING("ReadFBO: Incomplete");
1862 #ifdef MOZ_GL_DEBUG_BUILD
1863 if (ShouldSpew()) {
1864 printf_stderr("Framebuffer status: %X\n", status);
1866 #endif
1867 isComplete = false;
1870 if (drawFB_out) {
1871 *drawFB_out = drawFB;
1872 } else if (drawFB) {
1873 MOZ_CRASH("drawFB created when not requested!");
1876 if (readFB_out) {
1877 *readFB_out = readFB;
1878 } else if (readFB) {
1879 MOZ_CRASH("readFB created when not requested!");
1882 return isComplete;
1885 void GLContext::MarkDestroyed() {
1886 if (IsDestroyed()) return;
1888 OnMarkDestroyed();
1890 // Null these before they're naturally nulled after dtor, as we want GLContext
1891 // to still be alive in *their* dtors.
1892 mBlitHelper = nullptr;
1893 mReadTexImageHelper = nullptr;
1895 mContextLost = true;
1896 mSymbols = {};
1899 // -
1901 #ifdef MOZ_GL_DEBUG_BUILD
1902 /* static */
1903 void GLContext::AssertNotPassingStackBufferToTheGL(const void* ptr) {
1904 int somethingOnTheStack;
1905 const void* someStackPtr = &somethingOnTheStack;
1906 const int page_bits = 12;
1907 intptr_t page = reinterpret_cast<uintptr_t>(ptr) >> page_bits;
1908 intptr_t someStackPage =
1909 reinterpret_cast<uintptr_t>(someStackPtr) >> page_bits;
1910 uintptr_t pageDistance = std::abs(page - someStackPage);
1912 // Explanation for the "distance <= 1" check here as opposed to just
1913 // an equality check.
1915 // Here we assume that pages immediately adjacent to the someStackAddress
1916 // page, are also stack pages. That allows to catch the case where the calling
1917 // frame put a buffer on the stack, and we just crossed the page boundary.
1918 // That is likely to happen, precisely, when using stack arrays. I hit that
1919 // specifically with CompositorOGL::Initialize.
1921 // In theory we could be unlucky and wrongly assert here. If that happens,
1922 // it will only affect debug builds, and looking at stacks we'll be able to
1923 // see that this assert is wrong and revert to the conservative and safe
1924 // approach of only asserting when address and someStackAddress are
1925 // on the same page.
1926 bool isStackAddress = pageDistance <= 1;
1927 MOZ_ASSERT(!isStackAddress,
1928 "Please don't pass stack arrays to the GL. "
1929 "Consider using HeapCopyOfStackArray. "
1930 "See bug 1005658.");
1933 void GLContext::CreatedProgram(GLContext* aOrigin, GLuint aName) {
1934 mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName));
1937 void GLContext::CreatedShader(GLContext* aOrigin, GLuint aName) {
1938 mTrackedShaders.AppendElement(NamedResource(aOrigin, aName));
1941 void GLContext::CreatedBuffers(GLContext* aOrigin, GLsizei aCount,
1942 GLuint* aNames) {
1943 for (GLsizei i = 0; i < aCount; ++i) {
1944 mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1948 void GLContext::CreatedQueries(GLContext* aOrigin, GLsizei aCount,
1949 GLuint* aNames) {
1950 for (GLsizei i = 0; i < aCount; ++i) {
1951 mTrackedQueries.AppendElement(NamedResource(aOrigin, aNames[i]));
1955 void GLContext::CreatedTextures(GLContext* aOrigin, GLsizei aCount,
1956 GLuint* aNames) {
1957 for (GLsizei i = 0; i < aCount; ++i) {
1958 mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i]));
1962 void GLContext::CreatedFramebuffers(GLContext* aOrigin, GLsizei aCount,
1963 GLuint* aNames) {
1964 for (GLsizei i = 0; i < aCount; ++i) {
1965 mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1969 void GLContext::CreatedRenderbuffers(GLContext* aOrigin, GLsizei aCount,
1970 GLuint* aNames) {
1971 for (GLsizei i = 0; i < aCount; ++i) {
1972 mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1976 static void RemoveNamesFromArray(GLContext* aOrigin, GLsizei aCount,
1977 const GLuint* aNames,
1978 nsTArray<GLContext::NamedResource>& aArray) {
1979 for (GLsizei j = 0; j < aCount; ++j) {
1980 GLuint name = aNames[j];
1981 // name 0 can be ignored
1982 if (name == 0) continue;
1984 for (uint32_t i = 0; i < aArray.Length(); ++i) {
1985 if (aArray[i].name == name) {
1986 aArray.RemoveElementAt(i);
1987 break;
1993 void GLContext::DeletedProgram(GLContext* aOrigin, GLuint aName) {
1994 RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms);
1997 void GLContext::DeletedShader(GLContext* aOrigin, GLuint aName) {
1998 RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders);
2001 void GLContext::DeletedBuffers(GLContext* aOrigin, GLsizei aCount,
2002 const GLuint* aNames) {
2003 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers);
2006 void GLContext::DeletedQueries(GLContext* aOrigin, GLsizei aCount,
2007 const GLuint* aNames) {
2008 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedQueries);
2011 void GLContext::DeletedTextures(GLContext* aOrigin, GLsizei aCount,
2012 const GLuint* aNames) {
2013 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures);
2016 void GLContext::DeletedFramebuffers(GLContext* aOrigin, GLsizei aCount,
2017 const GLuint* aNames) {
2018 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers);
2021 void GLContext::DeletedRenderbuffers(GLContext* aOrigin, GLsizei aCount,
2022 const GLuint* aNames) {
2023 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers);
2026 static void MarkContextDestroyedInArray(
2027 GLContext* aContext, nsTArray<GLContext::NamedResource>& aArray) {
2028 for (uint32_t i = 0; i < aArray.Length(); ++i) {
2029 if (aArray[i].origin == aContext) aArray[i].originDeleted = true;
2033 void GLContext::SharedContextDestroyed(GLContext* aChild) {
2034 MarkContextDestroyedInArray(aChild, mTrackedPrograms);
2035 MarkContextDestroyedInArray(aChild, mTrackedShaders);
2036 MarkContextDestroyedInArray(aChild, mTrackedTextures);
2037 MarkContextDestroyedInArray(aChild, mTrackedFramebuffers);
2038 MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers);
2039 MarkContextDestroyedInArray(aChild, mTrackedBuffers);
2040 MarkContextDestroyedInArray(aChild, mTrackedQueries);
2043 static void ReportArrayContents(
2044 const char* title, const nsTArray<GLContext::NamedResource>& aArray) {
2045 if (aArray.Length() == 0) return;
2047 printf_stderr("%s:\n", title);
2049 nsTArray<GLContext::NamedResource> copy(aArray.Clone());
2050 copy.Sort();
2052 // Accumulate the output in a buffer to avoid interleaved output.
2053 nsCString line;
2055 GLContext* lastContext = nullptr;
2056 for (uint32_t i = 0; i < copy.Length(); ++i) {
2057 if (lastContext != copy[i].origin) {
2058 if (lastContext) {
2059 printf_stderr("%s\n", line.BeginReading());
2060 line.Assign("");
2062 line.Append(nsPrintfCString(" [%p - %s] ", copy[i].origin,
2063 copy[i].originDeleted ? "deleted" : "live"));
2064 lastContext = copy[i].origin;
2066 line.AppendInt(copy[i].name);
2067 line.Append(' ');
2069 printf_stderr("%s\n", line.BeginReading());
2072 void GLContext::ReportOutstandingNames() {
2073 if (!ShouldSpew()) return;
2075 printf_stderr("== GLContext %p Outstanding ==\n", this);
2077 ReportArrayContents("Outstanding Textures", mTrackedTextures);
2078 ReportArrayContents("Outstanding Buffers", mTrackedBuffers);
2079 ReportArrayContents("Outstanding Queries", mTrackedQueries);
2080 ReportArrayContents("Outstanding Programs", mTrackedPrograms);
2081 ReportArrayContents("Outstanding Shaders", mTrackedShaders);
2082 ReportArrayContents("Outstanding Framebuffers", mTrackedFramebuffers);
2083 ReportArrayContents("Outstanding Renderbuffers", mTrackedRenderbuffers);
2086 #endif // ifdef MOZ_GL_DEBUG_BUILD
2088 bool GLContext::IsOffscreenSizeAllowed(const IntSize& aSize) const {
2089 int32_t biggerDimension = std::max(aSize.width, aSize.height);
2090 int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize);
2091 return biggerDimension <= maxAllowed;
2094 bool GLContext::IsValidOwningThread() const {
2095 if (!mOwningThreadId) return true; // Free for all!
2096 return PlatformThread::CurrentId() == *mOwningThreadId;
2099 GLBlitHelper* GLContext::BlitHelper() {
2100 if (!mBlitHelper) {
2101 mBlitHelper.reset(new GLBlitHelper(this));
2104 return mBlitHelper.get();
2107 GLReadTexImageHelper* GLContext::ReadTexImageHelper() {
2108 if (!mReadTexImageHelper) {
2109 mReadTexImageHelper = MakeUnique<GLReadTexImageHelper>(this);
2112 return mReadTexImageHelper.get();
2115 void GLContext::FlushIfHeavyGLCallsSinceLastFlush() {
2116 if (!mHeavyGLCallsSinceLastFlush) {
2117 return;
2119 if (MakeCurrent()) {
2120 fFlush();
2124 /*static*/
2125 bool GLContext::ShouldDumpExts() { return gfxEnv::MOZ_GL_DUMP_EXTS(); }
2127 bool DoesStringMatch(const char* aString, const char* aWantedString) {
2128 if (!aString || !aWantedString) return false;
2130 const char* occurrence = strstr(aString, aWantedString);
2132 // aWanted not found
2133 if (!occurrence) return false;
2135 // aWantedString preceded by alpha character
2136 if (occurrence != aString && isalpha(*(occurrence - 1))) return false;
2138 // aWantedVendor followed by alpha character
2139 const char* afterOccurrence = occurrence + strlen(aWantedString);
2140 if (isalpha(*afterOccurrence)) return false;
2142 return true;
2145 /*static*/
2146 bool GLContext::ShouldSpew() { return gfxEnv::MOZ_GL_SPEW(); }
2148 void SplitByChar(const nsACString& str, const char delim,
2149 std::vector<nsCString>* const out) {
2150 uint32_t start = 0;
2151 while (true) {
2152 int32_t end = str.FindChar(' ', start);
2153 if (end == -1) break;
2155 uint32_t len = (uint32_t)end - start;
2156 nsDependentCSubstring substr(str, start, len);
2157 out->push_back(nsCString(substr));
2159 start = end + 1;
2162 nsDependentCSubstring substr(str, start);
2163 out->push_back(nsCString(substr));
2166 void GLContext::fCopyTexImage2D(GLenum target, GLint level,
2167 GLenum internalformat, GLint x, GLint y,
2168 GLsizei width, GLsizei height, GLint border) {
2169 if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
2170 // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2171 // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2172 level = -1;
2173 width = -1;
2174 height = -1;
2175 border = -1;
2178 BeforeGLReadCall();
2179 raw_fCopyTexImage2D(target, level, internalformat, x, y, width, height,
2180 border);
2181 AfterGLReadCall();
2184 void GLContext::fGetIntegerv(const GLenum pname, GLint* const params) const {
2185 const auto AssertBinding = [&](const char* const name, const GLenum binding,
2186 const GLuint expected) {
2187 if (MOZ_LIKELY(!mDebugFlags)) return;
2188 GLuint actual = 0;
2189 raw_fGetIntegerv(binding, (GLint*)&actual);
2190 if (actual != expected) {
2191 gfxCriticalError() << "Misprediction: " << name << " expected "
2192 << expected << ", was " << actual;
2196 switch (pname) {
2197 case LOCAL_GL_MAX_TEXTURE_SIZE:
2198 MOZ_ASSERT(mMaxTextureSize > 0);
2199 *params = mMaxTextureSize;
2200 return;
2202 case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
2203 MOZ_ASSERT(mMaxCubeMapTextureSize > 0);
2204 *params = mMaxCubeMapTextureSize;
2205 return;
2207 case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
2208 MOZ_ASSERT(mMaxRenderbufferSize > 0);
2209 *params = mMaxRenderbufferSize;
2210 return;
2212 case LOCAL_GL_VIEWPORT:
2213 for (size_t i = 0; i < 4; i++) {
2214 params[i] = mViewportRect[i];
2216 return;
2218 case LOCAL_GL_SCISSOR_BOX:
2219 for (size_t i = 0; i < 4; i++) {
2220 params[i] = mScissorRect[i];
2222 return;
2224 case LOCAL_GL_DRAW_FRAMEBUFFER_BINDING:
2225 if (mElideDuplicateBindFramebuffers) {
2226 static_assert(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING ==
2227 LOCAL_GL_FRAMEBUFFER_BINDING);
2228 AssertBinding("GL_DRAW_FRAMEBUFFER_BINDING",
2229 LOCAL_GL_DRAW_FRAMEBUFFER_BINDING, mCachedDrawFb);
2230 *params = static_cast<GLint>(mCachedDrawFb);
2231 return;
2233 break;
2235 case LOCAL_GL_READ_FRAMEBUFFER_BINDING:
2236 if (mElideDuplicateBindFramebuffers) {
2237 if (IsSupported(GLFeature::framebuffer_blit)) {
2238 AssertBinding("GL_READ_FRAMEBUFFER_BINDING",
2239 LOCAL_GL_READ_FRAMEBUFFER_BINDING, mCachedReadFb);
2241 *params = static_cast<GLint>(mCachedReadFb);
2242 return;
2244 break;
2246 default:
2247 break;
2249 raw_fGetIntegerv(pname, params);
2252 void GLContext::fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
2253 GLenum format, GLenum type, GLvoid* pixels) {
2254 BeforeGLReadCall();
2255 raw_fReadPixels(x, y, width, height, format, type, pixels);
2256 AfterGLReadCall();
2258 // Check if GL is giving back 1.0 alpha for
2259 // RGBA reads to RGBA images from no-alpha buffers.
2260 #ifdef XP_MACOSX
2261 if (WorkAroundDriverBugs() && Vendor() == gl::GLVendor::NVIDIA &&
2262 format == LOCAL_GL_RGBA && type == LOCAL_GL_UNSIGNED_BYTE &&
2263 !IsCoreProfile() && width && height) {
2264 GLint alphaBits = 0;
2265 fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits);
2266 if (!alphaBits) {
2267 const uint32_t alphaMask = 0xff000000;
2269 uint32_t* itr = (uint32_t*)pixels;
2270 uint32_t testPixel = *itr;
2271 if ((testPixel & alphaMask) != alphaMask) {
2272 // We need to set the alpha channel to 1.0 manually.
2273 uint32_t* itrEnd =
2274 itr + width * height; // Stride is guaranteed to be width*4.
2276 for (; itr != itrEnd; itr++) {
2277 *itr |= alphaMask;
2282 #endif
2285 void GLContext::fDeleteFramebuffers(GLsizei n, const GLuint* names) {
2286 // Avoid crash by flushing before glDeleteFramebuffers. See bug 1194923.
2287 if (mNeedsFlushBeforeDeleteFB) {
2288 fFlush();
2291 if (n == 1 && *names == 0) {
2292 // Deleting framebuffer 0 causes hangs on the DROID. See bug 623228.
2293 } else {
2294 raw_fDeleteFramebuffers(n, names);
2296 TRACKING_CONTEXT(DeletedFramebuffers(this, n, names));
2299 #ifdef MOZ_WIDGET_ANDROID
2301 * Conservatively estimate whether there is enough available
2302 * contiguous virtual address space to map a newly allocated texture.
2304 static bool WillTextureMapSucceed(GLsizei width, GLsizei height, GLenum format,
2305 GLenum type) {
2306 bool willSucceed = false;
2307 // Some drivers leave large gaps between textures, so require
2308 // there to be double the actual size of the texture available.
2309 size_t size = width * height * GetBytesPerTexel(format, type) * 2;
2311 void* p = mmap(nullptr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
2312 if (p != MAP_FAILED) {
2313 willSucceed = true;
2314 munmap(p, size);
2317 return willSucceed;
2319 #endif // MOZ_WIDGET_ANDROID
2321 void GLContext::fTexImage2D(GLenum target, GLint level, GLint internalformat,
2322 GLsizei width, GLsizei height, GLint border,
2323 GLenum format, GLenum type, const GLvoid* pixels) {
2324 if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
2325 // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2326 // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2327 level = -1;
2328 width = -1;
2329 height = -1;
2330 border = -1;
2332 #if MOZ_WIDGET_ANDROID
2333 if (mTextureAllocCrashesOnMapFailure) {
2334 // We have no way of knowing whether this texture already has
2335 // storage allocated for it, and therefore whether this check
2336 // is necessary. We must therefore assume it does not and
2337 // always perform the check.
2338 if (!WillTextureMapSucceed(width, height, internalformat, type)) {
2339 return;
2342 #endif
2343 raw_fTexImage2D(target, level, internalformat, width, height, border, format,
2344 type, pixels);
2347 UniquePtr<Texture> CreateTexture(GLContext& gl, const gfx::IntSize& size) {
2348 const GLenum target = LOCAL_GL_TEXTURE_2D;
2349 const GLenum format = LOCAL_GL_RGBA;
2351 auto tex = MakeUnique<Texture>(gl);
2352 ScopedBindTexture autoTex(&gl, tex->name, target);
2354 gl.fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
2355 gl.fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
2356 gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
2357 gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
2359 gl.fTexImage2D(target, 0, format, size.width, size.height, 0, format,
2360 LOCAL_GL_UNSIGNED_BYTE, nullptr);
2362 return tex;
2365 uint32_t GetBytesPerTexel(GLenum format, GLenum type) {
2366 // If there is no defined format or type, we're not taking up any memory
2367 if (!format || !type) {
2368 return 0;
2371 if (format == LOCAL_GL_DEPTH_COMPONENT) {
2372 if (type == LOCAL_GL_UNSIGNED_SHORT)
2373 return 2;
2374 else if (type == LOCAL_GL_UNSIGNED_INT)
2375 return 4;
2376 } else if (format == LOCAL_GL_DEPTH_STENCIL) {
2377 if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT) return 4;
2380 if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT ||
2381 type == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV) {
2382 uint32_t multiplier = type == LOCAL_GL_UNSIGNED_BYTE ? 1 : 4;
2383 switch (format) {
2384 case LOCAL_GL_ALPHA:
2385 case LOCAL_GL_LUMINANCE:
2386 case LOCAL_GL_R8:
2387 return 1 * multiplier;
2388 case LOCAL_GL_LUMINANCE_ALPHA:
2389 case LOCAL_GL_R16:
2390 return 2 * multiplier;
2391 case LOCAL_GL_RGB:
2392 return 3 * multiplier;
2393 case LOCAL_GL_RGBA:
2394 case LOCAL_GL_BGRA_EXT:
2395 return 4 * multiplier;
2396 default:
2397 break;
2399 } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
2400 type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
2401 type == LOCAL_GL_UNSIGNED_SHORT_5_6_5 ||
2402 type == LOCAL_GL_UNSIGNED_SHORT) {
2403 return 2;
2406 gfxCriticalError() << "Unknown texture type " << type << " or format "
2407 << format;
2408 return 0;
2411 void GLContext::ResetTLSCurrentContext() {
2412 if (sCurrentContext.init()) {
2413 sCurrentContext.set(nullptr);
2417 bool GLContext::MakeCurrent(bool aForce) const {
2418 if (MOZ_UNLIKELY(IsContextLost())) return false;
2420 if (MOZ_LIKELY(!aForce)) {
2421 bool isCurrent;
2422 if (mUseTLSIsCurrent && sCurrentContext.init()) {
2423 isCurrent = (sCurrentContext.get() == this);
2424 } else {
2425 isCurrent = IsCurrentImpl();
2427 if (MOZ_LIKELY(isCurrent)) {
2428 MOZ_ASSERT(IsCurrentImpl() ||
2429 MakeCurrentImpl()); // Might have lost context.
2430 return true;
2433 if (!IsValidOwningThread()) {
2434 gfxCriticalError() << "MakeCurrent called on a thread other than the"
2435 << " creating thread!";
2436 if (gfxEnv::MOZ_GL_RELEASE_ASSERT_CONTEXT_OWNERSHIP()) {
2437 MOZ_CRASH("MOZ_GL_RELEASE_ASSERT_CONTEXT_OWNERSHIP");
2440 if (!MakeCurrentImpl()) return false;
2442 if (sCurrentContext.init()) {
2443 sCurrentContext.set(this);
2445 return true;
2448 void GLContext::ResetSyncCallCount(const char* resetReason) const {
2449 if (ShouldSpew()) {
2450 printf_stderr("On %s, mSyncGLCallCount = %" PRIu64 "\n", resetReason,
2451 mSyncGLCallCount);
2454 mSyncGLCallCount = 0;
2457 // -
2459 bool CheckContextLost(const GLContext* const gl) {
2460 return gl->CheckContextLost();
2463 // -
2465 GLenum GLContext::GetError() const {
2466 if (mContextLost) return LOCAL_GL_CONTEXT_LOST;
2468 if (mImplicitMakeCurrent) {
2469 (void)MakeCurrent();
2472 const auto fnGetError = [&]() {
2473 const auto ret = mSymbols.fGetError();
2474 if (ret == LOCAL_GL_CONTEXT_LOST) {
2475 OnContextLostError();
2476 mTopError = ret; // Promote to top!
2478 return ret;
2481 auto ret = fnGetError();
2484 auto flushedErr = ret;
2485 uint32_t i = 1;
2486 while (flushedErr && !mContextLost) {
2487 if (i == 100) {
2488 gfxCriticalError() << "Flushing glGetError still "
2489 << gfx::hexa(flushedErr) << " after " << i
2490 << " calls.";
2491 break;
2493 flushedErr = fnGetError();
2494 i += 1;
2498 if (mTopError) {
2499 ret = mTopError;
2500 mTopError = 0;
2503 if (mDebugFlags & DebugFlagTrace) {
2504 const auto errStr = GLErrorToString(ret);
2505 printf_stderr("[gl:%p] GetError() -> %s\n", this, errStr.c_str());
2507 return ret;
2510 GLenum GLContext::fGetGraphicsResetStatus() const {
2511 OnSyncCall();
2513 GLenum ret = 0;
2514 if (mSymbols.fGetGraphicsResetStatus) {
2515 if (mImplicitMakeCurrent) {
2516 (void)MakeCurrent();
2518 ret = mSymbols.fGetGraphicsResetStatus();
2519 } else {
2520 if (!MakeCurrent(true)) {
2521 ret = LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB;
2525 if (mDebugFlags & DebugFlagTrace) {
2526 printf_stderr("[gl:%p] GetGraphicsResetStatus() -> 0x%04x\n", this, ret);
2529 return ret;
2532 void GLContext::OnContextLostError() const {
2533 if (mDebugFlags & DebugFlagTrace) {
2534 printf_stderr("[gl:%p] CONTEXT_LOST\n", this);
2536 mContextLost = true;
2539 // --
2541 /*static*/ std::string GLContext::GLErrorToString(const GLenum err) {
2542 switch (err) {
2543 case LOCAL_GL_NO_ERROR:
2544 return "GL_NO_ERROR";
2545 case LOCAL_GL_INVALID_ENUM:
2546 return "GL_INVALID_ENUM";
2547 case LOCAL_GL_INVALID_VALUE:
2548 return "GL_INVALID_VALUE";
2549 case LOCAL_GL_INVALID_OPERATION:
2550 return "GL_INVALID_OPERATION";
2551 case LOCAL_GL_STACK_OVERFLOW:
2552 return "GL_STACK_OVERFLOW";
2553 case LOCAL_GL_STACK_UNDERFLOW:
2554 return "GL_STACK_UNDERFLOW";
2555 case LOCAL_GL_OUT_OF_MEMORY:
2556 return "GL_OUT_OF_MEMORY";
2557 case LOCAL_GL_TABLE_TOO_LARGE:
2558 return "GL_TABLE_TOO_LARGE";
2559 case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
2560 return "GL_INVALID_FRAMEBUFFER_OPERATION";
2561 case LOCAL_GL_CONTEXT_LOST:
2562 return "GL_CONTEXT_LOST";
2565 const nsPrintfCString hex("<enum 0x%04x>", err);
2566 return hex.BeginReading();
2569 // --
2571 void GLContext::BeforeGLCall_Debug(const char* const funcName) const {
2572 MOZ_ASSERT(mDebugFlags);
2574 if (mDebugFlags & DebugFlagTrace) {
2575 printf_stderr("[gl:%p] > %s\n", this, funcName);
2578 MOZ_ASSERT(!mDebugErrorScope);
2579 mDebugErrorScope.reset(new LocalErrorScope(*this));
2582 void GLContext::AfterGLCall_Debug(const char* const funcName) const {
2583 MOZ_ASSERT(mDebugFlags);
2585 // calling fFinish() immediately after every GL call makes sure that if this
2586 // GL command crashes, the stack trace will actually point to it. Otherwise,
2587 // OpenGL being an asynchronous API, stack traces tend to be meaningless
2588 mSymbols.fFinish();
2590 const auto err = mDebugErrorScope->GetError();
2591 mDebugErrorScope = nullptr;
2592 if (!mTopError) {
2593 mTopError = err;
2596 if (mDebugFlags & DebugFlagTrace) {
2597 printf_stderr("[gl:%p] < %s [%s]\n", this, funcName,
2598 GLErrorToString(err).c_str());
2601 if (err && !mLocalErrorScopeStack.size()) {
2602 const auto errStr = GLErrorToString(err);
2603 const auto text = nsPrintfCString("%s: Generated unexpected %s error",
2604 funcName, errStr.c_str());
2605 printf_stderr("[gl:%p] %s.\n", this, text.BeginReading());
2607 const bool abortOnError = mDebugFlags & DebugFlagAbortOnError;
2608 if (abortOnError && err != LOCAL_GL_CONTEXT_LOST) {
2609 gfxCriticalErrorOnce() << text.BeginReading();
2610 MOZ_CRASH(
2611 "Aborting... (Run with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)");
2616 /*static*/
2617 void GLContext::OnImplicitMakeCurrentFailure(const char* const funcName) {
2618 gfxCriticalError() << "Ignoring call to " << funcName << " with failed"
2619 << " mImplicitMakeCurrent.";
2622 bool GLContext::CreateOffscreenDefaultFb(const gfx::IntSize& size) {
2623 mOffscreenDefaultFb = MozFramebuffer::Create(this, size, 0, true);
2624 return bool(mOffscreenDefaultFb);
2627 // Some of Mesa's drivers allocate heap memory when loaded and don't
2628 // free it when unloaded; this causes Leak Sanitizer to detect leaks and
2629 // fail to unwind the stack, so suppressions don't work. This
2630 // workaround leaks a reference to the driver library so that it's never
2631 // unloaded. Because the leak isn't significant for real usage, only
2632 // ASan runs in CI, this is applied only to the software renderer.
2634 // See bug 1702394 for more details.
2635 void MesaMemoryLeakWorkaround() {
2636 #if defined(XP_LINUX) && !defined(ANDROID)
2637 Maybe<nsAutoCString> foundPath;
2639 dl_iterate_phdr(
2640 [](dl_phdr_info* info, size_t size, void* data) {
2641 auto& foundPath = *reinterpret_cast<Maybe<nsAutoCString>*>(data);
2642 nsDependentCString thisPath(info->dlpi_name);
2643 if (StringEndsWith(thisPath, "/swrast_dri.so"_ns)) {
2644 foundPath.emplace(thisPath);
2645 return 1;
2647 return 0;
2649 &foundPath);
2651 if (foundPath) {
2652 // Deliberately leak to prevent unload
2653 Unused << dlopen(foundPath->get(), RTLD_LAZY);
2655 #endif // XP_LINUX but not ANDROID
2658 } /* namespace gl */
2659 } /* namespace mozilla */