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