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