Bug 1800456 - Add failIfNot function to reftest-wait.js, r=emilio
[gecko.git] / gfx / gl / GLContext.cpp
blobdaf6a5d2aa7a6cf3dc582c35240dc871a30b5213
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_BUILD
248 if (gfxEnv::MOZ_GL_DEBUG()) {
249 debugFlags |= GLContext::DebugFlagEnabled;
252 // Enables extra verbose output, informing of the start and finish of every GL
253 // call. Useful e.g. to record information to investigate graphics system
254 // crashes/lockups
255 if (gfxEnv::MOZ_GL_DEBUG_VERBOSE()) {
256 debugFlags |= GLContext::DebugFlagTrace;
259 // Aborts on GL error. Can be useful to debug quicker code that is known not
260 // to generate any GL error in principle.
261 bool abortOnError = false;
263 if (createFlags & CreateContextFlags::NO_VALIDATION) {
264 abortOnError = true;
266 const auto& env = gfxEnv::MOZ_GL_DEBUG_ABORT_ON_ERROR();
267 if (env.as_str == "0") {
268 abortOnError = false;
272 if (abortOnError) {
273 debugFlags |= GLContext::DebugFlagAbortOnError;
275 #endif
277 return debugFlags;
280 GLContext::GLContext(const GLContextDesc& desc, GLContext* sharedContext,
281 bool useTLSIsCurrent)
282 : mDesc(desc),
283 mUseTLSIsCurrent(ShouldUseTLSIsCurrent(useTLSIsCurrent)),
284 mDebugFlags(ChooseDebugFlags(mDesc.flags)),
285 mSharedContext(sharedContext),
286 mOwningThreadId(Some(PlatformThread::CurrentId())),
287 mWorkAroundDriverBugs(
288 StaticPrefs::gfx_work_around_driver_bugs_AtStartup()) {
289 MOZ_ALWAYS_TRUE(sCurrentContext.init());
290 sCurrentContext.set(0);
293 GLContext::~GLContext() {
294 NS_ASSERTION(
295 IsDestroyed(),
296 "GLContext implementation must call MarkDestroyed in destructor!");
297 #ifdef MOZ_GL_DEBUG_BUILD
298 if (mSharedContext) {
299 GLContext* tip = mSharedContext;
300 while (tip->mSharedContext) tip = tip->mSharedContext;
301 tip->SharedContextDestroyed(this);
302 tip->ReportOutstandingNames();
303 } else {
304 ReportOutstandingNames();
306 #endif
309 /*static*/
310 void GLContext::StaticDebugCallback(GLenum source, GLenum type, GLuint id,
311 GLenum severity, GLsizei length,
312 const GLchar* message,
313 const GLvoid* userParam) {
314 GLContext* gl = (GLContext*)userParam;
315 gl->DebugCallback(source, type, id, severity, length, message);
318 bool GLContext::Init() {
319 MOZ_RELEASE_ASSERT(!mSymbols.fBindFramebuffer,
320 "GFX: GLContext::Init should only be called once.");
322 ScopedGfxFeatureReporter reporter("GL Context");
324 if (!InitImpl()) {
325 // If initialization fails, zero the symbols to avoid hard-to-understand
326 // bugs.
327 mSymbols = {};
328 NS_WARNING("GLContext::InitWithPrefix failed!");
329 return false;
332 reporter.SetSuccessful();
333 return true;
336 static bool LoadSymbolsWithDesc(const SymbolLoader& loader,
337 const SymLoadStruct* list, const char* desc) {
338 const auto warnOnFailure = bool(desc);
339 if (loader.LoadSymbols(list, warnOnFailure)) return true;
341 ClearSymbols(list);
343 if (desc) {
344 const nsPrintfCString err("Failed to load symbols for %s.", desc);
345 NS_ERROR(err.BeginReading());
347 return false;
350 bool GLContext::LoadExtSymbols(const SymbolLoader& loader,
351 const SymLoadStruct* list, GLExtensions ext) {
352 const char* extName = sExtensionNames[size_t(ext)];
353 if (!LoadSymbolsWithDesc(loader, list, extName)) {
354 MarkExtensionUnsupported(ext);
355 return false;
357 return true;
360 bool GLContext::LoadFeatureSymbols(const SymbolLoader& loader,
361 const SymLoadStruct* list,
362 GLFeature feature) {
363 const char* featureName = GetFeatureName(feature);
364 if (!LoadSymbolsWithDesc(loader, list, featureName)) {
365 MarkUnsupported(feature);
366 return false;
368 return true;
371 bool GLContext::InitImpl() {
372 if (!MakeCurrent(true)) return false;
374 const auto loader = GetSymbolLoader();
375 if (!loader) return false;
377 const auto fnLoadSymbols = [&](const SymLoadStruct* const list,
378 const char* const desc) {
379 return LoadSymbolsWithDesc(*loader, list, desc);
382 // clang-format off
383 const SymLoadStruct coreSymbols[] = {
384 { (PRFuncPtr*) &mSymbols.fActiveTexture, {{ "glActiveTexture", "glActiveTextureARB" }} },
385 { (PRFuncPtr*) &mSymbols.fAttachShader, {{ "glAttachShader", "glAttachShaderARB" }} },
386 { (PRFuncPtr*) &mSymbols.fBindAttribLocation, {{ "glBindAttribLocation", "glBindAttribLocationARB" }} },
387 { (PRFuncPtr*) &mSymbols.fBindBuffer, {{ "glBindBuffer", "glBindBufferARB" }} },
388 { (PRFuncPtr*) &mSymbols.fBindTexture, {{ "glBindTexture", "glBindTextureARB" }} },
389 { (PRFuncPtr*) &mSymbols.fBlendColor, {{ "glBlendColor" }} },
390 { (PRFuncPtr*) &mSymbols.fBlendEquation, {{ "glBlendEquation" }} },
391 { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, {{ "glBlendEquationSeparate", "glBlendEquationSeparateEXT" }} },
392 { (PRFuncPtr*) &mSymbols.fBlendFunc, {{ "glBlendFunc" }} },
393 { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, {{ "glBlendFuncSeparate", "glBlendFuncSeparateEXT" }} },
394 { (PRFuncPtr*) &mSymbols.fBufferData, {{ "glBufferData" }} },
395 { (PRFuncPtr*) &mSymbols.fBufferSubData, {{ "glBufferSubData" }} },
396 { (PRFuncPtr*) &mSymbols.fClear, {{ "glClear" }} },
397 { (PRFuncPtr*) &mSymbols.fClearColor, {{ "glClearColor" }} },
398 { (PRFuncPtr*) &mSymbols.fClearStencil, {{ "glClearStencil" }} },
399 { (PRFuncPtr*) &mSymbols.fColorMask, {{ "glColorMask" }} },
400 { (PRFuncPtr*) &mSymbols.fCompressedTexImage2D, {{ "glCompressedTexImage2D" }} },
401 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage2D, {{ "glCompressedTexSubImage2D" }} },
402 { (PRFuncPtr*) &mSymbols.fCullFace, {{ "glCullFace" }} },
403 { (PRFuncPtr*) &mSymbols.fDetachShader, {{ "glDetachShader", "glDetachShaderARB" }} },
404 { (PRFuncPtr*) &mSymbols.fDepthFunc, {{ "glDepthFunc" }} },
405 { (PRFuncPtr*) &mSymbols.fDepthMask, {{ "glDepthMask" }} },
406 { (PRFuncPtr*) &mSymbols.fDisable, {{ "glDisable" }} },
407 { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, {{ "glDisableVertexAttribArray", "glDisableVertexAttribArrayARB" }} },
408 { (PRFuncPtr*) &mSymbols.fDrawArrays, {{ "glDrawArrays" }} },
409 { (PRFuncPtr*) &mSymbols.fDrawElements, {{ "glDrawElements" }} },
410 { (PRFuncPtr*) &mSymbols.fEnable, {{ "glEnable" }} },
411 { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, {{ "glEnableVertexAttribArray", "glEnableVertexAttribArrayARB" }} },
412 { (PRFuncPtr*) &mSymbols.fFinish, {{ "glFinish" }} },
413 { (PRFuncPtr*) &mSymbols.fFlush, {{ "glFlush" }} },
414 { (PRFuncPtr*) &mSymbols.fFrontFace, {{ "glFrontFace" }} },
415 { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, {{ "glGetActiveAttrib", "glGetActiveAttribARB" }} },
416 { (PRFuncPtr*) &mSymbols.fGetActiveUniform, {{ "glGetActiveUniform", "glGetActiveUniformARB" }} },
417 { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, {{ "glGetAttachedShaders", "glGetAttachedShadersARB" }} },
418 { (PRFuncPtr*) &mSymbols.fGetAttribLocation, {{ "glGetAttribLocation", "glGetAttribLocationARB" }} },
419 { (PRFuncPtr*) &mSymbols.fGetIntegerv, {{ "glGetIntegerv" }} },
420 { (PRFuncPtr*) &mSymbols.fGetFloatv, {{ "glGetFloatv" }} },
421 { (PRFuncPtr*) &mSymbols.fGetBooleanv, {{ "glGetBooleanv" }} },
422 { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, {{ "glGetBufferParameteriv", "glGetBufferParameterivARB" }} },
423 { (PRFuncPtr*) &mSymbols.fGetError, {{ "glGetError" }} },
424 { (PRFuncPtr*) &mSymbols.fGetProgramiv, {{ "glGetProgramiv", "glGetProgramivARB" }} },
425 { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, {{ "glGetProgramInfoLog", "glGetProgramInfoLogARB" }} },
426 { (PRFuncPtr*) &mSymbols.fTexParameteri, {{ "glTexParameteri" }} },
427 { (PRFuncPtr*) &mSymbols.fTexParameteriv, {{ "glTexParameteriv" }} },
428 { (PRFuncPtr*) &mSymbols.fTexParameterf, {{ "glTexParameterf" }} },
429 { (PRFuncPtr*) &mSymbols.fGetString, {{ "glGetString" }} },
430 { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, {{ "glGetTexParameterfv" }} },
431 { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, {{ "glGetTexParameteriv" }} },
432 { (PRFuncPtr*) &mSymbols.fGetUniformfv, {{ "glGetUniformfv", "glGetUniformfvARB" }} },
433 { (PRFuncPtr*) &mSymbols.fGetUniformiv, {{ "glGetUniformiv", "glGetUniformivARB" }} },
434 { (PRFuncPtr*) &mSymbols.fGetUniformLocation, {{ "glGetUniformLocation", "glGetUniformLocationARB" }} },
435 { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, {{ "glGetVertexAttribfv", "glGetVertexAttribfvARB" }} },
436 { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, {{ "glGetVertexAttribiv", "glGetVertexAttribivARB" }} },
437 { (PRFuncPtr*) &mSymbols.fGetVertexAttribPointerv, {{ "glGetVertexAttribPointerv" }} },
438 { (PRFuncPtr*) &mSymbols.fHint, {{ "glHint" }} },
439 { (PRFuncPtr*) &mSymbols.fIsBuffer, {{ "glIsBuffer", "glIsBufferARB" }} },
440 { (PRFuncPtr*) &mSymbols.fIsEnabled, {{ "glIsEnabled" }} },
441 { (PRFuncPtr*) &mSymbols.fIsProgram, {{ "glIsProgram", "glIsProgramARB" }} },
442 { (PRFuncPtr*) &mSymbols.fIsShader, {{ "glIsShader", "glIsShaderARB" }} },
443 { (PRFuncPtr*) &mSymbols.fIsTexture, {{ "glIsTexture", "glIsTextureARB" }} },
444 { (PRFuncPtr*) &mSymbols.fLineWidth, {{ "glLineWidth" }} },
445 { (PRFuncPtr*) &mSymbols.fLinkProgram, {{ "glLinkProgram", "glLinkProgramARB" }} },
446 { (PRFuncPtr*) &mSymbols.fPixelStorei, {{ "glPixelStorei" }} },
447 { (PRFuncPtr*) &mSymbols.fPolygonOffset, {{ "glPolygonOffset" }} },
448 { (PRFuncPtr*) &mSymbols.fReadPixels, {{ "glReadPixels" }} },
449 { (PRFuncPtr*) &mSymbols.fSampleCoverage, {{ "glSampleCoverage" }} },
450 { (PRFuncPtr*) &mSymbols.fScissor, {{ "glScissor" }} },
451 { (PRFuncPtr*) &mSymbols.fStencilFunc, {{ "glStencilFunc" }} },
452 { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, {{ "glStencilFuncSeparate", "glStencilFuncSeparateEXT" }} },
453 { (PRFuncPtr*) &mSymbols.fStencilMask, {{ "glStencilMask" }} },
454 { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, {{ "glStencilMaskSeparate", "glStencilMaskSeparateEXT" }} },
455 { (PRFuncPtr*) &mSymbols.fStencilOp, {{ "glStencilOp" }} },
456 { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, {{ "glStencilOpSeparate", "glStencilOpSeparateEXT" }} },
457 { (PRFuncPtr*) &mSymbols.fTexImage2D, {{ "glTexImage2D" }} },
458 { (PRFuncPtr*) &mSymbols.fTexSubImage2D, {{ "glTexSubImage2D" }} },
459 { (PRFuncPtr*) &mSymbols.fUniform1f, {{ "glUniform1f" }} },
460 { (PRFuncPtr*) &mSymbols.fUniform1fv, {{ "glUniform1fv" }} },
461 { (PRFuncPtr*) &mSymbols.fUniform1i, {{ "glUniform1i" }} },
462 { (PRFuncPtr*) &mSymbols.fUniform1iv, {{ "glUniform1iv" }} },
463 { (PRFuncPtr*) &mSymbols.fUniform2f, {{ "glUniform2f" }} },
464 { (PRFuncPtr*) &mSymbols.fUniform2fv, {{ "glUniform2fv" }} },
465 { (PRFuncPtr*) &mSymbols.fUniform2i, {{ "glUniform2i" }} },
466 { (PRFuncPtr*) &mSymbols.fUniform2iv, {{ "glUniform2iv" }} },
467 { (PRFuncPtr*) &mSymbols.fUniform3f, {{ "glUniform3f" }} },
468 { (PRFuncPtr*) &mSymbols.fUniform3fv, {{ "glUniform3fv" }} },
469 { (PRFuncPtr*) &mSymbols.fUniform3i, {{ "glUniform3i" }} },
470 { (PRFuncPtr*) &mSymbols.fUniform3iv, {{ "glUniform3iv" }} },
471 { (PRFuncPtr*) &mSymbols.fUniform4f, {{ "glUniform4f" }} },
472 { (PRFuncPtr*) &mSymbols.fUniform4fv, {{ "glUniform4fv" }} },
473 { (PRFuncPtr*) &mSymbols.fUniform4i, {{ "glUniform4i" }} },
474 { (PRFuncPtr*) &mSymbols.fUniform4iv, {{ "glUniform4iv" }} },
475 { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, {{ "glUniformMatrix2fv" }} },
476 { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, {{ "glUniformMatrix3fv" }} },
477 { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, {{ "glUniformMatrix4fv" }} },
478 { (PRFuncPtr*) &mSymbols.fUseProgram, {{ "glUseProgram" }} },
479 { (PRFuncPtr*) &mSymbols.fValidateProgram, {{ "glValidateProgram" }} },
480 { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, {{ "glVertexAttribPointer" }} },
481 { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, {{ "glVertexAttrib1f" }} },
482 { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, {{ "glVertexAttrib2f" }} },
483 { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, {{ "glVertexAttrib3f" }} },
484 { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, {{ "glVertexAttrib4f" }} },
485 { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, {{ "glVertexAttrib1fv" }} },
486 { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, {{ "glVertexAttrib2fv" }} },
487 { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, {{ "glVertexAttrib3fv" }} },
488 { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, {{ "glVertexAttrib4fv" }} },
489 { (PRFuncPtr*) &mSymbols.fViewport, {{ "glViewport" }} },
490 { (PRFuncPtr*) &mSymbols.fCompileShader, {{ "glCompileShader" }} },
491 { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, {{ "glCopyTexImage2D" }} },
492 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, {{ "glCopyTexSubImage2D" }} },
493 { (PRFuncPtr*) &mSymbols.fGetShaderiv, {{ "glGetShaderiv" }} },
494 { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, {{ "glGetShaderInfoLog" }} },
495 { (PRFuncPtr*) &mSymbols.fGetShaderSource, {{ "glGetShaderSource" }} },
496 { (PRFuncPtr*) &mSymbols.fShaderSource, {{ "glShaderSource" }} },
497 { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, {{ "glVertexAttribPointer" }} },
499 { (PRFuncPtr*) &mSymbols.fGenBuffers, {{ "glGenBuffers", "glGenBuffersARB" }} },
500 { (PRFuncPtr*) &mSymbols.fGenTextures, {{ "glGenTextures" }} },
501 { (PRFuncPtr*) &mSymbols.fCreateProgram, {{ "glCreateProgram", "glCreateProgramARB" }} },
502 { (PRFuncPtr*) &mSymbols.fCreateShader, {{ "glCreateShader", "glCreateShaderARB" }} },
504 { (PRFuncPtr*) &mSymbols.fDeleteBuffers, {{ "glDeleteBuffers", "glDeleteBuffersARB" }} },
505 { (PRFuncPtr*) &mSymbols.fDeleteTextures, {{ "glDeleteTextures", "glDeleteTexturesARB" }} },
506 { (PRFuncPtr*) &mSymbols.fDeleteProgram, {{ "glDeleteProgram", "glDeleteProgramARB" }} },
507 { (PRFuncPtr*) &mSymbols.fDeleteShader, {{ "glDeleteShader", "glDeleteShaderARB" }} },
509 END_SYMBOLS
511 // clang-format on
513 if (!fnLoadSymbols(coreSymbols, "GL")) return false;
516 const SymLoadStruct symbols[] = {
517 {(PRFuncPtr*)&mSymbols.fGetGraphicsResetStatus,
518 {{"glGetGraphicsResetStatus", "glGetGraphicsResetStatusARB",
519 "glGetGraphicsResetStatusKHR", "glGetGraphicsResetStatusEXT"}}},
520 END_SYMBOLS};
521 (void)fnLoadSymbols(symbols, nullptr);
523 // We need to call the fGetError symbol directly here because if there is an
524 // unflushed reset status, we don't want to mark the context as lost. That
525 // would prevent us from recovering.
526 auto err = mSymbols.fGetError();
527 if (err == LOCAL_GL_CONTEXT_LOST) {
528 MOZ_ASSERT(mSymbols.fGetGraphicsResetStatus);
529 const auto status = fGetGraphicsResetStatus();
530 if (status) {
531 printf_stderr("Unflushed glGetGraphicsResetStatus: 0x%04x\n", status);
533 err = fGetError();
534 MOZ_ASSERT(!err);
536 if (err) {
537 MOZ_ASSERT(false);
538 return false;
542 ////////////////
544 const auto* const versionRawStr = (const char*)fGetString(LOCAL_GL_VERSION);
545 if (!versionRawStr || !*versionRawStr) {
546 // This can happen with Pernosco.
547 NS_WARNING("Empty GL version string");
548 return false;
551 const std::string versionStr = versionRawStr;
552 if (versionStr.find("OpenGL ES") == 0) {
553 mProfile = ContextProfile::OpenGLES;
556 uint32_t majorVer, minorVer;
557 if (!ParseVersion(versionStr, &majorVer, &minorVer)) {
558 MOZ_ASSERT(false, "Failed to parse GL_VERSION");
559 return false;
561 MOZ_ASSERT(majorVer < 10);
562 MOZ_ASSERT(minorVer < 10);
563 mVersion = majorVer * 100 + minorVer * 10;
564 if (mVersion < 200) return false;
566 ////
568 const auto glslVersionStr =
569 (const char*)fGetString(LOCAL_GL_SHADING_LANGUAGE_VERSION);
570 if (!glslVersionStr) {
571 // This happens on the Android emulators. We'll just return 100
572 mShadingLanguageVersion = 100;
573 } else if (ParseVersion(glslVersionStr, &majorVer, &minorVer)) {
574 MOZ_ASSERT(majorVer < 10);
575 MOZ_ASSERT(minorVer < 100);
576 mShadingLanguageVersion = majorVer * 100 + minorVer;
577 } else {
578 MOZ_ASSERT(false, "Failed to parse GL_SHADING_LANGUAGE_VERSION");
579 return false;
582 if (ShouldSpew()) {
583 printf_stderr("GL version detected: %u\n", mVersion);
584 printf_stderr("GLSL version detected: %u\n", mShadingLanguageVersion);
585 printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR));
586 printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER));
589 ////////////////
591 // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
592 if (mProfile == ContextProfile::OpenGLES) {
593 const SymLoadStruct symbols[] = {CORE_SYMBOL(GetShaderPrecisionFormat),
594 CORE_SYMBOL(ClearDepthf),
595 CORE_SYMBOL(DepthRangef), END_SYMBOLS};
597 if (!fnLoadSymbols(symbols, "OpenGL ES")) return false;
598 } else {
599 const SymLoadStruct symbols[] = {
600 CORE_SYMBOL(ClearDepth), CORE_SYMBOL(DepthRange),
601 CORE_SYMBOL(ReadBuffer), CORE_SYMBOL(MapBuffer),
602 CORE_SYMBOL(UnmapBuffer), CORE_SYMBOL(PointParameterf),
603 CORE_SYMBOL(DrawBuffer),
604 // The following functions are only used by Skia/GL in desktop mode.
605 // Other parts of Gecko should avoid using these
606 CORE_SYMBOL(DrawBuffers), CORE_SYMBOL(ClientActiveTexture),
607 CORE_SYMBOL(DisableClientState), CORE_SYMBOL(EnableClientState),
608 CORE_SYMBOL(LoadIdentity), CORE_SYMBOL(LoadMatrixf),
609 CORE_SYMBOL(MatrixMode), CORE_SYMBOL(PolygonMode), CORE_SYMBOL(TexGeni),
610 CORE_SYMBOL(TexGenf), CORE_SYMBOL(TexGenfv), CORE_SYMBOL(VertexPointer),
611 END_SYMBOLS};
613 if (!fnLoadSymbols(symbols, "Desktop OpenGL")) return false;
616 ////////////////
618 const char* glVendorString = (const char*)fGetString(LOCAL_GL_VENDOR);
619 const char* glRendererString = (const char*)fGetString(LOCAL_GL_RENDERER);
620 if (!glVendorString || !glRendererString) return false;
622 // The order of these strings must match up with the order of the enum
623 // defined in GLContext.h for vendor IDs.
624 const char* vendorMatchStrings[size_t(GLVendor::Other) + 1] = {
625 "Intel", "NVIDIA", "ATI", "Qualcomm", "Imagination",
626 "nouveau", "Vivante", "VMware, Inc.", "ARM", "Unknown"};
628 mVendor = GLVendor::Other;
629 for (size_t i = 0; i < size_t(GLVendor::Other); ++i) {
630 if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
631 mVendor = GLVendor(i);
632 break;
636 // The order of these strings must match up with the order of the enum
637 // defined in GLContext.h for renderer IDs.
638 const char* rendererMatchStrings[size_t(GLRenderer::Other) + 1] = {
639 "Adreno 200",
640 "Adreno 205",
641 "Adreno (TM) 200",
642 "Adreno (TM) 205",
643 "Adreno (TM) 305",
644 "Adreno (TM) 320",
645 "Adreno (TM) 330",
646 "Adreno (TM) 420",
647 "Mali-400 MP",
648 "Mali-450 MP",
649 "PowerVR SGX 530",
650 "PowerVR SGX 540",
651 "PowerVR SGX 544MP",
652 "NVIDIA Tegra",
653 "Android Emulator",
654 "Gallium 0.4 on llvmpipe",
655 "Intel HD Graphics 3000 OpenGL Engine",
656 "Microsoft Basic Render Driver",
657 "Unknown"};
659 mRenderer = GLRenderer::Other;
660 for (size_t i = 0; i < size_t(GLRenderer::Other); ++i) {
661 if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) {
662 mRenderer = GLRenderer(i);
663 break;
668 const auto versionStr = (const char*)fGetString(LOCAL_GL_VERSION);
669 if (strstr(versionStr, "Mesa")) {
670 mIsMesa = true;
674 const auto Once = []() {
675 static bool did = false;
676 if (did) return false;
677 did = true;
678 return true;
681 bool printRenderer = ShouldSpew();
682 printRenderer |= (kIsDebug && Once());
683 if (printRenderer) {
684 printf_stderr("GL_VENDOR: %s\n", glVendorString);
685 printf_stderr("mVendor: %s\n", vendorMatchStrings[size_t(mVendor)]);
686 printf_stderr("GL_RENDERER: %s\n", glRendererString);
687 printf_stderr("mRenderer: %s\n", rendererMatchStrings[size_t(mRenderer)]);
688 printf_stderr("mIsMesa: %i\n", int(mIsMesa));
691 ////////////////
693 if (mVersion >= 300) { // Both GL3 and ES3.
694 const SymLoadStruct symbols[] = {
695 {(PRFuncPtr*)&mSymbols.fGetStringi, {{"glGetStringi"}}}, END_SYMBOLS};
697 if (!fnLoadSymbols(symbols, "GetStringi")) {
698 MOZ_RELEASE_ASSERT(false, "GFX: GetStringi is required!");
699 return false;
703 InitExtensions();
704 if (mProfile != ContextProfile::OpenGLES) {
705 if (mVersion >= 310 && !IsExtensionSupported(ARB_compatibility)) {
706 mProfile = ContextProfile::OpenGLCore;
707 } else {
708 mProfile = ContextProfile::OpenGLCompatibility;
711 MOZ_ASSERT(mProfile != ContextProfile::Unknown);
713 if (ShouldSpew()) {
714 const char* profileStr = "";
715 if (mProfile == ContextProfile::OpenGLES) {
716 profileStr = " es";
717 } else if (mProfile == ContextProfile::OpenGLCore) {
718 profileStr = " core";
720 printf_stderr("Detected profile: %u%s\n", mVersion, profileStr);
723 InitFeatures();
725 ////
727 // Disable extensions with partial or incorrect support.
728 if (WorkAroundDriverBugs()) {
729 if (Renderer() == GLRenderer::AdrenoTM320) {
730 MarkUnsupported(GLFeature::standard_derivatives);
733 if (Renderer() == GLRenderer::AndroidEmulator) {
734 // Bug 1665300
735 mSymbols.fGetGraphicsResetStatus = 0;
738 if (Vendor() == GLVendor::Vivante) {
739 // bug 958256
740 MarkUnsupported(GLFeature::standard_derivatives);
743 if (Renderer() == GLRenderer::MicrosoftBasicRenderDriver) {
744 // Bug 978966: on Microsoft's "Basic Render Driver" (software renderer)
745 // multisampling hardcodes blending with the default blendfunc, which
746 // breaks WebGL.
747 MarkUnsupported(GLFeature::framebuffer_multisample);
750 if (IsMesa()) {
751 // DrawElementsInstanced hangs the driver.
752 MarkUnsupported(GLFeature::robust_buffer_access_behavior);
756 if (IsExtensionSupported(GLContext::ARB_pixel_buffer_object)) {
757 MOZ_ASSERT(
758 (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
759 "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer"
760 " being available!");
763 ////////////////////////////////////////////////////////////////////////////
765 const auto fnLoadForFeature = [&](const SymLoadStruct* list,
766 GLFeature feature) {
767 return this->LoadFeatureSymbols(*loader, list, feature);
770 // Check for ARB_framebuffer_objects
771 if (IsSupported(GLFeature::framebuffer_object)) {
772 // https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
773 const SymLoadStruct symbols[] = {
774 CORE_SYMBOL(IsRenderbuffer),
775 CORE_SYMBOL(BindRenderbuffer),
776 CORE_SYMBOL(DeleteRenderbuffers),
777 CORE_SYMBOL(GenRenderbuffers),
778 CORE_SYMBOL(RenderbufferStorage),
779 CORE_SYMBOL(RenderbufferStorageMultisample),
780 CORE_SYMBOL(GetRenderbufferParameteriv),
781 CORE_SYMBOL(IsFramebuffer),
782 CORE_SYMBOL(BindFramebuffer),
783 CORE_SYMBOL(DeleteFramebuffers),
784 CORE_SYMBOL(GenFramebuffers),
785 CORE_SYMBOL(CheckFramebufferStatus),
786 CORE_SYMBOL(FramebufferTexture2D),
787 CORE_SYMBOL(FramebufferTextureLayer),
788 CORE_SYMBOL(FramebufferRenderbuffer),
789 CORE_SYMBOL(GetFramebufferAttachmentParameteriv),
790 CORE_SYMBOL(BlitFramebuffer),
791 CORE_SYMBOL(GenerateMipmap),
792 END_SYMBOLS};
793 fnLoadForFeature(symbols, GLFeature::framebuffer_object);
796 if (!IsSupported(GLFeature::framebuffer_object)) {
797 // Check for aux symbols based on extensions
798 if (IsSupported(GLFeature::framebuffer_object_EXT_OES)) {
799 const SymLoadStruct symbols[] = {
800 CORE_EXT_SYMBOL2(IsRenderbuffer, EXT, OES),
801 CORE_EXT_SYMBOL2(BindRenderbuffer, EXT, OES),
802 CORE_EXT_SYMBOL2(DeleteRenderbuffers, EXT, OES),
803 CORE_EXT_SYMBOL2(GenRenderbuffers, EXT, OES),
804 CORE_EXT_SYMBOL2(RenderbufferStorage, EXT, OES),
805 CORE_EXT_SYMBOL2(GetRenderbufferParameteriv, EXT, OES),
806 CORE_EXT_SYMBOL2(IsFramebuffer, EXT, OES),
807 CORE_EXT_SYMBOL2(BindFramebuffer, EXT, OES),
808 CORE_EXT_SYMBOL2(DeleteFramebuffers, EXT, OES),
809 CORE_EXT_SYMBOL2(GenFramebuffers, EXT, OES),
810 CORE_EXT_SYMBOL2(CheckFramebufferStatus, EXT, OES),
811 CORE_EXT_SYMBOL2(FramebufferTexture2D, EXT, OES),
812 CORE_EXT_SYMBOL2(FramebufferRenderbuffer, EXT, OES),
813 CORE_EXT_SYMBOL2(GetFramebufferAttachmentParameteriv, EXT, OES),
814 CORE_EXT_SYMBOL2(GenerateMipmap, EXT, OES),
815 END_SYMBOLS};
816 fnLoadForFeature(symbols, GLFeature::framebuffer_object_EXT_OES);
819 if (IsSupported(GLFeature::framebuffer_blit)) {
820 const SymLoadStruct symbols[] = {
821 EXT_SYMBOL3(BlitFramebuffer, ANGLE, EXT, NV), END_SYMBOLS};
822 fnLoadForFeature(symbols, GLFeature::framebuffer_blit);
825 if (IsSupported(GLFeature::framebuffer_multisample)) {
826 const SymLoadStruct symbols[] = {
827 EXT_SYMBOL3(RenderbufferStorageMultisample, ANGLE, APPLE, EXT),
828 END_SYMBOLS};
829 fnLoadForFeature(symbols, GLFeature::framebuffer_multisample);
832 if (IsExtensionSupported(GLContext::ARB_geometry_shader4) ||
833 IsExtensionSupported(GLContext::NV_geometry_program4)) {
834 const SymLoadStruct symbols[] = {
835 EXT_SYMBOL2(FramebufferTextureLayer, ARB, EXT), END_SYMBOLS};
836 if (!fnLoadSymbols(symbols,
837 "ARB_geometry_shader4/NV_geometry_program4")) {
838 MarkExtensionUnsupported(GLContext::ARB_geometry_shader4);
839 MarkExtensionUnsupported(GLContext::NV_geometry_program4);
844 if (!IsSupported(GLFeature::framebuffer_object) &&
845 !IsSupported(GLFeature::framebuffer_object_EXT_OES)) {
846 NS_ERROR("GLContext requires support for framebuffer objects.");
847 return false;
849 MOZ_RELEASE_ASSERT(mSymbols.fBindFramebuffer,
850 "GFX: mSymbols.fBindFramebuffer zero or not set.");
852 ////////////////
854 const auto err = fGetError();
855 MOZ_RELEASE_ASSERT(!IsBadCallError(err));
856 if (err) return false;
858 LoadMoreSymbols(*loader);
860 ////////////////////////////////////////////////////////////////////////////
862 raw_fGetIntegerv(LOCAL_GL_VIEWPORT, mViewportRect);
863 raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mScissorRect);
864 raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
865 raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
866 raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
867 raw_fGetIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
869 if (mWorkAroundDriverBugs) {
870 int maxTexSize = INT32_MAX;
871 int maxCubeSize = INT32_MAX;
872 #ifdef XP_MACOSX
873 if (!nsCocoaFeatures::IsAtLeastVersion(10, 12)) {
874 if (mVendor == GLVendor::Intel) {
875 // see bug 737182 for 2D textures, bug 684882 for cube map textures.
876 maxTexSize = 4096;
877 maxCubeSize = 512;
878 } else if (mVendor == GLVendor::NVIDIA) {
879 // See bug 879656. 8192 fails, 8191 works.
880 maxTexSize = 8191;
882 } else {
883 // https://bugzilla.mozilla.org/show_bug.cgi?id=1544446
884 // Mojave exposes 16k textures, but gives FRAMEBUFFER_UNSUPPORTED for any
885 // 16k*16k FB except rgba8 without depth/stencil.
886 // The max supported sizes changes based on involved formats.
887 // (RGBA32F more restrictive than RGBA16F)
888 maxTexSize = 8192;
890 #endif
891 #ifdef MOZ_X11
892 if (mVendor == GLVendor::Nouveau) {
893 // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau.
894 maxCubeSize = 2048;
895 } else if (mVendor == GLVendor::Intel) {
896 // Bug 1199923. Driver seems to report a larger max size than
897 // actually supported.
898 maxTexSize = mMaxTextureSize / 2;
900 // Bug 1367570. Explicitly set vertex attributes [1,3] to opaque
901 // black because Nvidia doesn't do it for us.
902 if (mVendor == GLVendor::NVIDIA) {
903 for (size_t i = 1; i <= 3; ++i) {
904 mSymbols.fVertexAttrib4f(i, 0, 0, 0, 1);
907 #endif
908 if (Renderer() == GLRenderer::AdrenoTM420) {
909 // see bug 1194923. Calling glFlush before glDeleteFramebuffers
910 // prevents occasional driver crash.
911 mNeedsFlushBeforeDeleteFB = true;
913 #ifdef MOZ_WIDGET_ANDROID
914 if ((Renderer() == GLRenderer::AdrenoTM305 ||
915 Renderer() == GLRenderer::AdrenoTM320 ||
916 Renderer() == GLRenderer::AdrenoTM330) &&
917 jni::GetAPIVersion() < 21) {
918 // Bug 1164027. Driver crashes when functions such as
919 // glTexImage2D fail due to virtual memory exhaustion.
920 mTextureAllocCrashesOnMapFailure = true;
922 #endif
923 #if MOZ_WIDGET_ANDROID
924 if (Renderer() == GLRenderer::SGX540 && jni::GetAPIVersion() <= 15) {
925 // Bug 1288446. Driver sometimes crashes when uploading data to a
926 // texture if the render target has changed since the texture was
927 // rendered from. Calling glCheckFramebufferStatus after
928 // glFramebufferTexture2D prevents the crash.
929 mNeedsCheckAfterAttachTextureToFb = true;
931 #endif
933 // -
935 const auto fnLimit = [&](int* const driver, const int limit) {
936 if (*driver > limit) {
937 *driver = limit;
938 mNeedsTextureSizeChecks = true;
942 fnLimit(&mMaxTextureSize, maxTexSize);
943 fnLimit(&mMaxRenderbufferSize, maxTexSize);
945 maxCubeSize = std::min(maxCubeSize, maxTexSize);
946 fnLimit(&mMaxCubeMapTextureSize, maxCubeSize);
949 if (IsSupported(GLFeature::framebuffer_multisample)) {
950 fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples);
953 mMaxTexOrRbSize = std::min(mMaxTextureSize, mMaxRenderbufferSize);
955 ////////////////////////////////////////////////////////////////////////////
957 // We're ready for final setup.
958 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
959 MOZ_GL_ASSERT(this, IsCurrent());
961 if (ShouldSpew() && IsExtensionSupported(KHR_debug)) {
962 fEnable(LOCAL_GL_DEBUG_OUTPUT);
963 fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS);
964 fDebugMessageCallback(&StaticDebugCallback, (void*)this);
965 fDebugMessageControl(LOCAL_GL_DONT_CARE, LOCAL_GL_DONT_CARE,
966 LOCAL_GL_DONT_CARE, 0, nullptr, true);
969 return true;
972 void GLContext::LoadMoreSymbols(const SymbolLoader& loader) {
973 const auto fnLoadForExt = [&](const SymLoadStruct* list, GLExtensions ext) {
974 return this->LoadExtSymbols(loader, list, ext);
977 const auto fnLoadForFeature = [&](const SymLoadStruct* list,
978 GLFeature feature) {
979 return this->LoadFeatureSymbols(loader, list, feature);
982 const auto fnLoadFeatureByCore = [&](const SymLoadStruct* coreList,
983 const SymLoadStruct* extList,
984 GLFeature feature) {
985 const bool useCore = this->IsFeatureProvidedByCoreSymbols(feature);
986 const auto list = useCore ? coreList : extList;
987 return fnLoadForFeature(list, feature);
990 if (IsSupported(GLFeature::robustness)) {
991 const auto resetStrategy =
992 GetIntAs<GLuint>(LOCAL_GL_RESET_NOTIFICATION_STRATEGY);
993 if (resetStrategy != LOCAL_GL_LOSE_CONTEXT_ON_RESET) {
994 NS_WARNING(
995 "Robustness supported, strategy is not LOSE_CONTEXT_ON_RESET!");
996 if (ShouldSpew()) {
997 const bool isDisabled =
998 (resetStrategy == LOCAL_GL_NO_RESET_NOTIFICATION);
999 printf_stderr("Strategy: %s (0x%04x)",
1000 (isDisabled ? "disabled" : "unrecognized"),
1001 resetStrategy);
1003 MarkUnsupported(GLFeature::robustness);
1007 if (IsSupported(GLFeature::sync)) {
1008 const SymLoadStruct symbols[] = {
1009 CORE_SYMBOL(FenceSync), CORE_SYMBOL(IsSync),
1010 CORE_SYMBOL(DeleteSync), CORE_SYMBOL(ClientWaitSync),
1011 CORE_SYMBOL(WaitSync), CORE_SYMBOL(GetInteger64v),
1012 CORE_SYMBOL(GetSynciv), END_SYMBOLS};
1013 fnLoadForFeature(symbols, GLFeature::sync);
1016 if (IsExtensionSupported(OES_EGL_image)) {
1017 const SymLoadStruct symbols[] = {
1018 {(PRFuncPtr*)&mSymbols.fEGLImageTargetTexture2D,
1019 {{"glEGLImageTargetTexture2DOES"}}},
1020 {(PRFuncPtr*)&mSymbols.fEGLImageTargetRenderbufferStorage,
1021 {{"glEGLImageTargetRenderbufferStorageOES"}}},
1022 END_SYMBOLS};
1023 fnLoadForExt(symbols, OES_EGL_image);
1026 if (IsExtensionSupported(APPLE_texture_range)) {
1027 const SymLoadStruct symbols[] = {CORE_SYMBOL(TextureRangeAPPLE),
1028 END_SYMBOLS};
1029 fnLoadForExt(symbols, APPLE_texture_range);
1032 if (IsExtensionSupported(APPLE_fence)) {
1033 const SymLoadStruct symbols[] = {CORE_SYMBOL(FinishObjectAPPLE),
1034 CORE_SYMBOL(TestObjectAPPLE), END_SYMBOLS};
1035 fnLoadForExt(symbols, APPLE_fence);
1038 // clang-format off
1040 if (IsSupported(GLFeature::vertex_array_object)) {
1041 const SymLoadStruct coreSymbols[] = {
1042 { (PRFuncPtr*) &mSymbols.fIsVertexArray, {{ "glIsVertexArray" }} },
1043 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, {{ "glGenVertexArrays" }} },
1044 { (PRFuncPtr*) &mSymbols.fBindVertexArray, {{ "glBindVertexArray" }} },
1045 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, {{ "glDeleteVertexArrays" }} },
1046 END_SYMBOLS
1048 const SymLoadStruct extSymbols[] = {
1049 { (PRFuncPtr*) &mSymbols.fIsVertexArray, {{ "glIsVertexArrayARB", "glIsVertexArrayOES", "glIsVertexArrayAPPLE" }} },
1050 { (PRFuncPtr*) &mSymbols.fGenVertexArrays, {{ "glGenVertexArraysARB", "glGenVertexArraysOES", "glGenVertexArraysAPPLE" }} },
1051 { (PRFuncPtr*) &mSymbols.fBindVertexArray, {{ "glBindVertexArrayARB", "glBindVertexArrayOES", "glBindVertexArrayAPPLE" }} },
1052 { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, {{ "glDeleteVertexArraysARB", "glDeleteVertexArraysOES", "glDeleteVertexArraysAPPLE" }} },
1053 END_SYMBOLS
1055 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::vertex_array_object);
1058 if (IsSupported(GLFeature::draw_instanced)) {
1059 const SymLoadStruct coreSymbols[] = {
1060 { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, {{ "glDrawArraysInstanced" }} },
1061 { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, {{ "glDrawElementsInstanced" }} },
1062 END_SYMBOLS
1064 const SymLoadStruct extSymbols[] = {
1065 { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, {{ "glDrawArraysInstancedARB", "glDrawArraysInstancedEXT", "glDrawArraysInstancedNV", "glDrawArraysInstancedANGLE" }} },
1066 { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, {{ "glDrawElementsInstancedARB", "glDrawElementsInstancedEXT", "glDrawElementsInstancedNV", "glDrawElementsInstancedANGLE" }}
1068 END_SYMBOLS
1070 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_instanced);
1073 if (IsSupported(GLFeature::instanced_arrays)) {
1074 const SymLoadStruct coreSymbols[] = {
1075 { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, {{ "glVertexAttribDivisor" }} },
1076 END_SYMBOLS
1078 const SymLoadStruct extSymbols[] = {
1079 { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, {{ "glVertexAttribDivisorARB", "glVertexAttribDivisorNV", "glVertexAttribDivisorANGLE" }} },
1080 END_SYMBOLS
1082 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::instanced_arrays);
1085 if (IsSupported(GLFeature::texture_storage)) {
1086 const SymLoadStruct coreSymbols[] = {
1087 { (PRFuncPtr*) &mSymbols.fTexStorage2D, {{ "glTexStorage2D" }} },
1088 { (PRFuncPtr*) &mSymbols.fTexStorage3D, {{ "glTexStorage3D" }} },
1089 END_SYMBOLS
1091 const SymLoadStruct extSymbols[] = {
1092 { (PRFuncPtr*) &mSymbols.fTexStorage2D, {{ "glTexStorage2DEXT" }} },
1093 { (PRFuncPtr*) &mSymbols.fTexStorage3D, {{ "glTexStorage3DEXT" }} },
1094 END_SYMBOLS
1096 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_storage);
1099 if (IsSupported(GLFeature::sampler_objects)) {
1100 const SymLoadStruct symbols[] = {
1101 { (PRFuncPtr*) &mSymbols.fGenSamplers, {{ "glGenSamplers" }} },
1102 { (PRFuncPtr*) &mSymbols.fDeleteSamplers, {{ "glDeleteSamplers" }} },
1103 { (PRFuncPtr*) &mSymbols.fIsSampler, {{ "glIsSampler" }} },
1104 { (PRFuncPtr*) &mSymbols.fBindSampler, {{ "glBindSampler" }} },
1105 { (PRFuncPtr*) &mSymbols.fSamplerParameteri, {{ "glSamplerParameteri" }} },
1106 { (PRFuncPtr*) &mSymbols.fSamplerParameteriv, {{ "glSamplerParameteriv" }} },
1107 { (PRFuncPtr*) &mSymbols.fSamplerParameterf, {{ "glSamplerParameterf" }} },
1108 { (PRFuncPtr*) &mSymbols.fSamplerParameterfv, {{ "glSamplerParameterfv" }} },
1109 { (PRFuncPtr*) &mSymbols.fGetSamplerParameteriv, {{ "glGetSamplerParameteriv" }} },
1110 { (PRFuncPtr*) &mSymbols.fGetSamplerParameterfv, {{ "glGetSamplerParameterfv" }} },
1111 END_SYMBOLS
1113 fnLoadForFeature(symbols, GLFeature::sampler_objects);
1116 // ARB_transform_feedback2/NV_transform_feedback2 is a
1117 // superset of EXT_transform_feedback/NV_transform_feedback
1118 // and adds glPauseTransformFeedback &
1119 // glResumeTransformFeedback, which are required for WebGL2.
1120 if (IsSupported(GLFeature::transform_feedback2)) {
1121 const SymLoadStruct coreSymbols[] = {
1122 { (PRFuncPtr*) &mSymbols.fBindBufferBase, {{ "glBindBufferBase" }} },
1123 { (PRFuncPtr*) &mSymbols.fBindBufferRange, {{ "glBindBufferRange" }} },
1124 { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, {{ "glGenTransformFeedbacks" }} },
1125 { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, {{ "glBindTransformFeedback" }} },
1126 { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, {{ "glDeleteTransformFeedbacks" }} },
1127 { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, {{ "glIsTransformFeedback" }} },
1128 { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, {{ "glBeginTransformFeedback" }} },
1129 { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, {{ "glEndTransformFeedback" }} },
1130 { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, {{ "glTransformFeedbackVaryings" }} },
1131 { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, {{ "glGetTransformFeedbackVarying" }} },
1132 { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, {{ "glPauseTransformFeedback" }} },
1133 { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, {{ "glResumeTransformFeedback" }} },
1134 END_SYMBOLS
1136 const SymLoadStruct extSymbols[] = {
1137 { (PRFuncPtr*) &mSymbols.fBindBufferBase, {{ "glBindBufferBaseEXT", "glBindBufferBaseNV" }} },
1138 { (PRFuncPtr*) &mSymbols.fBindBufferRange, {{ "glBindBufferRangeEXT", "glBindBufferRangeNV" }} },
1139 { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, {{ "glGenTransformFeedbacksNV" }} },
1140 { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, {{ "glBindTransformFeedbackNV" }} },
1141 { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, {{ "glDeleteTransformFeedbacksNV" }} },
1142 { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, {{ "glIsTransformFeedbackNV" }} },
1143 { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, {{ "glBeginTransformFeedbackEXT", "glBeginTransformFeedbackNV" }} },
1144 { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, {{ "glEndTransformFeedbackEXT", "glEndTransformFeedbackNV" }} },
1145 { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, {{ "glTransformFeedbackVaryingsEXT", "glTransformFeedbackVaryingsNV" }} },
1146 { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, {{ "glGetTransformFeedbackVaryingEXT", "glGetTransformFeedbackVaryingNV" }} },
1147 { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, {{ "glPauseTransformFeedbackNV" }} },
1148 { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, {{ "glResumeTransformFeedbackNV" }} },
1149 END_SYMBOLS
1151 if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::transform_feedback2)) {
1152 // Also mark bind_buffer_offset as unsupported.
1153 MarkUnsupported(GLFeature::bind_buffer_offset);
1157 if (IsSupported(GLFeature::bind_buffer_offset)) {
1158 const SymLoadStruct coreSymbols[] = {
1159 { (PRFuncPtr*) &mSymbols.fBindBufferOffset, {{ "glBindBufferOffset" }} },
1160 END_SYMBOLS
1162 const SymLoadStruct extSymbols[] = {
1163 { (PRFuncPtr*) &mSymbols.fBindBufferOffset,
1164 {{ "glBindBufferOffsetEXT", "glBindBufferOffsetNV" }}
1166 END_SYMBOLS
1168 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::bind_buffer_offset);
1171 if (IsSupported(GLFeature::query_counter)) {
1172 const SymLoadStruct coreSymbols[] = {
1173 { (PRFuncPtr*) &mSymbols.fQueryCounter, {{ "glQueryCounter" }} },
1174 END_SYMBOLS
1176 const SymLoadStruct extSymbols[] = {
1177 { (PRFuncPtr*) &mSymbols.fQueryCounter, {{ "glQueryCounterEXT", "glQueryCounterANGLE" }} },
1178 END_SYMBOLS
1180 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_counter);
1183 if (IsSupported(GLFeature::query_objects)) {
1184 const SymLoadStruct coreSymbols[] = {
1185 { (PRFuncPtr*) &mSymbols.fBeginQuery, {{ "glBeginQuery" }} },
1186 { (PRFuncPtr*) &mSymbols.fGenQueries, {{ "glGenQueries" }} },
1187 { (PRFuncPtr*) &mSymbols.fDeleteQueries, {{ "glDeleteQueries" }} },
1188 { (PRFuncPtr*) &mSymbols.fEndQuery, {{ "glEndQuery" }} },
1189 { (PRFuncPtr*) &mSymbols.fGetQueryiv, {{ "glGetQueryiv" }} },
1190 { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, {{ "glGetQueryObjectuiv" }} },
1191 { (PRFuncPtr*) &mSymbols.fIsQuery, {{ "glIsQuery" }} },
1192 END_SYMBOLS
1194 const SymLoadStruct extSymbols[] = {
1195 { (PRFuncPtr*) &mSymbols.fBeginQuery, {{ "glBeginQueryEXT", "glBeginQueryANGLE" }} },
1196 { (PRFuncPtr*) &mSymbols.fGenQueries, {{ "glGenQueriesEXT", "glGenQueriesANGLE" }} },
1197 { (PRFuncPtr*) &mSymbols.fDeleteQueries, {{ "glDeleteQueriesEXT", "glDeleteQueriesANGLE" }} },
1198 { (PRFuncPtr*) &mSymbols.fEndQuery, {{ "glEndQueryEXT", "glEndQueryANGLE" }} },
1199 { (PRFuncPtr*) &mSymbols.fGetQueryiv, {{ "glGetQueryivEXT", "glGetQueryivANGLE" }} },
1200 { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, {{ "glGetQueryObjectuivEXT", "glGetQueryObjectuivANGLE" }} },
1201 { (PRFuncPtr*) &mSymbols.fIsQuery, {{ "glIsQueryEXT", "glIsQueryANGLE" }} },
1202 END_SYMBOLS
1204 if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_objects)) {
1205 MarkUnsupported(GLFeature::get_query_object_i64v);
1206 MarkUnsupported(GLFeature::get_query_object_iv);
1207 MarkUnsupported(GLFeature::occlusion_query);
1208 MarkUnsupported(GLFeature::occlusion_query_boolean);
1209 MarkUnsupported(GLFeature::occlusion_query2);
1213 if (IsSupported(GLFeature::get_query_object_i64v)) {
1214 const SymLoadStruct coreSymbols[] = {
1215 { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, {{ "glGetQueryObjecti64v" }} },
1216 { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, {{ "glGetQueryObjectui64v" }} },
1217 END_SYMBOLS
1219 const SymLoadStruct extSymbols[] = {
1220 { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, {{ "glGetQueryObjecti64vEXT", "glGetQueryObjecti64vANGLE" }} },
1221 { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, {{ "glGetQueryObjectui64vEXT", "glGetQueryObjectui64vANGLE" }} },
1222 END_SYMBOLS
1224 if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_i64v)) {
1225 MarkUnsupported(GLFeature::query_counter);
1229 if (IsSupported(GLFeature::get_query_object_iv)) {
1230 const SymLoadStruct coreSymbols[] = {
1231 { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, {{ "glGetQueryObjectiv" }} },
1232 END_SYMBOLS
1234 const SymLoadStruct extSymbols[] = {
1235 { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, {{ "glGetQueryObjectivEXT", "glGetQueryObjectivANGLE" }} },
1236 END_SYMBOLS
1238 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_iv);
1241 if (IsSupported(GLFeature::clear_buffers)) {
1242 const SymLoadStruct symbols[] = {
1243 { (PRFuncPtr*) &mSymbols.fClearBufferfi, {{ "glClearBufferfi", }} },
1244 { (PRFuncPtr*) &mSymbols.fClearBufferfv, {{ "glClearBufferfv", }} },
1245 { (PRFuncPtr*) &mSymbols.fClearBufferiv, {{ "glClearBufferiv", }} },
1246 { (PRFuncPtr*) &mSymbols.fClearBufferuiv, {{ "glClearBufferuiv" }} },
1247 END_SYMBOLS
1249 fnLoadForFeature(symbols, GLFeature::clear_buffers);
1252 if (IsSupported(GLFeature::copy_buffer)) {
1253 const SymLoadStruct symbols[] = {
1254 { (PRFuncPtr*) &mSymbols.fCopyBufferSubData, {{ "glCopyBufferSubData" }} },
1255 END_SYMBOLS
1257 fnLoadForFeature(symbols, GLFeature::copy_buffer);
1260 if (IsSupported(GLFeature::draw_buffers)) {
1261 const SymLoadStruct coreSymbols[] = {
1262 { (PRFuncPtr*) &mSymbols.fDrawBuffers, {{ "glDrawBuffers" }} },
1263 END_SYMBOLS
1265 const SymLoadStruct extSymbols[] = {
1266 { (PRFuncPtr*) &mSymbols.fDrawBuffers, {{ "glDrawBuffersARB", "glDrawBuffersEXT" }} },
1267 END_SYMBOLS
1269 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers);
1272 if (IsSupported(GLFeature::draw_buffers_indexed)) {
1273 const SymLoadStruct coreSymbols[] = {
1274 { (PRFuncPtr*) &mSymbols.fBlendEquationSeparatei, {{ "glBlendEquationSeparatei" }} },
1275 { (PRFuncPtr*) &mSymbols.fBlendFuncSeparatei, {{ "glBlendFuncSeparatei" }} },
1276 { (PRFuncPtr*) &mSymbols.fColorMaski, {{ "glColorMaski" }} },
1277 { (PRFuncPtr*) &mSymbols.fDisablei, {{ "glDisablei" }} },
1278 { (PRFuncPtr*) &mSymbols.fEnablei, {{ "glEnablei" }} },
1279 END_SYMBOLS
1281 const SymLoadStruct extSymbols[] = {
1282 { (PRFuncPtr*) &mSymbols.fBlendEquationSeparatei, {{ "glBlendEquationSeparateiOES" }} },
1283 { (PRFuncPtr*) &mSymbols.fBlendFuncSeparatei, {{ "glBlendFuncSeparateiOES" }} },
1284 { (PRFuncPtr*) &mSymbols.fColorMaski, {{ "glColorMaskiOES" }} },
1285 { (PRFuncPtr*) &mSymbols.fDisablei, {{ "glDisableiOES" }} },
1286 { (PRFuncPtr*) &mSymbols.fEnablei, {{ "glEnableiOES" }} },
1287 END_SYMBOLS
1289 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers_indexed);
1292 if (IsSupported(GLFeature::get_integer_indexed)) {
1293 const SymLoadStruct coreSymbols[] = {
1294 { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, {{ "glGetIntegeri_v" }} },
1295 END_SYMBOLS
1297 const SymLoadStruct extSymbols[] ={
1298 { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, {{ "glGetIntegerIndexedvEXT" }} },
1299 END_SYMBOLS
1301 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_integer_indexed);
1304 if (IsSupported(GLFeature::get_integer64_indexed)) {
1305 const SymLoadStruct symbols[] = {
1306 { (PRFuncPtr*) &mSymbols.fGetInteger64i_v, {{ "glGetInteger64i_v" }} },
1307 END_SYMBOLS
1309 fnLoadForFeature(symbols, GLFeature::get_integer64_indexed);
1312 if (IsSupported(GLFeature::gpu_shader4)) {
1313 const SymLoadStruct symbols[] = {
1314 { (PRFuncPtr*) &mSymbols.fGetVertexAttribIiv, {{ "glGetVertexAttribIiv", "glGetVertexAttribIivEXT" }} },
1315 { (PRFuncPtr*) &mSymbols.fGetVertexAttribIuiv, {{ "glGetVertexAttribIuiv", "glGetVertexAttribIuivEXT" }} },
1316 { (PRFuncPtr*) &mSymbols.fVertexAttribI4i, {{ "glVertexAttribI4i", "glVertexAttribI4iEXT" }} },
1317 { (PRFuncPtr*) &mSymbols.fVertexAttribI4iv, {{ "glVertexAttribI4iv", "glVertexAttribI4ivEXT" }} },
1318 { (PRFuncPtr*) &mSymbols.fVertexAttribI4ui, {{ "glVertexAttribI4ui", "glVertexAttribI4uiEXT" }} },
1319 { (PRFuncPtr*) &mSymbols.fVertexAttribI4uiv, {{ "glVertexAttribI4uiv", "glVertexAttribI4uivEXT" }} },
1320 { (PRFuncPtr*) &mSymbols.fVertexAttribIPointer, {{ "glVertexAttribIPointer", "glVertexAttribIPointerEXT" }} },
1321 { (PRFuncPtr*) &mSymbols.fUniform1ui, {{ "glUniform1ui", "glUniform1uiEXT" }} },
1322 { (PRFuncPtr*) &mSymbols.fUniform2ui, {{ "glUniform2ui", "glUniform2uiEXT" }} },
1323 { (PRFuncPtr*) &mSymbols.fUniform3ui, {{ "glUniform3ui", "glUniform3uiEXT" }} },
1324 { (PRFuncPtr*) &mSymbols.fUniform4ui, {{ "glUniform4ui", "glUniform4uiEXT" }} },
1325 { (PRFuncPtr*) &mSymbols.fUniform1uiv, {{ "glUniform1uiv", "glUniform1uivEXT" }} },
1326 { (PRFuncPtr*) &mSymbols.fUniform2uiv, {{ "glUniform2uiv", "glUniform2uivEXT" }} },
1327 { (PRFuncPtr*) &mSymbols.fUniform3uiv, {{ "glUniform3uiv", "glUniform3uivEXT" }} },
1328 { (PRFuncPtr*) &mSymbols.fUniform4uiv, {{ "glUniform4uiv", "glUniform4uivEXT" }} },
1329 { (PRFuncPtr*) &mSymbols.fGetFragDataLocation, {{ "glGetFragDataLocation", "glGetFragDataLocationEXT" }} },
1330 { (PRFuncPtr*) &mSymbols.fGetUniformuiv, {{ "glGetUniformuiv", "glGetUniformuivEXT" }} },
1331 END_SYMBOLS
1333 fnLoadForFeature(symbols, GLFeature::gpu_shader4);
1336 if (IsSupported(GLFeature::map_buffer_range)) {
1337 const SymLoadStruct symbols[] = {
1338 { (PRFuncPtr*) &mSymbols.fMapBufferRange, {{ "glMapBufferRange" }} },
1339 { (PRFuncPtr*) &mSymbols.fFlushMappedBufferRange, {{ "glFlushMappedBufferRange" }} },
1340 { (PRFuncPtr*) &mSymbols.fUnmapBuffer, {{ "glUnmapBuffer" }} },
1341 END_SYMBOLS
1343 fnLoadForFeature(symbols, GLFeature::map_buffer_range);
1346 if (IsSupported(GLFeature::texture_3D)) {
1347 const SymLoadStruct coreSymbols[] = {
1348 { (PRFuncPtr*) &mSymbols.fTexImage3D, {{ "glTexImage3D" }} },
1349 { (PRFuncPtr*) &mSymbols.fTexSubImage3D, {{ "glTexSubImage3D" }} },
1350 END_SYMBOLS
1352 const SymLoadStruct extSymbols[] = {
1353 { (PRFuncPtr*) &mSymbols.fTexImage3D, {{ "glTexImage3DOES" }} },
1354 { (PRFuncPtr*) &mSymbols.fTexSubImage3D, {{ "glTexSubImage3DOES" }} },
1355 END_SYMBOLS
1357 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D);
1360 if (IsSupported(GLFeature::texture_3D_compressed)) {
1361 const SymLoadStruct coreSymbols[] = {
1362 { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, {{ "glCompressedTexImage3D" }} },
1363 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, {{ "glCompressedTexSubImage3D" }} },
1364 END_SYMBOLS
1366 const SymLoadStruct extSymbols[] = {
1367 { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, {{ "glCompressedTexImage3DARB", "glCompressedTexImage3DOES" }} },
1368 { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, {{ "glCompressedTexSubImage3DARB", "glCompressedTexSubImage3DOES" }} },
1369 END_SYMBOLS
1371 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_compressed);
1374 if (IsSupported(GLFeature::texture_3D_copy)) {
1375 const SymLoadStruct coreSymbols[] = {
1376 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, {{ "glCopyTexSubImage3D" }} },
1377 END_SYMBOLS
1379 const SymLoadStruct extSymbols[] = {
1380 { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, {{ "glCopyTexSubImage3DEXT", "glCopyTexSubImage3DOES" }} },
1381 END_SYMBOLS
1383 fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_copy);
1386 if (IsSupported(GLFeature::uniform_buffer_object)) {
1387 // Note: Don't query for glGetActiveUniformName because it is not
1388 // supported by GL ES 3.
1389 const SymLoadStruct symbols[] = {
1390 { (PRFuncPtr*) &mSymbols.fGetUniformIndices, {{ "glGetUniformIndices" }} },
1391 { (PRFuncPtr*) &mSymbols.fGetActiveUniformsiv, {{ "glGetActiveUniformsiv" }} },
1392 { (PRFuncPtr*) &mSymbols.fGetUniformBlockIndex, {{ "glGetUniformBlockIndex" }} },
1393 { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockiv, {{ "glGetActiveUniformBlockiv" }} },
1394 { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockName, {{ "glGetActiveUniformBlockName" }} },
1395 { (PRFuncPtr*) &mSymbols.fUniformBlockBinding, {{ "glUniformBlockBinding" }} },
1396 END_SYMBOLS
1398 fnLoadForFeature(symbols, GLFeature::uniform_buffer_object);
1401 if (IsSupported(GLFeature::uniform_matrix_nonsquare)) {
1402 const SymLoadStruct symbols[] = {
1403 { (PRFuncPtr*) &mSymbols.fUniformMatrix2x3fv, {{ "glUniformMatrix2x3fv" }} },
1404 { (PRFuncPtr*) &mSymbols.fUniformMatrix2x4fv, {{ "glUniformMatrix2x4fv" }} },
1405 { (PRFuncPtr*) &mSymbols.fUniformMatrix3x2fv, {{ "glUniformMatrix3x2fv" }} },
1406 { (PRFuncPtr*) &mSymbols.fUniformMatrix3x4fv, {{ "glUniformMatrix3x4fv" }} },
1407 { (PRFuncPtr*) &mSymbols.fUniformMatrix4x2fv, {{ "glUniformMatrix4x2fv" }} },
1408 { (PRFuncPtr*) &mSymbols.fUniformMatrix4x3fv, {{ "glUniformMatrix4x3fv" }} },
1409 END_SYMBOLS
1411 fnLoadForFeature(symbols, GLFeature::uniform_matrix_nonsquare);
1414 if (IsSupported(GLFeature::internalformat_query)) {
1415 const SymLoadStruct symbols[] = {
1416 CORE_SYMBOL(GetInternalformativ),
1417 END_SYMBOLS
1419 fnLoadForFeature(symbols, GLFeature::internalformat_query);
1422 if (IsSupported(GLFeature::invalidate_framebuffer)) {
1423 const SymLoadStruct symbols[] = {
1424 { (PRFuncPtr*) &mSymbols.fInvalidateFramebuffer, {{ "glInvalidateFramebuffer" }} },
1425 { (PRFuncPtr*) &mSymbols.fInvalidateSubFramebuffer, {{ "glInvalidateSubFramebuffer" }} },
1426 END_SYMBOLS
1428 fnLoadForFeature(symbols, GLFeature::invalidate_framebuffer);
1431 if (IsSupported(GLFeature::multiview)) {
1432 const SymLoadStruct symbols[] = {
1433 { (PRFuncPtr*) &mSymbols.fFramebufferTextureMultiview, {{
1434 "glFramebufferTextureMultiviewOVR",
1435 "glFramebufferTextureMultiviewLayeredANGLE"
1436 }} },
1437 END_SYMBOLS
1439 fnLoadForFeature(symbols, GLFeature::multiview);
1442 if (IsSupported(GLFeature::prim_restart)) {
1443 const SymLoadStruct symbols[] = {
1444 { (PRFuncPtr*) &mSymbols.fPrimitiveRestartIndex, {{ "glPrimitiveRestartIndex", "glPrimitiveRestartIndexNV" }} },
1445 END_SYMBOLS
1447 fnLoadForFeature(symbols, GLFeature::prim_restart);
1450 if (IsExtensionSupported(KHR_debug)) {
1451 const SymLoadStruct symbols[] = {
1452 { (PRFuncPtr*) &mSymbols.fDebugMessageControl, {{ "glDebugMessageControl", "glDebugMessageControlKHR", }} },
1453 { (PRFuncPtr*) &mSymbols.fDebugMessageInsert, {{ "glDebugMessageInsert", "glDebugMessageInsertKHR", }} },
1454 { (PRFuncPtr*) &mSymbols.fDebugMessageCallback, {{ "glDebugMessageCallback", "glDebugMessageCallbackKHR" }} },
1455 { (PRFuncPtr*) &mSymbols.fGetDebugMessageLog, {{ "glGetDebugMessageLog", "glGetDebugMessageLogKHR", }} },
1456 { (PRFuncPtr*) &mSymbols.fGetPointerv, {{ "glGetPointerv", "glGetPointervKHR", }} },
1457 { (PRFuncPtr*) &mSymbols.fPushDebugGroup, {{ "glPushDebugGroup", "glPushDebugGroupKHR", }} },
1458 { (PRFuncPtr*) &mSymbols.fPopDebugGroup, {{ "glPopDebugGroup", "glPopDebugGroupKHR", }} },
1459 { (PRFuncPtr*) &mSymbols.fObjectLabel, {{ "glObjectLabel", "glObjectLabelKHR", }} },
1460 { (PRFuncPtr*) &mSymbols.fGetObjectLabel, {{ "glGetObjectLabel", "glGetObjectLabelKHR", }} },
1461 { (PRFuncPtr*) &mSymbols.fObjectPtrLabel, {{ "glObjectPtrLabel", "glObjectPtrLabelKHR", }} },
1462 { (PRFuncPtr*) &mSymbols.fGetObjectPtrLabel, {{ "glGetObjectPtrLabel", "glGetObjectPtrLabelKHR", }} },
1463 END_SYMBOLS
1465 fnLoadForExt(symbols, KHR_debug);
1468 if (IsExtensionSupported(NV_fence)) {
1469 const SymLoadStruct symbols[] = {
1470 { (PRFuncPtr*) &mSymbols.fGenFences, {{ "glGenFencesNV" }} },
1471 { (PRFuncPtr*) &mSymbols.fDeleteFences, {{ "glDeleteFencesNV" }} },
1472 { (PRFuncPtr*) &mSymbols.fSetFence, {{ "glSetFenceNV" }} },
1473 { (PRFuncPtr*) &mSymbols.fTestFence, {{ "glTestFenceNV" }} },
1474 { (PRFuncPtr*) &mSymbols.fFinishFence, {{ "glFinishFenceNV" }} },
1475 { (PRFuncPtr*) &mSymbols.fIsFence, {{ "glIsFenceNV" }} },
1476 { (PRFuncPtr*) &mSymbols.fGetFenceiv, {{ "glGetFenceivNV" }} },
1477 END_SYMBOLS
1479 fnLoadForExt(symbols, NV_fence);
1482 // clang-format on
1484 if (IsExtensionSupported(NV_texture_barrier)) {
1485 const SymLoadStruct symbols[] = {
1486 {(PRFuncPtr*)&mSymbols.fTextureBarrier, {{"glTextureBarrierNV"}}},
1487 END_SYMBOLS};
1488 fnLoadForExt(symbols, NV_texture_barrier);
1491 if (IsSupported(GLFeature::read_buffer)) {
1492 const SymLoadStruct symbols[] = {CORE_SYMBOL(ReadBuffer), END_SYMBOLS};
1493 fnLoadForFeature(symbols, GLFeature::read_buffer);
1496 if (IsExtensionSupported(APPLE_framebuffer_multisample)) {
1497 const SymLoadStruct symbols[] = {
1498 CORE_SYMBOL(ResolveMultisampleFramebufferAPPLE), END_SYMBOLS};
1499 fnLoadForExt(symbols, APPLE_framebuffer_multisample);
1502 // Load developer symbols, don't fail if we can't find them.
1503 const SymLoadStruct devSymbols[] = {CORE_SYMBOL(GetTexImage),
1504 CORE_SYMBOL(GetTexLevelParameteriv),
1505 END_SYMBOLS};
1506 const bool warnOnFailures = ShouldSpew();
1507 (void)loader.LoadSymbols(devSymbols, warnOnFailures);
1510 #undef CORE_SYMBOL
1511 #undef CORE_EXT_SYMBOL2
1512 #undef EXT_SYMBOL2
1513 #undef EXT_SYMBOL3
1514 #undef END_SYMBOLS
1516 void GLContext::DebugCallback(GLenum source, GLenum type, GLuint id,
1517 GLenum severity, GLsizei length,
1518 const GLchar* message) {
1519 nsAutoCString sourceStr;
1520 switch (source) {
1521 case LOCAL_GL_DEBUG_SOURCE_API:
1522 sourceStr = "SOURCE_API"_ns;
1523 break;
1524 case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM:
1525 sourceStr = "SOURCE_WINDOW_SYSTEM"_ns;
1526 break;
1527 case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER:
1528 sourceStr = "SOURCE_SHADER_COMPILER"_ns;
1529 break;
1530 case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY:
1531 sourceStr = "SOURCE_THIRD_PARTY"_ns;
1532 break;
1533 case LOCAL_GL_DEBUG_SOURCE_APPLICATION:
1534 sourceStr = "SOURCE_APPLICATION"_ns;
1535 break;
1536 case LOCAL_GL_DEBUG_SOURCE_OTHER:
1537 sourceStr = "SOURCE_OTHER"_ns;
1538 break;
1539 default:
1540 sourceStr = nsPrintfCString("<source 0x%04x>", source);
1541 break;
1544 nsAutoCString typeStr;
1545 switch (type) {
1546 case LOCAL_GL_DEBUG_TYPE_ERROR:
1547 typeStr = "TYPE_ERROR"_ns;
1548 break;
1549 case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
1550 typeStr = "TYPE_DEPRECATED_BEHAVIOR"_ns;
1551 break;
1552 case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
1553 typeStr = "TYPE_UNDEFINED_BEHAVIOR"_ns;
1554 break;
1555 case LOCAL_GL_DEBUG_TYPE_PORTABILITY:
1556 typeStr = "TYPE_PORTABILITY"_ns;
1557 break;
1558 case LOCAL_GL_DEBUG_TYPE_PERFORMANCE:
1559 typeStr = "TYPE_PERFORMANCE"_ns;
1560 break;
1561 case LOCAL_GL_DEBUG_TYPE_OTHER:
1562 typeStr = "TYPE_OTHER"_ns;
1563 break;
1564 case LOCAL_GL_DEBUG_TYPE_MARKER:
1565 typeStr = "TYPE_MARKER"_ns;
1566 break;
1567 default:
1568 typeStr = nsPrintfCString("<type 0x%04x>", type);
1569 break;
1572 nsAutoCString sevStr;
1573 switch (severity) {
1574 case LOCAL_GL_DEBUG_SEVERITY_HIGH:
1575 sevStr = "SEVERITY_HIGH"_ns;
1576 break;
1577 case LOCAL_GL_DEBUG_SEVERITY_MEDIUM:
1578 sevStr = "SEVERITY_MEDIUM"_ns;
1579 break;
1580 case LOCAL_GL_DEBUG_SEVERITY_LOW:
1581 sevStr = "SEVERITY_LOW"_ns;
1582 break;
1583 case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION:
1584 sevStr = "SEVERITY_NOTIFICATION"_ns;
1585 break;
1586 default:
1587 sevStr = nsPrintfCString("<severity 0x%04x>", severity);
1588 break;
1591 printf_stderr("[KHR_debug: 0x%" PRIxPTR "] ID %u: %s, %s, %s:\n %s\n",
1592 (uintptr_t)this, id, sourceStr.BeginReading(),
1593 typeStr.BeginReading(), sevStr.BeginReading(), message);
1596 void GLContext::InitExtensions() {
1597 MOZ_GL_ASSERT(this, IsCurrent());
1599 std::vector<nsCString> driverExtensionList;
1601 [&]() {
1602 if (mSymbols.fGetStringi) {
1603 GLuint count = 0;
1604 if (GetPotentialInteger(LOCAL_GL_NUM_EXTENSIONS, (GLint*)&count)) {
1605 for (GLuint i = 0; i < count; i++) {
1606 // This is UTF-8.
1607 const char* rawExt = (const char*)fGetStringi(LOCAL_GL_EXTENSIONS, i);
1609 // We CANNOT use nsDependentCString here, because the spec doesn't
1610 // guarantee that the pointers returned are different, only that their
1611 // contents are. On Flame, each of these index string queries returns
1612 // the same address.
1613 driverExtensionList.push_back(nsCString(rawExt));
1615 return;
1619 const char* rawExts = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
1620 if (rawExts) {
1621 nsDependentCString exts(rawExts);
1622 SplitByChar(exts, ' ', &driverExtensionList);
1624 }();
1625 const auto err = fGetError();
1626 MOZ_ALWAYS_TRUE(!IsBadCallError(err));
1628 const bool shouldDumpExts = ShouldDumpExts();
1629 if (shouldDumpExts) {
1630 printf_stderr("%i GL driver extensions: (*: recognized)\n",
1631 (uint32_t)driverExtensionList.size());
1634 MarkBitfieldByStrings(driverExtensionList, shouldDumpExts, sExtensionNames,
1635 &mAvailableExtensions);
1637 if (WorkAroundDriverBugs()) {
1638 if (Vendor() == GLVendor::Qualcomm) {
1639 // Some Adreno drivers do not report GL_OES_EGL_sync, but they really do
1640 // support it.
1641 MarkExtensionSupported(OES_EGL_sync);
1644 if (Vendor() == GLVendor::ATI) {
1645 // ATI drivers say this extension exists, but we can't
1646 // actually find the EGLImageTargetRenderbufferStorageOES
1647 // extension function pointer in the drivers.
1648 MarkExtensionUnsupported(OES_EGL_image);
1651 if (Vendor() == GLVendor::Imagination && Renderer() == GLRenderer::SGX540) {
1652 // Bug 980048
1653 MarkExtensionUnsupported(OES_EGL_sync);
1656 #ifdef MOZ_WIDGET_ANDROID
1657 if (Vendor() == GLVendor::Imagination &&
1658 Renderer() == GLRenderer::SGX544MP && jni::GetAPIVersion() < 21) {
1659 // Bug 1026404
1660 MarkExtensionUnsupported(OES_EGL_image);
1661 MarkExtensionUnsupported(OES_EGL_image_external);
1663 #endif
1665 if (Vendor() == GLVendor::ARM && (Renderer() == GLRenderer::Mali400MP ||
1666 Renderer() == GLRenderer::Mali450MP)) {
1667 // Bug 1264505
1668 MarkExtensionUnsupported(OES_EGL_image_external);
1671 if (Renderer() == GLRenderer::AndroidEmulator) {
1672 // the Android emulator, which we use to run B2G reftests on,
1673 // doesn't expose the OES_rgb8_rgba8 extension, but it seems to
1674 // support it (tautologically, as it only runs on desktop GL).
1675 MarkExtensionSupported(OES_rgb8_rgba8);
1678 if (Vendor() == GLVendor::VMware &&
1679 Renderer() == GLRenderer::GalliumLlvmpipe) {
1680 // The llvmpipe driver that is used on linux try servers appears to have
1681 // buggy support for s3tc/dxt1 compressed textures.
1682 // See Bug 975824.
1683 MarkExtensionUnsupported(EXT_texture_compression_s3tc);
1684 MarkExtensionUnsupported(EXT_texture_compression_dxt1);
1685 MarkExtensionUnsupported(ANGLE_texture_compression_dxt3);
1686 MarkExtensionUnsupported(ANGLE_texture_compression_dxt5);
1689 #ifdef XP_MACOSX
1690 // Bug 1009642: On OSX Mavericks (10.9), the driver for Intel HD
1691 // 3000 appears to be buggy WRT updating sub-images of S3TC
1692 // textures with glCompressedTexSubImage2D. Works on Intel HD 4000
1693 // and Intel HD 5000/Iris that I tested.
1694 // Bug 1124996: Appears to be the same on OSX Yosemite (10.10)
1695 if (Renderer() == GLRenderer::IntelHD3000) {
1696 MarkExtensionUnsupported(EXT_texture_compression_s3tc);
1699 // OSX supports EXT_texture_sRGB in Legacy contexts, but not in Core
1700 // contexts. Though EXT_texture_sRGB was included into GL2.1, it *excludes*
1701 // the interactions with s3tc. Strictly speaking, you must advertize support
1702 // for EXT_texture_sRGB in order to allow for srgb+s3tc on desktop GL. The
1703 // omission of EXT_texture_sRGB in OSX Core contexts appears to be a bug.
1704 MarkExtensionSupported(EXT_texture_sRGB);
1705 #endif
1708 if (shouldDumpExts) {
1709 printf_stderr("\nActivated extensions:\n");
1711 for (size_t i = 0; i < mAvailableExtensions.size(); i++) {
1712 if (!mAvailableExtensions[i]) continue;
1714 const char* ext = sExtensionNames[i];
1715 printf_stderr("[%i] %s\n", (uint32_t)i, ext);
1720 void GLContext::PlatformStartup() {
1721 RegisterStrongMemoryReporter(new GfxTexturesReporter());
1724 // Common code for checking for both GL extensions and GLX extensions.
1725 bool GLContext::ListHasExtension(const GLubyte* extensions,
1726 const char* extension) {
1727 // fix bug 612572 - we were crashing as we were calling this function with
1728 // extensions==null
1729 if (extensions == nullptr || extension == nullptr) return false;
1731 const GLubyte* start;
1732 GLubyte* where;
1733 GLubyte* terminator;
1735 /* Extension names should not have spaces. */
1736 where = (GLubyte*)strchr(extension, ' ');
1737 if (where || *extension == '\0') return false;
1740 * It takes a bit of care to be fool-proof about parsing the
1741 * OpenGL extensions string. Don't be fooled by sub-strings,
1742 * etc.
1744 start = extensions;
1745 for (;;) {
1746 where = (GLubyte*)strstr((const char*)start, extension);
1747 if (!where) {
1748 break;
1750 terminator = where + strlen(extension);
1751 if (where == start || *(where - 1) == ' ') {
1752 if (*terminator == ' ' || *terminator == '\0') {
1753 return true;
1756 start = terminator;
1758 return false;
1761 bool GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus) {
1762 MOZ_ASSERT(fb);
1764 ScopedBindFramebuffer autoFB(this, fb);
1765 MOZ_GL_ASSERT(this, fIsFramebuffer(fb));
1767 GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
1768 if (pStatus) *pStatus = status;
1770 return status == LOCAL_GL_FRAMEBUFFER_COMPLETE;
1773 void GLContext::AttachBuffersToFB(GLuint colorTex, GLuint colorRB,
1774 GLuint depthRB, GLuint stencilRB, GLuint fb,
1775 GLenum target) {
1776 MOZ_ASSERT(fb);
1777 MOZ_ASSERT(!(colorTex && colorRB));
1779 ScopedBindFramebuffer autoFB(this, fb);
1780 MOZ_GL_ASSERT(this, fIsFramebuffer(fb)); // It only counts after being bound.
1782 if (colorTex) {
1783 MOZ_GL_ASSERT(this, fIsTexture(colorTex));
1784 MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
1785 target == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
1786 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1787 target, colorTex, 0);
1788 } else if (colorRB) {
1789 // On the Android 4.3 emulator, IsRenderbuffer may return false incorrectly.
1790 MOZ_GL_ASSERT(this, fIsRenderbuffer(colorRB) ||
1791 Renderer() == GLRenderer::AndroidEmulator);
1792 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1793 LOCAL_GL_RENDERBUFFER, colorRB);
1796 if (depthRB) {
1797 MOZ_GL_ASSERT(this, fIsRenderbuffer(depthRB) ||
1798 Renderer() == GLRenderer::AndroidEmulator);
1799 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
1800 LOCAL_GL_RENDERBUFFER, depthRB);
1803 if (stencilRB) {
1804 MOZ_GL_ASSERT(this, fIsRenderbuffer(stencilRB) ||
1805 Renderer() == GLRenderer::AndroidEmulator);
1806 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
1807 LOCAL_GL_RENDERBUFFER, stencilRB);
1811 bool GLContext::AssembleOffscreenFBs(const GLuint colorMSRB,
1812 const GLuint depthRB,
1813 const GLuint stencilRB,
1814 const GLuint texture, GLuint* drawFB_out,
1815 GLuint* readFB_out) {
1816 if (!colorMSRB && !texture) {
1817 MOZ_ASSERT(!depthRB && !stencilRB);
1819 if (drawFB_out) *drawFB_out = 0;
1820 if (readFB_out) *readFB_out = 0;
1822 return true;
1825 ScopedBindFramebuffer autoFB(this);
1827 GLuint drawFB = 0;
1828 GLuint readFB = 0;
1830 if (texture) {
1831 readFB = 0;
1832 fGenFramebuffers(1, &readFB);
1833 BindFB(readFB);
1834 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1835 LOCAL_GL_TEXTURE_2D, texture, 0);
1838 if (colorMSRB) {
1839 drawFB = 0;
1840 fGenFramebuffers(1, &drawFB);
1841 BindFB(drawFB);
1842 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
1843 LOCAL_GL_RENDERBUFFER, colorMSRB);
1844 } else {
1845 drawFB = readFB;
1847 MOZ_ASSERT(GetIntAs<GLuint>(LOCAL_GL_FRAMEBUFFER_BINDING) == drawFB);
1849 if (depthRB) {
1850 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
1851 LOCAL_GL_RENDERBUFFER, depthRB);
1854 if (stencilRB) {
1855 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
1856 LOCAL_GL_RENDERBUFFER, stencilRB);
1859 // We should be all resized. Check for framebuffer completeness.
1860 GLenum status;
1861 bool isComplete = true;
1863 if (!IsFramebufferComplete(drawFB, &status)) {
1864 NS_WARNING("DrawFBO: Incomplete");
1865 #ifdef MOZ_GL_DEBUG_BUILD
1866 if (ShouldSpew()) {
1867 printf_stderr("Framebuffer status: %X\n", status);
1869 #endif
1870 isComplete = false;
1873 if (!IsFramebufferComplete(readFB, &status)) {
1874 NS_WARNING("ReadFBO: Incomplete");
1875 #ifdef MOZ_GL_DEBUG_BUILD
1876 if (ShouldSpew()) {
1877 printf_stderr("Framebuffer status: %X\n", status);
1879 #endif
1880 isComplete = false;
1883 if (drawFB_out) {
1884 *drawFB_out = drawFB;
1885 } else if (drawFB) {
1886 MOZ_CRASH("drawFB created when not requested!");
1889 if (readFB_out) {
1890 *readFB_out = readFB;
1891 } else if (readFB) {
1892 MOZ_CRASH("readFB created when not requested!");
1895 return isComplete;
1898 void GLContext::MarkDestroyed() {
1899 if (IsDestroyed()) return;
1901 OnMarkDestroyed();
1903 // Null these before they're naturally nulled after dtor, as we want GLContext
1904 // to still be alive in *their* dtors.
1905 mBlitHelper = nullptr;
1906 mReadTexImageHelper = nullptr;
1908 mContextLost = true;
1909 mSymbols = {};
1912 // -
1914 #ifdef MOZ_GL_DEBUG_BUILD
1915 /* static */
1916 void GLContext::AssertNotPassingStackBufferToTheGL(const void* ptr) {
1917 int somethingOnTheStack;
1918 const void* someStackPtr = &somethingOnTheStack;
1919 const int page_bits = 12;
1920 intptr_t page = reinterpret_cast<uintptr_t>(ptr) >> page_bits;
1921 intptr_t someStackPage =
1922 reinterpret_cast<uintptr_t>(someStackPtr) >> page_bits;
1923 uintptr_t pageDistance = std::abs(page - someStackPage);
1925 // Explanation for the "distance <= 1" check here as opposed to just
1926 // an equality check.
1928 // Here we assume that pages immediately adjacent to the someStackAddress
1929 // page, are also stack pages. That allows to catch the case where the calling
1930 // frame put a buffer on the stack, and we just crossed the page boundary.
1931 // That is likely to happen, precisely, when using stack arrays. I hit that
1932 // specifically with CompositorOGL::Initialize.
1934 // In theory we could be unlucky and wrongly assert here. If that happens,
1935 // it will only affect debug builds, and looking at stacks we'll be able to
1936 // see that this assert is wrong and revert to the conservative and safe
1937 // approach of only asserting when address and someStackAddress are
1938 // on the same page.
1939 bool isStackAddress = pageDistance <= 1;
1940 MOZ_ASSERT(!isStackAddress,
1941 "Please don't pass stack arrays to the GL. "
1942 "Consider using HeapCopyOfStackArray. "
1943 "See bug 1005658.");
1946 void GLContext::CreatedProgram(GLContext* aOrigin, GLuint aName) {
1947 mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName));
1950 void GLContext::CreatedShader(GLContext* aOrigin, GLuint aName) {
1951 mTrackedShaders.AppendElement(NamedResource(aOrigin, aName));
1954 void GLContext::CreatedBuffers(GLContext* aOrigin, GLsizei aCount,
1955 GLuint* aNames) {
1956 for (GLsizei i = 0; i < aCount; ++i) {
1957 mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1961 void GLContext::CreatedQueries(GLContext* aOrigin, GLsizei aCount,
1962 GLuint* aNames) {
1963 for (GLsizei i = 0; i < aCount; ++i) {
1964 mTrackedQueries.AppendElement(NamedResource(aOrigin, aNames[i]));
1968 void GLContext::CreatedTextures(GLContext* aOrigin, GLsizei aCount,
1969 GLuint* aNames) {
1970 for (GLsizei i = 0; i < aCount; ++i) {
1971 mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i]));
1975 void GLContext::CreatedFramebuffers(GLContext* aOrigin, GLsizei aCount,
1976 GLuint* aNames) {
1977 for (GLsizei i = 0; i < aCount; ++i) {
1978 mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1982 void GLContext::CreatedRenderbuffers(GLContext* aOrigin, GLsizei aCount,
1983 GLuint* aNames) {
1984 for (GLsizei i = 0; i < aCount; ++i) {
1985 mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
1989 static void RemoveNamesFromArray(GLContext* aOrigin, GLsizei aCount,
1990 const GLuint* aNames,
1991 nsTArray<GLContext::NamedResource>& aArray) {
1992 for (GLsizei j = 0; j < aCount; ++j) {
1993 GLuint name = aNames[j];
1994 // name 0 can be ignored
1995 if (name == 0) continue;
1997 for (uint32_t i = 0; i < aArray.Length(); ++i) {
1998 if (aArray[i].name == name) {
1999 aArray.RemoveElementAt(i);
2000 break;
2006 void GLContext::DeletedProgram(GLContext* aOrigin, GLuint aName) {
2007 RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms);
2010 void GLContext::DeletedShader(GLContext* aOrigin, GLuint aName) {
2011 RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders);
2014 void GLContext::DeletedBuffers(GLContext* aOrigin, GLsizei aCount,
2015 const GLuint* aNames) {
2016 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers);
2019 void GLContext::DeletedQueries(GLContext* aOrigin, GLsizei aCount,
2020 const GLuint* aNames) {
2021 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedQueries);
2024 void GLContext::DeletedTextures(GLContext* aOrigin, GLsizei aCount,
2025 const GLuint* aNames) {
2026 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures);
2029 void GLContext::DeletedFramebuffers(GLContext* aOrigin, GLsizei aCount,
2030 const GLuint* aNames) {
2031 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers);
2034 void GLContext::DeletedRenderbuffers(GLContext* aOrigin, GLsizei aCount,
2035 const GLuint* aNames) {
2036 RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers);
2039 static void MarkContextDestroyedInArray(
2040 GLContext* aContext, nsTArray<GLContext::NamedResource>& aArray) {
2041 for (uint32_t i = 0; i < aArray.Length(); ++i) {
2042 if (aArray[i].origin == aContext) aArray[i].originDeleted = true;
2046 void GLContext::SharedContextDestroyed(GLContext* aChild) {
2047 MarkContextDestroyedInArray(aChild, mTrackedPrograms);
2048 MarkContextDestroyedInArray(aChild, mTrackedShaders);
2049 MarkContextDestroyedInArray(aChild, mTrackedTextures);
2050 MarkContextDestroyedInArray(aChild, mTrackedFramebuffers);
2051 MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers);
2052 MarkContextDestroyedInArray(aChild, mTrackedBuffers);
2053 MarkContextDestroyedInArray(aChild, mTrackedQueries);
2056 static void ReportArrayContents(
2057 const char* title, const nsTArray<GLContext::NamedResource>& aArray) {
2058 if (aArray.Length() == 0) return;
2060 printf_stderr("%s:\n", title);
2062 nsTArray<GLContext::NamedResource> copy(aArray.Clone());
2063 copy.Sort();
2065 GLContext* lastContext = nullptr;
2066 for (uint32_t i = 0; i < copy.Length(); ++i) {
2067 if (lastContext != copy[i].origin) {
2068 if (lastContext) printf_stderr("\n");
2069 printf_stderr(" [%p - %s] ", copy[i].origin,
2070 copy[i].originDeleted ? "deleted" : "live");
2071 lastContext = copy[i].origin;
2073 printf_stderr("%d ", copy[i].name);
2075 printf_stderr("\n");
2078 void GLContext::ReportOutstandingNames() {
2079 if (!ShouldSpew()) return;
2081 printf_stderr("== GLContext %p Outstanding ==\n", this);
2083 ReportArrayContents("Outstanding Textures", mTrackedTextures);
2084 ReportArrayContents("Outstanding Buffers", mTrackedBuffers);
2085 ReportArrayContents("Outstanding Queries", mTrackedQueries);
2086 ReportArrayContents("Outstanding Programs", mTrackedPrograms);
2087 ReportArrayContents("Outstanding Shaders", mTrackedShaders);
2088 ReportArrayContents("Outstanding Framebuffers", mTrackedFramebuffers);
2089 ReportArrayContents("Outstanding Renderbuffers", mTrackedRenderbuffers);
2092 #endif // ifdef MOZ_GL_DEBUG_BUILD
2094 bool GLContext::IsOffscreenSizeAllowed(const IntSize& aSize) const {
2095 int32_t biggerDimension = std::max(aSize.width, aSize.height);
2096 int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize);
2097 return biggerDimension <= maxAllowed;
2100 bool GLContext::IsValidOwningThread() const {
2101 if (!mOwningThreadId) return true; // Free for all!
2102 return PlatformThread::CurrentId() == *mOwningThreadId;
2105 GLBlitHelper* GLContext::BlitHelper() {
2106 if (!mBlitHelper) {
2107 mBlitHelper.reset(new GLBlitHelper(this));
2110 return mBlitHelper.get();
2113 GLReadTexImageHelper* GLContext::ReadTexImageHelper() {
2114 if (!mReadTexImageHelper) {
2115 mReadTexImageHelper = MakeUnique<GLReadTexImageHelper>(this);
2118 return mReadTexImageHelper.get();
2121 void GLContext::FlushIfHeavyGLCallsSinceLastFlush() {
2122 if (!mHeavyGLCallsSinceLastFlush) {
2123 return;
2125 if (MakeCurrent()) {
2126 fFlush();
2130 /*static*/
2131 bool GLContext::ShouldDumpExts() { return gfxEnv::MOZ_GL_DUMP_EXTS(); }
2133 bool DoesStringMatch(const char* aString, const char* aWantedString) {
2134 if (!aString || !aWantedString) return false;
2136 const char* occurrence = strstr(aString, aWantedString);
2138 // aWanted not found
2139 if (!occurrence) return false;
2141 // aWantedString preceded by alpha character
2142 if (occurrence != aString && isalpha(*(occurrence - 1))) return false;
2144 // aWantedVendor followed by alpha character
2145 const char* afterOccurrence = occurrence + strlen(aWantedString);
2146 if (isalpha(*afterOccurrence)) return false;
2148 return true;
2151 /*static*/
2152 bool GLContext::ShouldSpew() { return gfxEnv::MOZ_GL_SPEW(); }
2154 void SplitByChar(const nsACString& str, const char delim,
2155 std::vector<nsCString>* const out) {
2156 uint32_t start = 0;
2157 while (true) {
2158 int32_t end = str.FindChar(' ', start);
2159 if (end == -1) break;
2161 uint32_t len = (uint32_t)end - start;
2162 nsDependentCSubstring substr(str, start, len);
2163 out->push_back(nsCString(substr));
2165 start = end + 1;
2168 nsDependentCSubstring substr(str, start);
2169 out->push_back(nsCString(substr));
2172 void GLContext::fCopyTexImage2D(GLenum target, GLint level,
2173 GLenum internalformat, GLint x, GLint y,
2174 GLsizei width, GLsizei height, GLint border) {
2175 if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
2176 // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2177 // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2178 level = -1;
2179 width = -1;
2180 height = -1;
2181 border = -1;
2184 BeforeGLReadCall();
2185 raw_fCopyTexImage2D(target, level, internalformat, x, y, width, height,
2186 border);
2187 AfterGLReadCall();
2190 void GLContext::fGetIntegerv(const GLenum pname, GLint* const params) const {
2191 const auto AssertBinding = [&](const char* const name, const GLenum binding,
2192 const GLuint expected) {
2193 if (MOZ_LIKELY(!mDebugFlags)) return;
2194 GLuint actual = 0;
2195 raw_fGetIntegerv(binding, (GLint*)&actual);
2196 if (actual != expected) {
2197 gfxCriticalError() << "Misprediction: " << name << " expected "
2198 << expected << ", was " << actual;
2202 switch (pname) {
2203 case LOCAL_GL_MAX_TEXTURE_SIZE:
2204 MOZ_ASSERT(mMaxTextureSize > 0);
2205 *params = mMaxTextureSize;
2206 return;
2208 case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
2209 MOZ_ASSERT(mMaxCubeMapTextureSize > 0);
2210 *params = mMaxCubeMapTextureSize;
2211 return;
2213 case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
2214 MOZ_ASSERT(mMaxRenderbufferSize > 0);
2215 *params = mMaxRenderbufferSize;
2216 return;
2218 case LOCAL_GL_VIEWPORT:
2219 for (size_t i = 0; i < 4; i++) {
2220 params[i] = mViewportRect[i];
2222 return;
2224 case LOCAL_GL_SCISSOR_BOX:
2225 for (size_t i = 0; i < 4; i++) {
2226 params[i] = mScissorRect[i];
2228 return;
2230 case LOCAL_GL_DRAW_FRAMEBUFFER_BINDING:
2231 if (mElideDuplicateBindFramebuffers) {
2232 static_assert(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING ==
2233 LOCAL_GL_FRAMEBUFFER_BINDING);
2234 AssertBinding("GL_DRAW_FRAMEBUFFER_BINDING",
2235 LOCAL_GL_DRAW_FRAMEBUFFER_BINDING, mCachedDrawFb);
2236 *params = static_cast<GLint>(mCachedDrawFb);
2237 return;
2239 break;
2241 case LOCAL_GL_READ_FRAMEBUFFER_BINDING:
2242 if (mElideDuplicateBindFramebuffers) {
2243 if (IsSupported(GLFeature::framebuffer_blit)) {
2244 AssertBinding("GL_READ_FRAMEBUFFER_BINDING",
2245 LOCAL_GL_READ_FRAMEBUFFER_BINDING, mCachedReadFb);
2247 *params = static_cast<GLint>(mCachedReadFb);
2248 return;
2250 break;
2252 default:
2253 break;
2255 raw_fGetIntegerv(pname, params);
2258 void GLContext::fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
2259 GLenum format, GLenum type, GLvoid* pixels) {
2260 BeforeGLReadCall();
2261 raw_fReadPixels(x, y, width, height, format, type, pixels);
2262 AfterGLReadCall();
2264 // Check if GL is giving back 1.0 alpha for
2265 // RGBA reads to RGBA images from no-alpha buffers.
2266 #ifdef XP_MACOSX
2267 if (WorkAroundDriverBugs() && Vendor() == gl::GLVendor::NVIDIA &&
2268 format == LOCAL_GL_RGBA && type == LOCAL_GL_UNSIGNED_BYTE &&
2269 !IsCoreProfile() && width && height) {
2270 GLint alphaBits = 0;
2271 fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits);
2272 if (!alphaBits) {
2273 const uint32_t alphaMask = 0xff000000;
2275 uint32_t* itr = (uint32_t*)pixels;
2276 uint32_t testPixel = *itr;
2277 if ((testPixel & alphaMask) != alphaMask) {
2278 // We need to set the alpha channel to 1.0 manually.
2279 uint32_t* itrEnd =
2280 itr + width * height; // Stride is guaranteed to be width*4.
2282 for (; itr != itrEnd; itr++) {
2283 *itr |= alphaMask;
2288 #endif
2291 void GLContext::fDeleteFramebuffers(GLsizei n, const GLuint* names) {
2292 // Avoid crash by flushing before glDeleteFramebuffers. See bug 1194923.
2293 if (mNeedsFlushBeforeDeleteFB) {
2294 fFlush();
2297 if (n == 1 && *names == 0) {
2298 // Deleting framebuffer 0 causes hangs on the DROID. See bug 623228.
2299 } else {
2300 raw_fDeleteFramebuffers(n, names);
2302 TRACKING_CONTEXT(DeletedFramebuffers(this, n, names));
2305 #ifdef MOZ_WIDGET_ANDROID
2307 * Conservatively estimate whether there is enough available
2308 * contiguous virtual address space to map a newly allocated texture.
2310 static bool WillTextureMapSucceed(GLsizei width, GLsizei height, GLenum format,
2311 GLenum type) {
2312 bool willSucceed = false;
2313 // Some drivers leave large gaps between textures, so require
2314 // there to be double the actual size of the texture available.
2315 size_t size = width * height * GetBytesPerTexel(format, type) * 2;
2317 void* p = mmap(nullptr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
2318 if (p != MAP_FAILED) {
2319 willSucceed = true;
2320 munmap(p, size);
2323 return willSucceed;
2325 #endif // MOZ_WIDGET_ANDROID
2327 void GLContext::fTexImage2D(GLenum target, GLint level, GLint internalformat,
2328 GLsizei width, GLsizei height, GLint border,
2329 GLenum format, GLenum type, const GLvoid* pixels) {
2330 if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
2331 // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2332 // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2333 level = -1;
2334 width = -1;
2335 height = -1;
2336 border = -1;
2338 #if MOZ_WIDGET_ANDROID
2339 if (mTextureAllocCrashesOnMapFailure) {
2340 // We have no way of knowing whether this texture already has
2341 // storage allocated for it, and therefore whether this check
2342 // is necessary. We must therefore assume it does not and
2343 // always perform the check.
2344 if (!WillTextureMapSucceed(width, height, internalformat, type)) {
2345 return;
2348 #endif
2349 raw_fTexImage2D(target, level, internalformat, width, height, border, format,
2350 type, pixels);
2353 UniquePtr<Texture> CreateTexture(GLContext& gl, const gfx::IntSize& size) {
2354 const GLenum target = LOCAL_GL_TEXTURE_2D;
2355 const GLenum format = LOCAL_GL_RGBA;
2357 auto tex = MakeUnique<Texture>(gl);
2358 ScopedBindTexture autoTex(&gl, tex->name, target);
2360 gl.fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
2361 gl.fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
2362 gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
2363 gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
2365 gl.fTexImage2D(target, 0, format, size.width, size.height, 0, format,
2366 LOCAL_GL_UNSIGNED_BYTE, nullptr);
2368 return tex;
2371 uint32_t GetBytesPerTexel(GLenum format, GLenum type) {
2372 // If there is no defined format or type, we're not taking up any memory
2373 if (!format || !type) {
2374 return 0;
2377 if (format == LOCAL_GL_DEPTH_COMPONENT) {
2378 if (type == LOCAL_GL_UNSIGNED_SHORT)
2379 return 2;
2380 else if (type == LOCAL_GL_UNSIGNED_INT)
2381 return 4;
2382 } else if (format == LOCAL_GL_DEPTH_STENCIL) {
2383 if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT) return 4;
2386 if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT ||
2387 type == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV) {
2388 uint32_t multiplier = type == LOCAL_GL_UNSIGNED_BYTE ? 1 : 4;
2389 switch (format) {
2390 case LOCAL_GL_ALPHA:
2391 case LOCAL_GL_LUMINANCE:
2392 case LOCAL_GL_R8:
2393 return 1 * multiplier;
2394 case LOCAL_GL_LUMINANCE_ALPHA:
2395 case LOCAL_GL_R16:
2396 return 2 * multiplier;
2397 case LOCAL_GL_RGB:
2398 return 3 * multiplier;
2399 case LOCAL_GL_RGBA:
2400 case LOCAL_GL_BGRA_EXT:
2401 return 4 * multiplier;
2402 default:
2403 break;
2405 } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
2406 type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
2407 type == LOCAL_GL_UNSIGNED_SHORT_5_6_5 ||
2408 type == LOCAL_GL_UNSIGNED_SHORT) {
2409 return 2;
2412 gfxCriticalError() << "Unknown texture type " << type << " or format "
2413 << format;
2414 return 0;
2417 bool GLContext::MakeCurrent(bool aForce) const {
2418 if (MOZ_UNLIKELY(IsContextLost())) return false;
2420 if (MOZ_LIKELY(!aForce)) {
2421 bool isCurrent;
2422 if (mUseTLSIsCurrent) {
2423 isCurrent = (sCurrentContext.get() == reinterpret_cast<uintptr_t>(this));
2424 } else {
2425 isCurrent = IsCurrentImpl();
2427 if (MOZ_LIKELY(isCurrent)) {
2428 MOZ_ASSERT(IsCurrentImpl() ||
2429 !MakeCurrentImpl()); // Might have lost context.
2430 return true;
2433 if (!IsValidOwningThread()) {
2434 gfxCriticalError() << "MakeCurrent called on a thread other than the"
2435 << " creating thread!";
2436 if (gfxEnv::MOZ_GL_RELEASE_ASSERT_CONTEXT_OWNERSHIP()) {
2437 MOZ_CRASH("MOZ_GL_RELEASE_ASSERT_CONTEXT_OWNERSHIP");
2440 if (!MakeCurrentImpl()) return false;
2442 sCurrentContext.set(reinterpret_cast<uintptr_t>(this));
2443 return true;
2446 void GLContext::ResetSyncCallCount(const char* resetReason) const {
2447 if (ShouldSpew()) {
2448 printf_stderr("On %s, mSyncGLCallCount = %" PRIu64 "\n", resetReason,
2449 mSyncGLCallCount);
2452 mSyncGLCallCount = 0;
2455 // -
2457 bool CheckContextLost(const GLContext* const gl) {
2458 return gl->CheckContextLost();
2461 // -
2463 GLenum GLContext::GetError() const {
2464 if (mContextLost) return LOCAL_GL_CONTEXT_LOST;
2466 if (mImplicitMakeCurrent) {
2467 (void)MakeCurrent();
2470 const auto fnGetError = [&]() {
2471 const auto ret = mSymbols.fGetError();
2472 if (ret == LOCAL_GL_CONTEXT_LOST) {
2473 OnContextLostError();
2474 mTopError = ret; // Promote to top!
2476 return ret;
2479 auto ret = fnGetError();
2482 auto flushedErr = ret;
2483 uint32_t i = 1;
2484 while (flushedErr && !mContextLost) {
2485 if (i == 100) {
2486 gfxCriticalError() << "Flushing glGetError still "
2487 << gfx::hexa(flushedErr) << " after " << i
2488 << " calls.";
2489 break;
2491 flushedErr = fnGetError();
2492 i += 1;
2496 if (mTopError) {
2497 ret = mTopError;
2498 mTopError = 0;
2501 if (mDebugFlags & DebugFlagTrace) {
2502 const auto errStr = GLErrorToString(ret);
2503 printf_stderr("[gl:%p] GetError() -> %s\n", this, errStr.c_str());
2505 return ret;
2508 GLenum GLContext::fGetGraphicsResetStatus() const {
2509 OnSyncCall();
2511 GLenum ret = 0;
2512 if (mSymbols.fGetGraphicsResetStatus) {
2513 if (mImplicitMakeCurrent) {
2514 (void)MakeCurrent();
2516 ret = mSymbols.fGetGraphicsResetStatus();
2517 } else {
2518 if (!MakeCurrent(true)) {
2519 ret = LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB;
2523 if (mDebugFlags & DebugFlagTrace) {
2524 printf_stderr("[gl:%p] GetGraphicsResetStatus() -> 0x%04x\n", this, ret);
2527 return ret;
2530 void GLContext::OnContextLostError() const {
2531 if (mDebugFlags & DebugFlagTrace) {
2532 printf_stderr("[gl:%p] CONTEXT_LOST\n", this);
2534 mContextLost = true;
2537 // --
2539 /*static*/ std::string GLContext::GLErrorToString(const GLenum err) {
2540 switch (err) {
2541 case LOCAL_GL_NO_ERROR:
2542 return "GL_NO_ERROR";
2543 case LOCAL_GL_INVALID_ENUM:
2544 return "GL_INVALID_ENUM";
2545 case LOCAL_GL_INVALID_VALUE:
2546 return "GL_INVALID_VALUE";
2547 case LOCAL_GL_INVALID_OPERATION:
2548 return "GL_INVALID_OPERATION";
2549 case LOCAL_GL_STACK_OVERFLOW:
2550 return "GL_STACK_OVERFLOW";
2551 case LOCAL_GL_STACK_UNDERFLOW:
2552 return "GL_STACK_UNDERFLOW";
2553 case LOCAL_GL_OUT_OF_MEMORY:
2554 return "GL_OUT_OF_MEMORY";
2555 case LOCAL_GL_TABLE_TOO_LARGE:
2556 return "GL_TABLE_TOO_LARGE";
2557 case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
2558 return "GL_INVALID_FRAMEBUFFER_OPERATION";
2559 case LOCAL_GL_CONTEXT_LOST:
2560 return "GL_CONTEXT_LOST";
2563 const nsPrintfCString hex("<enum 0x%04x>", err);
2564 return hex.BeginReading();
2567 // --
2569 void GLContext::BeforeGLCall_Debug(const char* const funcName) const {
2570 MOZ_ASSERT(mDebugFlags);
2572 if (mDebugFlags & DebugFlagTrace) {
2573 printf_stderr("[gl:%p] > %s\n", this, funcName);
2576 MOZ_ASSERT(!mDebugErrorScope);
2577 mDebugErrorScope.reset(new LocalErrorScope(*this));
2580 void GLContext::AfterGLCall_Debug(const char* const funcName) const {
2581 MOZ_ASSERT(mDebugFlags);
2583 // calling fFinish() immediately after every GL call makes sure that if this
2584 // GL command crashes, the stack trace will actually point to it. Otherwise,
2585 // OpenGL being an asynchronous API, stack traces tend to be meaningless
2586 mSymbols.fFinish();
2588 const auto err = mDebugErrorScope->GetError();
2589 mDebugErrorScope = nullptr;
2590 if (!mTopError) {
2591 mTopError = err;
2594 if (mDebugFlags & DebugFlagTrace) {
2595 printf_stderr("[gl:%p] < %s [%s]\n", this, funcName,
2596 GLErrorToString(err).c_str());
2599 if (err && !mLocalErrorScopeStack.size()) {
2600 const auto errStr = GLErrorToString(err);
2601 const auto text = nsPrintfCString("%s: Generated unexpected %s error",
2602 funcName, errStr.c_str());
2603 printf_stderr("[gl:%p] %s.\n", this, text.BeginReading());
2605 const bool abortOnError = mDebugFlags & DebugFlagAbortOnError;
2606 if (abortOnError && err != LOCAL_GL_CONTEXT_LOST) {
2607 gfxCriticalErrorOnce() << text.BeginReading();
2608 MOZ_CRASH(
2609 "Aborting... (Run with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)");
2614 /*static*/
2615 void GLContext::OnImplicitMakeCurrentFailure(const char* const funcName) {
2616 gfxCriticalError() << "Ignoring call to " << funcName << " with failed"
2617 << " mImplicitMakeCurrent.";
2620 bool GLContext::CreateOffscreenDefaultFb(const gfx::IntSize& size) {
2621 mOffscreenDefaultFb = MozFramebuffer::Create(this, size, 0, true);
2622 return bool(mOffscreenDefaultFb);
2625 // Some of Mesa's drivers allocate heap memory when loaded and don't
2626 // free it when unloaded; this causes Leak Sanitizer to detect leaks and
2627 // fail to unwind the stack, so suppressions don't work. This
2628 // workaround leaks a reference to the driver library so that it's never
2629 // unloaded. Because the leak isn't significant for real usage, only
2630 // ASan runs in CI, this is applied only to the software renderer.
2632 // See bug 1702394 for more details.
2633 void MesaMemoryLeakWorkaround() {
2634 #if defined(XP_LINUX) && !defined(ANDROID)
2635 Maybe<nsAutoCString> foundPath;
2637 dl_iterate_phdr(
2638 [](dl_phdr_info* info, size_t size, void* data) {
2639 auto& foundPath = *reinterpret_cast<Maybe<nsAutoCString>*>(data);
2640 nsDependentCString thisPath(info->dlpi_name);
2641 if (StringEndsWith(thisPath, "/swrast_dri.so"_ns)) {
2642 foundPath.emplace(thisPath);
2643 return 1;
2645 return 0;
2647 &foundPath);
2649 if (foundPath) {
2650 // Deliberately leak to prevent unload
2651 Unused << dlopen(foundPath->get(), RTLD_LAZY);
2653 #endif // XP_LINUX but not ANDROID
2656 } /* namespace gl */
2657 } /* namespace mozilla */