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