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