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 #ifdef MOZ_WIDGET_ANDROID
60 # include "mozilla/jni/Utils.h"
66 using namespace mozilla::gfx
;
67 using namespace mozilla::layers
;
69 // Zero-initialized after init().
70 MOZ_THREAD_LOCAL(const GLContext
*) GLContext::sCurrentContext
;
72 // If adding defines, don't forget to undefine symbols. See #undef block below.
74 #define CORE_SYMBOL(x) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x }} }
75 #define CORE_EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x, "gl" #x #y, "gl" #x #z }} }
76 #define EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x #y, "gl" #x #z }} }
77 #define EXT_SYMBOL3(x,y,z,w) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x #y, "gl" #x #z, "gl" #x #w }} }
78 #define END_SYMBOLS { nullptr, {} }
81 // should match the order of GLExtensions, and be null-terminated.
82 static const char* const sExtensionNames
[] = {
84 "GL_AMD_compressed_ATC_texture",
85 "GL_ANGLE_depth_texture",
86 "GL_ANGLE_framebuffer_blit",
87 "GL_ANGLE_framebuffer_multisample",
88 "GL_ANGLE_instanced_arrays",
90 "GL_ANGLE_provoking_vertex",
91 "GL_ANGLE_texture_compression_dxt3",
92 "GL_ANGLE_texture_compression_dxt5",
93 "GL_ANGLE_timer_query",
94 "GL_APPLE_client_storage",
96 "GL_APPLE_framebuffer_multisample",
98 "GL_APPLE_texture_range",
99 "GL_APPLE_vertex_array_object",
100 "GL_ARB_ES2_compatibility",
101 "GL_ARB_ES3_compatibility",
102 "GL_ARB_color_buffer_float",
103 "GL_ARB_compatibility",
104 "GL_ARB_copy_buffer",
105 "GL_ARB_depth_texture",
106 "GL_ARB_draw_buffers",
107 "GL_ARB_draw_instanced",
108 "GL_ARB_framebuffer_object",
109 "GL_ARB_framebuffer_sRGB",
110 "GL_ARB_geometry_shader4",
111 "GL_ARB_half_float_pixel",
112 "GL_ARB_instanced_arrays",
113 "GL_ARB_internalformat_query",
114 "GL_ARB_invalidate_subdata",
115 "GL_ARB_map_buffer_range",
116 "GL_ARB_occlusion_query2",
117 "GL_ARB_pixel_buffer_object",
118 "GL_ARB_provoking_vertex",
119 "GL_ARB_robust_buffer_access_behavior",
121 "GL_ARB_sampler_objects",
122 "GL_ARB_seamless_cube_map",
123 "GL_ARB_shader_texture_lod",
125 "GL_ARB_texture_compression",
126 "GL_ARB_texture_compression_bptc",
127 "GL_ARB_texture_compression_rgtc",
128 "GL_ARB_texture_float",
129 "GL_ARB_texture_non_power_of_two",
130 "GL_ARB_texture_rectangle",
132 "GL_ARB_texture_storage",
133 "GL_ARB_texture_swizzle",
134 "GL_ARB_timer_query",
135 "GL_ARB_transform_feedback2",
136 "GL_ARB_uniform_buffer_object",
137 "GL_ARB_vertex_array_object",
138 "GL_CHROMIUM_color_buffer_float_rgb",
139 "GL_CHROMIUM_color_buffer_float_rgba",
141 "GL_EXT_blend_minmax",
142 "GL_EXT_color_buffer_float",
143 "GL_EXT_color_buffer_half_float",
144 "GL_EXT_copy_texture",
145 "GL_EXT_disjoint_timer_query",
146 "GL_EXT_draw_buffers",
147 "GL_EXT_draw_buffers2",
148 "GL_EXT_draw_instanced",
149 "GL_EXT_float_blend",
151 "GL_EXT_framebuffer_blit",
152 "GL_EXT_framebuffer_multisample",
153 "GL_EXT_framebuffer_object",
154 "GL_EXT_framebuffer_sRGB",
155 "GL_EXT_gpu_shader4",
156 "GL_EXT_map_buffer_range",
157 "GL_EXT_multisampled_render_to_texture",
158 "GL_EXT_occlusion_query_boolean",
159 "GL_EXT_packed_depth_stencil",
160 "GL_EXT_provoking_vertex",
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()) {}
290 GLContext::~GLContext() {
293 "GLContext implementation must call MarkDestroyed in destructor!");
294 #ifdef MOZ_GL_DEBUG_BUILD
295 if (mSharedContext
) {
296 GLContext
* tip
= mSharedContext
;
297 while (tip
->mSharedContext
) tip
= tip
->mSharedContext
;
298 tip
->SharedContextDestroyed(this);
299 tip
->ReportOutstandingNames();
301 ReportOutstandingNames();
304 // Ensure we clear sCurrentContext if we were the last context set and avoid
305 // the memory getting reused.
306 if (sCurrentContext
.init() && sCurrentContext
.get() == this) {
307 sCurrentContext
.set(nullptr);
312 void GLContext::InvalidateCurrentContext() {
313 if (sCurrentContext
.init()) {
314 sCurrentContext
.set(nullptr);
319 void GLContext::StaticDebugCallback(GLenum source
, GLenum type
, GLuint id
,
320 GLenum severity
, GLsizei length
,
321 const GLchar
* message
,
322 const GLvoid
* userParam
) {
323 GLContext
* gl
= (GLContext
*)userParam
;
324 gl
->DebugCallback(source
, type
, id
, severity
, length
, message
);
327 bool GLContext::Init() {
328 MOZ_RELEASE_ASSERT(!mSymbols
.fBindFramebuffer
,
329 "GFX: GLContext::Init should only be called once.");
331 ScopedGfxFeatureReporter
reporter("GL Context");
334 // If initialization fails, zero the symbols to avoid hard-to-understand
337 NS_WARNING("GLContext::InitWithPrefix failed!");
341 reporter
.SetSuccessful();
345 static bool LoadSymbolsWithDesc(const SymbolLoader
& loader
,
346 const SymLoadStruct
* list
, const char* desc
) {
347 const auto warnOnFailure
= bool(desc
);
348 if (loader
.LoadSymbols(list
, warnOnFailure
)) return true;
353 const nsPrintfCString
err("Failed to load symbols for %s.", desc
);
354 NS_ERROR(err
.BeginReading());
359 bool GLContext::LoadExtSymbols(const SymbolLoader
& loader
,
360 const SymLoadStruct
* list
, GLExtensions ext
) {
361 const char* extName
= sExtensionNames
[size_t(ext
)];
362 if (!LoadSymbolsWithDesc(loader
, list
, extName
)) {
363 MarkExtensionUnsupported(ext
);
369 bool GLContext::LoadFeatureSymbols(const SymbolLoader
& loader
,
370 const SymLoadStruct
* list
,
372 const char* featureName
= GetFeatureName(feature
);
373 if (!LoadSymbolsWithDesc(loader
, list
, featureName
)) {
374 MarkUnsupported(feature
);
380 bool GLContext::InitImpl() {
381 if (!MakeCurrent(true)) return false;
383 const auto loader
= GetSymbolLoader();
384 if (!loader
) return false;
386 const auto fnLoadSymbols
= [&](const SymLoadStruct
* const list
,
387 const char* const desc
) {
388 return LoadSymbolsWithDesc(*loader
, list
, desc
);
392 const SymLoadStruct coreSymbols
[] = {
393 { (PRFuncPtr
*) &mSymbols
.fActiveTexture
, {{ "glActiveTexture", "glActiveTextureARB" }} },
394 { (PRFuncPtr
*) &mSymbols
.fAttachShader
, {{ "glAttachShader", "glAttachShaderARB" }} },
395 { (PRFuncPtr
*) &mSymbols
.fBindAttribLocation
, {{ "glBindAttribLocation", "glBindAttribLocationARB" }} },
396 { (PRFuncPtr
*) &mSymbols
.fBindBuffer
, {{ "glBindBuffer", "glBindBufferARB" }} },
397 { (PRFuncPtr
*) &mSymbols
.fBindTexture
, {{ "glBindTexture", "glBindTextureARB" }} },
398 { (PRFuncPtr
*) &mSymbols
.fBlendColor
, {{ "glBlendColor" }} },
399 { (PRFuncPtr
*) &mSymbols
.fBlendEquation
, {{ "glBlendEquation" }} },
400 { (PRFuncPtr
*) &mSymbols
.fBlendEquationSeparate
, {{ "glBlendEquationSeparate", "glBlendEquationSeparateEXT" }} },
401 { (PRFuncPtr
*) &mSymbols
.fBlendFunc
, {{ "glBlendFunc" }} },
402 { (PRFuncPtr
*) &mSymbols
.fBlendFuncSeparate
, {{ "glBlendFuncSeparate", "glBlendFuncSeparateEXT" }} },
403 { (PRFuncPtr
*) &mSymbols
.fBufferData
, {{ "glBufferData" }} },
404 { (PRFuncPtr
*) &mSymbols
.fBufferSubData
, {{ "glBufferSubData" }} },
405 { (PRFuncPtr
*) &mSymbols
.fClear
, {{ "glClear" }} },
406 { (PRFuncPtr
*) &mSymbols
.fClearColor
, {{ "glClearColor" }} },
407 { (PRFuncPtr
*) &mSymbols
.fClearStencil
, {{ "glClearStencil" }} },
408 { (PRFuncPtr
*) &mSymbols
.fColorMask
, {{ "glColorMask" }} },
409 { (PRFuncPtr
*) &mSymbols
.fCompressedTexImage2D
, {{ "glCompressedTexImage2D" }} },
410 { (PRFuncPtr
*) &mSymbols
.fCompressedTexSubImage2D
, {{ "glCompressedTexSubImage2D" }} },
411 { (PRFuncPtr
*) &mSymbols
.fCullFace
, {{ "glCullFace" }} },
412 { (PRFuncPtr
*) &mSymbols
.fDetachShader
, {{ "glDetachShader", "glDetachShaderARB" }} },
413 { (PRFuncPtr
*) &mSymbols
.fDepthFunc
, {{ "glDepthFunc" }} },
414 { (PRFuncPtr
*) &mSymbols
.fDepthMask
, {{ "glDepthMask" }} },
415 { (PRFuncPtr
*) &mSymbols
.fDisable
, {{ "glDisable" }} },
416 { (PRFuncPtr
*) &mSymbols
.fDisableVertexAttribArray
, {{ "glDisableVertexAttribArray", "glDisableVertexAttribArrayARB" }} },
417 { (PRFuncPtr
*) &mSymbols
.fDrawArrays
, {{ "glDrawArrays" }} },
418 { (PRFuncPtr
*) &mSymbols
.fDrawElements
, {{ "glDrawElements" }} },
419 { (PRFuncPtr
*) &mSymbols
.fEnable
, {{ "glEnable" }} },
420 { (PRFuncPtr
*) &mSymbols
.fEnableVertexAttribArray
, {{ "glEnableVertexAttribArray", "glEnableVertexAttribArrayARB" }} },
421 { (PRFuncPtr
*) &mSymbols
.fFinish
, {{ "glFinish" }} },
422 { (PRFuncPtr
*) &mSymbols
.fFlush
, {{ "glFlush" }} },
423 { (PRFuncPtr
*) &mSymbols
.fFrontFace
, {{ "glFrontFace" }} },
424 { (PRFuncPtr
*) &mSymbols
.fGetActiveAttrib
, {{ "glGetActiveAttrib", "glGetActiveAttribARB" }} },
425 { (PRFuncPtr
*) &mSymbols
.fGetActiveUniform
, {{ "glGetActiveUniform", "glGetActiveUniformARB" }} },
426 { (PRFuncPtr
*) &mSymbols
.fGetAttachedShaders
, {{ "glGetAttachedShaders", "glGetAttachedShadersARB" }} },
427 { (PRFuncPtr
*) &mSymbols
.fGetAttribLocation
, {{ "glGetAttribLocation", "glGetAttribLocationARB" }} },
428 { (PRFuncPtr
*) &mSymbols
.fGetIntegerv
, {{ "glGetIntegerv" }} },
429 { (PRFuncPtr
*) &mSymbols
.fGetFloatv
, {{ "glGetFloatv" }} },
430 { (PRFuncPtr
*) &mSymbols
.fGetBooleanv
, {{ "glGetBooleanv" }} },
431 { (PRFuncPtr
*) &mSymbols
.fGetBufferParameteriv
, {{ "glGetBufferParameteriv", "glGetBufferParameterivARB" }} },
432 { (PRFuncPtr
*) &mSymbols
.fGetError
, {{ "glGetError" }} },
433 { (PRFuncPtr
*) &mSymbols
.fGetProgramiv
, {{ "glGetProgramiv", "glGetProgramivARB" }} },
434 { (PRFuncPtr
*) &mSymbols
.fGetProgramInfoLog
, {{ "glGetProgramInfoLog", "glGetProgramInfoLogARB" }} },
435 { (PRFuncPtr
*) &mSymbols
.fTexParameteri
, {{ "glTexParameteri" }} },
436 { (PRFuncPtr
*) &mSymbols
.fTexParameteriv
, {{ "glTexParameteriv" }} },
437 { (PRFuncPtr
*) &mSymbols
.fTexParameterf
, {{ "glTexParameterf" }} },
438 { (PRFuncPtr
*) &mSymbols
.fGetString
, {{ "glGetString" }} },
439 { (PRFuncPtr
*) &mSymbols
.fGetTexParameterfv
, {{ "glGetTexParameterfv" }} },
440 { (PRFuncPtr
*) &mSymbols
.fGetTexParameteriv
, {{ "glGetTexParameteriv" }} },
441 { (PRFuncPtr
*) &mSymbols
.fGetUniformfv
, {{ "glGetUniformfv", "glGetUniformfvARB" }} },
442 { (PRFuncPtr
*) &mSymbols
.fGetUniformiv
, {{ "glGetUniformiv", "glGetUniformivARB" }} },
443 { (PRFuncPtr
*) &mSymbols
.fGetUniformLocation
, {{ "glGetUniformLocation", "glGetUniformLocationARB" }} },
444 { (PRFuncPtr
*) &mSymbols
.fGetVertexAttribfv
, {{ "glGetVertexAttribfv", "glGetVertexAttribfvARB" }} },
445 { (PRFuncPtr
*) &mSymbols
.fGetVertexAttribiv
, {{ "glGetVertexAttribiv", "glGetVertexAttribivARB" }} },
446 { (PRFuncPtr
*) &mSymbols
.fGetVertexAttribPointerv
, {{ "glGetVertexAttribPointerv" }} },
447 { (PRFuncPtr
*) &mSymbols
.fHint
, {{ "glHint" }} },
448 { (PRFuncPtr
*) &mSymbols
.fIsBuffer
, {{ "glIsBuffer", "glIsBufferARB" }} },
449 { (PRFuncPtr
*) &mSymbols
.fIsEnabled
, {{ "glIsEnabled" }} },
450 { (PRFuncPtr
*) &mSymbols
.fIsProgram
, {{ "glIsProgram", "glIsProgramARB" }} },
451 { (PRFuncPtr
*) &mSymbols
.fIsShader
, {{ "glIsShader", "glIsShaderARB" }} },
452 { (PRFuncPtr
*) &mSymbols
.fIsTexture
, {{ "glIsTexture", "glIsTextureARB" }} },
453 { (PRFuncPtr
*) &mSymbols
.fLineWidth
, {{ "glLineWidth" }} },
454 { (PRFuncPtr
*) &mSymbols
.fLinkProgram
, {{ "glLinkProgram", "glLinkProgramARB" }} },
455 { (PRFuncPtr
*) &mSymbols
.fPixelStorei
, {{ "glPixelStorei" }} },
456 { (PRFuncPtr
*) &mSymbols
.fPolygonOffset
, {{ "glPolygonOffset" }} },
457 { (PRFuncPtr
*) &mSymbols
.fReadPixels
, {{ "glReadPixels" }} },
458 { (PRFuncPtr
*) &mSymbols
.fSampleCoverage
, {{ "glSampleCoverage" }} },
459 { (PRFuncPtr
*) &mSymbols
.fScissor
, {{ "glScissor" }} },
460 { (PRFuncPtr
*) &mSymbols
.fStencilFunc
, {{ "glStencilFunc" }} },
461 { (PRFuncPtr
*) &mSymbols
.fStencilFuncSeparate
, {{ "glStencilFuncSeparate", "glStencilFuncSeparateEXT" }} },
462 { (PRFuncPtr
*) &mSymbols
.fStencilMask
, {{ "glStencilMask" }} },
463 { (PRFuncPtr
*) &mSymbols
.fStencilMaskSeparate
, {{ "glStencilMaskSeparate", "glStencilMaskSeparateEXT" }} },
464 { (PRFuncPtr
*) &mSymbols
.fStencilOp
, {{ "glStencilOp" }} },
465 { (PRFuncPtr
*) &mSymbols
.fStencilOpSeparate
, {{ "glStencilOpSeparate", "glStencilOpSeparateEXT" }} },
466 { (PRFuncPtr
*) &mSymbols
.fTexImage2D
, {{ "glTexImage2D" }} },
467 { (PRFuncPtr
*) &mSymbols
.fTexSubImage2D
, {{ "glTexSubImage2D" }} },
468 { (PRFuncPtr
*) &mSymbols
.fUniform1f
, {{ "glUniform1f" }} },
469 { (PRFuncPtr
*) &mSymbols
.fUniform1fv
, {{ "glUniform1fv" }} },
470 { (PRFuncPtr
*) &mSymbols
.fUniform1i
, {{ "glUniform1i" }} },
471 { (PRFuncPtr
*) &mSymbols
.fUniform1iv
, {{ "glUniform1iv" }} },
472 { (PRFuncPtr
*) &mSymbols
.fUniform2f
, {{ "glUniform2f" }} },
473 { (PRFuncPtr
*) &mSymbols
.fUniform2fv
, {{ "glUniform2fv" }} },
474 { (PRFuncPtr
*) &mSymbols
.fUniform2i
, {{ "glUniform2i" }} },
475 { (PRFuncPtr
*) &mSymbols
.fUniform2iv
, {{ "glUniform2iv" }} },
476 { (PRFuncPtr
*) &mSymbols
.fUniform3f
, {{ "glUniform3f" }} },
477 { (PRFuncPtr
*) &mSymbols
.fUniform3fv
, {{ "glUniform3fv" }} },
478 { (PRFuncPtr
*) &mSymbols
.fUniform3i
, {{ "glUniform3i" }} },
479 { (PRFuncPtr
*) &mSymbols
.fUniform3iv
, {{ "glUniform3iv" }} },
480 { (PRFuncPtr
*) &mSymbols
.fUniform4f
, {{ "glUniform4f" }} },
481 { (PRFuncPtr
*) &mSymbols
.fUniform4fv
, {{ "glUniform4fv" }} },
482 { (PRFuncPtr
*) &mSymbols
.fUniform4i
, {{ "glUniform4i" }} },
483 { (PRFuncPtr
*) &mSymbols
.fUniform4iv
, {{ "glUniform4iv" }} },
484 { (PRFuncPtr
*) &mSymbols
.fUniformMatrix2fv
, {{ "glUniformMatrix2fv" }} },
485 { (PRFuncPtr
*) &mSymbols
.fUniformMatrix3fv
, {{ "glUniformMatrix3fv" }} },
486 { (PRFuncPtr
*) &mSymbols
.fUniformMatrix4fv
, {{ "glUniformMatrix4fv" }} },
487 { (PRFuncPtr
*) &mSymbols
.fUseProgram
, {{ "glUseProgram" }} },
488 { (PRFuncPtr
*) &mSymbols
.fValidateProgram
, {{ "glValidateProgram" }} },
489 { (PRFuncPtr
*) &mSymbols
.fVertexAttribPointer
, {{ "glVertexAttribPointer" }} },
490 { (PRFuncPtr
*) &mSymbols
.fVertexAttrib1f
, {{ "glVertexAttrib1f" }} },
491 { (PRFuncPtr
*) &mSymbols
.fVertexAttrib2f
, {{ "glVertexAttrib2f" }} },
492 { (PRFuncPtr
*) &mSymbols
.fVertexAttrib3f
, {{ "glVertexAttrib3f" }} },
493 { (PRFuncPtr
*) &mSymbols
.fVertexAttrib4f
, {{ "glVertexAttrib4f" }} },
494 { (PRFuncPtr
*) &mSymbols
.fVertexAttrib1fv
, {{ "glVertexAttrib1fv" }} },
495 { (PRFuncPtr
*) &mSymbols
.fVertexAttrib2fv
, {{ "glVertexAttrib2fv" }} },
496 { (PRFuncPtr
*) &mSymbols
.fVertexAttrib3fv
, {{ "glVertexAttrib3fv" }} },
497 { (PRFuncPtr
*) &mSymbols
.fVertexAttrib4fv
, {{ "glVertexAttrib4fv" }} },
498 { (PRFuncPtr
*) &mSymbols
.fViewport
, {{ "glViewport" }} },
499 { (PRFuncPtr
*) &mSymbols
.fCompileShader
, {{ "glCompileShader" }} },
500 { (PRFuncPtr
*) &mSymbols
.fCopyTexImage2D
, {{ "glCopyTexImage2D" }} },
501 { (PRFuncPtr
*) &mSymbols
.fCopyTexSubImage2D
, {{ "glCopyTexSubImage2D" }} },
502 { (PRFuncPtr
*) &mSymbols
.fGetShaderiv
, {{ "glGetShaderiv" }} },
503 { (PRFuncPtr
*) &mSymbols
.fGetShaderInfoLog
, {{ "glGetShaderInfoLog" }} },
504 { (PRFuncPtr
*) &mSymbols
.fGetShaderSource
, {{ "glGetShaderSource" }} },
505 { (PRFuncPtr
*) &mSymbols
.fShaderSource
, {{ "glShaderSource" }} },
506 { (PRFuncPtr
*) &mSymbols
.fVertexAttribPointer
, {{ "glVertexAttribPointer" }} },
508 { (PRFuncPtr
*) &mSymbols
.fGenBuffers
, {{ "glGenBuffers", "glGenBuffersARB" }} },
509 { (PRFuncPtr
*) &mSymbols
.fGenTextures
, {{ "glGenTextures" }} },
510 { (PRFuncPtr
*) &mSymbols
.fCreateProgram
, {{ "glCreateProgram", "glCreateProgramARB" }} },
511 { (PRFuncPtr
*) &mSymbols
.fCreateShader
, {{ "glCreateShader", "glCreateShaderARB" }} },
513 { (PRFuncPtr
*) &mSymbols
.fDeleteBuffers
, {{ "glDeleteBuffers", "glDeleteBuffersARB" }} },
514 { (PRFuncPtr
*) &mSymbols
.fDeleteTextures
, {{ "glDeleteTextures", "glDeleteTexturesARB" }} },
515 { (PRFuncPtr
*) &mSymbols
.fDeleteProgram
, {{ "glDeleteProgram", "glDeleteProgramARB" }} },
516 { (PRFuncPtr
*) &mSymbols
.fDeleteShader
, {{ "glDeleteShader", "glDeleteShaderARB" }} },
522 if (!fnLoadSymbols(coreSymbols
, "GL")) return false;
525 const SymLoadStruct symbols
[] = {
526 {(PRFuncPtr
*)&mSymbols
.fGetGraphicsResetStatus
,
527 {{"glGetGraphicsResetStatus", "glGetGraphicsResetStatusARB",
528 "glGetGraphicsResetStatusKHR", "glGetGraphicsResetStatusEXT"}}},
530 (void)fnLoadSymbols(symbols
, nullptr);
532 // We need to call the fGetError symbol directly here because if there is an
533 // unflushed reset status, we don't want to mark the context as lost. That
534 // would prevent us from recovering.
535 auto err
= mSymbols
.fGetError();
536 if (err
== LOCAL_GL_CONTEXT_LOST
) {
537 MOZ_ASSERT(mSymbols
.fGetGraphicsResetStatus
);
538 const auto status
= fGetGraphicsResetStatus();
540 printf_stderr("Unflushed glGetGraphicsResetStatus: 0x%04x\n", status
);
553 const auto* const versionRawStr
= (const char*)fGetString(LOCAL_GL_VERSION
);
554 if (!versionRawStr
|| !*versionRawStr
) {
555 // This can happen with Pernosco.
556 NS_WARNING("Empty GL version string");
560 const std::string versionStr
= versionRawStr
;
561 if (versionStr
.find("OpenGL ES") == 0) {
562 mProfile
= ContextProfile::OpenGLES
;
565 uint32_t majorVer
, minorVer
;
566 if (!ParseVersion(versionStr
, &majorVer
, &minorVer
)) {
567 MOZ_ASSERT(false, "Failed to parse GL_VERSION");
570 MOZ_ASSERT(majorVer
< 10);
571 MOZ_ASSERT(minorVer
< 10);
572 mVersion
= majorVer
* 100 + minorVer
* 10;
573 if (mVersion
< 200) return false;
577 const auto glslVersionStr
=
578 (const char*)fGetString(LOCAL_GL_SHADING_LANGUAGE_VERSION
);
579 if (!glslVersionStr
) {
580 // This happens on the Android emulators. We'll just return 100
581 mShadingLanguageVersion
= 100;
582 } else if (ParseVersion(glslVersionStr
, &majorVer
, &minorVer
)) {
583 MOZ_ASSERT(majorVer
< 10);
584 MOZ_ASSERT(minorVer
< 100);
585 mShadingLanguageVersion
= majorVer
* 100 + minorVer
;
587 MOZ_ASSERT(false, "Failed to parse GL_SHADING_LANGUAGE_VERSION");
592 printf_stderr("GL version detected: %u\n", mVersion
);
593 printf_stderr("GLSL version detected: %u\n", mShadingLanguageVersion
);
594 printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR
));
595 printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER
));
600 // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
601 if (mProfile
== ContextProfile::OpenGLES
) {
602 const SymLoadStruct symbols
[] = {CORE_SYMBOL(GetShaderPrecisionFormat
),
603 CORE_SYMBOL(ClearDepthf
),
604 CORE_SYMBOL(DepthRangef
), END_SYMBOLS
};
606 if (!fnLoadSymbols(symbols
, "OpenGL ES")) return false;
608 const SymLoadStruct symbols
[] = {
609 CORE_SYMBOL(ClearDepth
), CORE_SYMBOL(DepthRange
),
610 CORE_SYMBOL(ReadBuffer
), CORE_SYMBOL(MapBuffer
),
611 CORE_SYMBOL(UnmapBuffer
), CORE_SYMBOL(PointParameterf
),
612 CORE_SYMBOL(DrawBuffer
),
613 // The following functions are only used by Skia/GL in desktop mode.
614 // Other parts of Gecko should avoid using these
615 CORE_SYMBOL(DrawBuffers
), CORE_SYMBOL(ClientActiveTexture
),
616 CORE_SYMBOL(DisableClientState
), CORE_SYMBOL(EnableClientState
),
617 CORE_SYMBOL(LoadIdentity
), CORE_SYMBOL(LoadMatrixf
),
618 CORE_SYMBOL(MatrixMode
), CORE_SYMBOL(PolygonMode
), CORE_SYMBOL(TexGeni
),
619 CORE_SYMBOL(TexGenf
), CORE_SYMBOL(TexGenfv
), CORE_SYMBOL(VertexPointer
),
622 if (!fnLoadSymbols(symbols
, "Desktop OpenGL")) return false;
627 const char* glVendorString
= (const char*)fGetString(LOCAL_GL_VENDOR
);
628 const char* glRendererString
= (const char*)fGetString(LOCAL_GL_RENDERER
);
629 if (!glVendorString
|| !glRendererString
) return false;
631 // The order of these strings must match up with the order of the enum
632 // defined in GLContext.h for vendor IDs.
633 const char* vendorMatchStrings
[size_t(GLVendor::Other
) + 1] = {
634 "Intel", "NVIDIA", "ATI", "Qualcomm", "Imagination",
635 "nouveau", "Vivante", "VMware, Inc.", "ARM", "Unknown"};
637 mVendor
= GLVendor::Other
;
638 for (size_t i
= 0; i
< size_t(GLVendor::Other
); ++i
) {
639 if (DoesStringMatch(glVendorString
, vendorMatchStrings
[i
])) {
640 mVendor
= GLVendor(i
);
645 // The order of these strings must match up with the order of the enum
646 // defined in GLContext.h for renderer IDs.
647 const char* rendererMatchStrings
[size_t(GLRenderer::Other
) + 1] = {
664 "Gallium 0.4 on llvmpipe",
665 "Intel HD Graphics 3000 OpenGL Engine",
666 "Microsoft Basic Render Driver",
670 mRenderer
= GLRenderer::Other
;
671 for (size_t i
= 0; i
< size_t(GLRenderer::Other
); ++i
) {
672 if (DoesStringMatch(glRendererString
, rendererMatchStrings
[i
])) {
673 mRenderer
= GLRenderer(i
);
679 const auto versionStr
= (const char*)fGetString(LOCAL_GL_VERSION
);
680 if (strstr(versionStr
, "Mesa")) {
685 const auto Once
= []() {
686 static bool did
= false;
687 if (did
) return false;
692 bool printRenderer
= ShouldSpew();
693 printRenderer
|= (kIsDebug
&& Once());
695 printf_stderr("GL_VENDOR: %s\n", glVendorString
);
696 printf_stderr("mVendor: %s\n", vendorMatchStrings
[size_t(mVendor
)]);
697 printf_stderr("GL_RENDERER: %s\n", glRendererString
);
698 printf_stderr("mRenderer: %s\n", rendererMatchStrings
[size_t(mRenderer
)]);
699 printf_stderr("mIsMesa: %i\n", int(mIsMesa
));
704 if (mVersion
>= 300) { // Both GL3 and ES3.
705 const SymLoadStruct symbols
[] = {
706 {(PRFuncPtr
*)&mSymbols
.fGetStringi
, {{"glGetStringi"}}}, END_SYMBOLS
};
708 if (!fnLoadSymbols(symbols
, "GetStringi")) {
709 MOZ_RELEASE_ASSERT(false, "GFX: GetStringi is required!");
715 if (mProfile
!= ContextProfile::OpenGLES
) {
716 if (mVersion
>= 310 && !IsExtensionSupported(ARB_compatibility
)) {
717 mProfile
= ContextProfile::OpenGLCore
;
719 mProfile
= ContextProfile::OpenGLCompatibility
;
722 MOZ_ASSERT(mProfile
!= ContextProfile::Unknown
);
725 const char* profileStr
= "";
726 if (mProfile
== ContextProfile::OpenGLES
) {
728 } else if (mProfile
== ContextProfile::OpenGLCore
) {
729 profileStr
= " core";
731 printf_stderr("Detected profile: %u%s\n", mVersion
, profileStr
);
738 // Disable extensions with partial or incorrect support.
739 if (WorkAroundDriverBugs()) {
740 if (Renderer() == GLRenderer::AdrenoTM320
) {
741 MarkUnsupported(GLFeature::standard_derivatives
);
744 if (Renderer() == GLRenderer::AndroidEmulator
) {
746 mSymbols
.fGetGraphicsResetStatus
= 0;
749 if (Vendor() == GLVendor::Vivante
) {
751 MarkUnsupported(GLFeature::standard_derivatives
);
754 if (Renderer() == GLRenderer::MicrosoftBasicRenderDriver
) {
755 // Bug 978966: on Microsoft's "Basic Render Driver" (software renderer)
756 // multisampling hardcodes blending with the default blendfunc, which
758 MarkUnsupported(GLFeature::framebuffer_multisample
);
762 // DrawElementsInstanced hangs the driver.
763 MarkUnsupported(GLFeature::robust_buffer_access_behavior
);
766 if (Renderer() == GLRenderer::SamsungXclipse
) {
767 MarkUnsupported(GLFeature::invalidate_framebuffer
);
771 if (IsExtensionSupported(GLContext::ARB_pixel_buffer_object
)) {
773 (mSymbols
.fMapBuffer
&& mSymbols
.fUnmapBuffer
),
774 "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer"
775 " being available!");
778 ////////////////////////////////////////////////////////////////////////////
780 const auto fnLoadForFeature
= [&](const SymLoadStruct
* list
,
782 return this->LoadFeatureSymbols(*loader
, list
, feature
);
785 // Check for ARB_framebuffer_objects
786 if (IsSupported(GLFeature::framebuffer_object
)) {
787 // https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
788 const SymLoadStruct symbols
[] = {
789 CORE_SYMBOL(IsRenderbuffer
),
790 CORE_SYMBOL(BindRenderbuffer
),
791 CORE_SYMBOL(DeleteRenderbuffers
),
792 CORE_SYMBOL(GenRenderbuffers
),
793 CORE_SYMBOL(RenderbufferStorage
),
794 CORE_SYMBOL(RenderbufferStorageMultisample
),
795 CORE_SYMBOL(GetRenderbufferParameteriv
),
796 CORE_SYMBOL(IsFramebuffer
),
797 CORE_SYMBOL(BindFramebuffer
),
798 CORE_SYMBOL(DeleteFramebuffers
),
799 CORE_SYMBOL(GenFramebuffers
),
800 CORE_SYMBOL(CheckFramebufferStatus
),
801 CORE_SYMBOL(FramebufferTexture2D
),
802 CORE_SYMBOL(FramebufferTextureLayer
),
803 CORE_SYMBOL(FramebufferRenderbuffer
),
804 CORE_SYMBOL(GetFramebufferAttachmentParameteriv
),
805 CORE_SYMBOL(BlitFramebuffer
),
806 CORE_SYMBOL(GenerateMipmap
),
808 fnLoadForFeature(symbols
, GLFeature::framebuffer_object
);
811 if (!IsSupported(GLFeature::framebuffer_object
)) {
812 // Check for aux symbols based on extensions
813 if (IsSupported(GLFeature::framebuffer_object_EXT_OES
)) {
814 const SymLoadStruct symbols
[] = {
815 CORE_EXT_SYMBOL2(IsRenderbuffer
, EXT
, OES
),
816 CORE_EXT_SYMBOL2(BindRenderbuffer
, EXT
, OES
),
817 CORE_EXT_SYMBOL2(DeleteRenderbuffers
, EXT
, OES
),
818 CORE_EXT_SYMBOL2(GenRenderbuffers
, EXT
, OES
),
819 CORE_EXT_SYMBOL2(RenderbufferStorage
, EXT
, OES
),
820 CORE_EXT_SYMBOL2(GetRenderbufferParameteriv
, EXT
, OES
),
821 CORE_EXT_SYMBOL2(IsFramebuffer
, EXT
, OES
),
822 CORE_EXT_SYMBOL2(BindFramebuffer
, EXT
, OES
),
823 CORE_EXT_SYMBOL2(DeleteFramebuffers
, EXT
, OES
),
824 CORE_EXT_SYMBOL2(GenFramebuffers
, EXT
, OES
),
825 CORE_EXT_SYMBOL2(CheckFramebufferStatus
, EXT
, OES
),
826 CORE_EXT_SYMBOL2(FramebufferTexture2D
, EXT
, OES
),
827 CORE_EXT_SYMBOL2(FramebufferRenderbuffer
, EXT
, OES
),
828 CORE_EXT_SYMBOL2(GetFramebufferAttachmentParameteriv
, EXT
, OES
),
829 CORE_EXT_SYMBOL2(GenerateMipmap
, EXT
, OES
),
831 fnLoadForFeature(symbols
, GLFeature::framebuffer_object_EXT_OES
);
834 if (IsSupported(GLFeature::framebuffer_blit
)) {
835 const SymLoadStruct symbols
[] = {
836 EXT_SYMBOL3(BlitFramebuffer
, ANGLE
, EXT
, NV
), END_SYMBOLS
};
837 fnLoadForFeature(symbols
, GLFeature::framebuffer_blit
);
840 if (IsSupported(GLFeature::framebuffer_multisample
)) {
841 const SymLoadStruct symbols
[] = {
842 EXT_SYMBOL3(RenderbufferStorageMultisample
, ANGLE
, APPLE
, EXT
),
844 fnLoadForFeature(symbols
, GLFeature::framebuffer_multisample
);
847 if (IsExtensionSupported(GLContext::ARB_geometry_shader4
) ||
848 IsExtensionSupported(GLContext::NV_geometry_program4
)) {
849 const SymLoadStruct symbols
[] = {
850 EXT_SYMBOL2(FramebufferTextureLayer
, ARB
, EXT
), END_SYMBOLS
};
851 if (!fnLoadSymbols(symbols
,
852 "ARB_geometry_shader4/NV_geometry_program4")) {
853 MarkExtensionUnsupported(GLContext::ARB_geometry_shader4
);
854 MarkExtensionUnsupported(GLContext::NV_geometry_program4
);
859 if (!IsSupported(GLFeature::framebuffer_object
) &&
860 !IsSupported(GLFeature::framebuffer_object_EXT_OES
)) {
861 NS_ERROR("GLContext requires support for framebuffer objects.");
864 MOZ_RELEASE_ASSERT(mSymbols
.fBindFramebuffer
,
865 "GFX: mSymbols.fBindFramebuffer zero or not set.");
869 const auto err
= fGetError();
870 MOZ_RELEASE_ASSERT(!IsBadCallError(err
));
871 if (err
) return false;
873 LoadMoreSymbols(*loader
);
875 ////////////////////////////////////////////////////////////////////////////
877 raw_fGetIntegerv(LOCAL_GL_VIEWPORT
, mViewportRect
);
878 raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX
, mScissorRect
);
879 raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE
, &mMaxTextureSize
);
880 raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &mMaxCubeMapTextureSize
);
881 raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE
, &mMaxRenderbufferSize
);
882 raw_fGetIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS
, mMaxViewportDims
);
884 if (mWorkAroundDriverBugs
) {
885 int maxTexSize
= INT32_MAX
;
886 int maxCubeSize
= INT32_MAX
;
888 // https://bugzilla.mozilla.org/show_bug.cgi?id=1544446
889 // Mojave exposes 16k textures, but gives FRAMEBUFFER_UNSUPPORTED for any
890 // 16k*16k FB except rgba8 without depth/stencil.
891 // The max supported sizes changes based on involved formats.
892 // (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;
920 const auto fnLimit
= [&](int* const driver
, const int limit
) {
921 if (*driver
> limit
) {
923 mNeedsTextureSizeChecks
= true;
927 fnLimit(&mMaxTextureSize
, maxTexSize
);
928 fnLimit(&mMaxRenderbufferSize
, maxTexSize
);
930 maxCubeSize
= std::min(maxCubeSize
, maxTexSize
);
931 fnLimit(&mMaxCubeMapTextureSize
, maxCubeSize
);
934 if (IsSupported(GLFeature::framebuffer_multisample
)) {
935 fGetIntegerv(LOCAL_GL_MAX_SAMPLES
, (GLint
*)&mMaxSamples
);
938 mMaxTexOrRbSize
= std::min(mMaxTextureSize
, mMaxRenderbufferSize
);
940 ////////////////////////////////////////////////////////////////////////////
942 // We're ready for final setup.
943 fBindFramebuffer(LOCAL_GL_FRAMEBUFFER
, 0);
944 MOZ_GL_ASSERT(this, IsCurrent());
946 if (ShouldSpew() && IsExtensionSupported(KHR_debug
)) {
947 fEnable(LOCAL_GL_DEBUG_OUTPUT
);
948 fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS
);
949 fDebugMessageCallback(&StaticDebugCallback
, (void*)this);
950 fDebugMessageControl(LOCAL_GL_DONT_CARE
, LOCAL_GL_DONT_CARE
,
951 LOCAL_GL_DONT_CARE
, 0, nullptr, true);
957 void GLContext::LoadMoreSymbols(const SymbolLoader
& loader
) {
958 const auto fnLoadForExt
= [&](const SymLoadStruct
* list
, GLExtensions ext
) {
959 return this->LoadExtSymbols(loader
, list
, ext
);
962 const auto fnLoadForFeature
= [&](const SymLoadStruct
* list
,
964 return this->LoadFeatureSymbols(loader
, list
, feature
);
967 const auto fnLoadFeatureByCore
= [&](const SymLoadStruct
* coreList
,
968 const SymLoadStruct
* extList
,
970 const bool useCore
= this->IsFeatureProvidedByCoreSymbols(feature
);
971 const auto list
= useCore
? coreList
: extList
;
972 return fnLoadForFeature(list
, feature
);
975 if (IsSupported(GLFeature::robustness
)) {
976 const auto resetStrategy
=
977 GetIntAs
<GLuint
>(LOCAL_GL_RESET_NOTIFICATION_STRATEGY
);
978 if (resetStrategy
!= LOCAL_GL_LOSE_CONTEXT_ON_RESET
) {
980 "Robustness supported, strategy is not LOSE_CONTEXT_ON_RESET!");
982 const bool isDisabled
=
983 (resetStrategy
== LOCAL_GL_NO_RESET_NOTIFICATION
);
984 printf_stderr("Strategy: %s (0x%04x)",
985 (isDisabled
? "disabled" : "unrecognized"),
988 MarkUnsupported(GLFeature::robustness
);
992 if (IsSupported(GLFeature::sync
)) {
993 const SymLoadStruct symbols
[] = {
994 CORE_SYMBOL(FenceSync
), CORE_SYMBOL(IsSync
),
995 CORE_SYMBOL(DeleteSync
), CORE_SYMBOL(ClientWaitSync
),
996 CORE_SYMBOL(WaitSync
), CORE_SYMBOL(GetInteger64v
),
997 CORE_SYMBOL(GetSynciv
), END_SYMBOLS
};
998 fnLoadForFeature(symbols
, GLFeature::sync
);
1001 if (IsExtensionSupported(OES_EGL_image
)) {
1002 const SymLoadStruct symbols
[] = {
1003 {(PRFuncPtr
*)&mSymbols
.fEGLImageTargetTexture2D
,
1004 {{"glEGLImageTargetTexture2DOES"}}},
1005 {(PRFuncPtr
*)&mSymbols
.fEGLImageTargetRenderbufferStorage
,
1006 {{"glEGLImageTargetRenderbufferStorageOES"}}},
1008 fnLoadForExt(symbols
, OES_EGL_image
);
1011 if (IsExtensionSupported(APPLE_texture_range
)) {
1012 const SymLoadStruct symbols
[] = {CORE_SYMBOL(TextureRangeAPPLE
),
1014 fnLoadForExt(symbols
, APPLE_texture_range
);
1017 if (IsExtensionSupported(APPLE_fence
)) {
1018 const SymLoadStruct symbols
[] = {CORE_SYMBOL(FinishObjectAPPLE
),
1019 CORE_SYMBOL(TestObjectAPPLE
), END_SYMBOLS
};
1020 fnLoadForExt(symbols
, APPLE_fence
);
1025 if (IsSupported(GLFeature::vertex_array_object
)) {
1026 const SymLoadStruct coreSymbols
[] = {
1027 { (PRFuncPtr
*) &mSymbols
.fIsVertexArray
, {{ "glIsVertexArray" }} },
1028 { (PRFuncPtr
*) &mSymbols
.fGenVertexArrays
, {{ "glGenVertexArrays" }} },
1029 { (PRFuncPtr
*) &mSymbols
.fBindVertexArray
, {{ "glBindVertexArray" }} },
1030 { (PRFuncPtr
*) &mSymbols
.fDeleteVertexArrays
, {{ "glDeleteVertexArrays" }} },
1033 const SymLoadStruct extSymbols
[] = {
1034 { (PRFuncPtr
*) &mSymbols
.fIsVertexArray
, {{ "glIsVertexArrayARB", "glIsVertexArrayOES", "glIsVertexArrayAPPLE" }} },
1035 { (PRFuncPtr
*) &mSymbols
.fGenVertexArrays
, {{ "glGenVertexArraysARB", "glGenVertexArraysOES", "glGenVertexArraysAPPLE" }} },
1036 { (PRFuncPtr
*) &mSymbols
.fBindVertexArray
, {{ "glBindVertexArrayARB", "glBindVertexArrayOES", "glBindVertexArrayAPPLE" }} },
1037 { (PRFuncPtr
*) &mSymbols
.fDeleteVertexArrays
, {{ "glDeleteVertexArraysARB", "glDeleteVertexArraysOES", "glDeleteVertexArraysAPPLE" }} },
1040 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::vertex_array_object
);
1043 if (IsSupported(GLFeature::draw_instanced
)) {
1044 const SymLoadStruct coreSymbols
[] = {
1045 { (PRFuncPtr
*) &mSymbols
.fDrawArraysInstanced
, {{ "glDrawArraysInstanced" }} },
1046 { (PRFuncPtr
*) &mSymbols
.fDrawElementsInstanced
, {{ "glDrawElementsInstanced" }} },
1049 const SymLoadStruct extSymbols
[] = {
1050 { (PRFuncPtr
*) &mSymbols
.fDrawArraysInstanced
, {{ "glDrawArraysInstancedARB", "glDrawArraysInstancedEXT", "glDrawArraysInstancedNV", "glDrawArraysInstancedANGLE" }} },
1051 { (PRFuncPtr
*) &mSymbols
.fDrawElementsInstanced
, {{ "glDrawElementsInstancedARB", "glDrawElementsInstancedEXT", "glDrawElementsInstancedNV", "glDrawElementsInstancedANGLE" }}
1055 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::draw_instanced
);
1058 if (IsSupported(GLFeature::instanced_arrays
)) {
1059 const SymLoadStruct coreSymbols
[] = {
1060 { (PRFuncPtr
*) &mSymbols
.fVertexAttribDivisor
, {{ "glVertexAttribDivisor" }} },
1063 const SymLoadStruct extSymbols
[] = {
1064 { (PRFuncPtr
*) &mSymbols
.fVertexAttribDivisor
, {{ "glVertexAttribDivisorARB", "glVertexAttribDivisorNV", "glVertexAttribDivisorANGLE" }} },
1067 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::instanced_arrays
);
1070 if (IsSupported(GLFeature::texture_storage
)) {
1071 const SymLoadStruct coreSymbols
[] = {
1072 { (PRFuncPtr
*) &mSymbols
.fTexStorage2D
, {{ "glTexStorage2D" }} },
1073 { (PRFuncPtr
*) &mSymbols
.fTexStorage3D
, {{ "glTexStorage3D" }} },
1076 const SymLoadStruct extSymbols
[] = {
1077 { (PRFuncPtr
*) &mSymbols
.fTexStorage2D
, {{ "glTexStorage2DEXT" }} },
1078 { (PRFuncPtr
*) &mSymbols
.fTexStorage3D
, {{ "glTexStorage3DEXT" }} },
1081 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::texture_storage
);
1084 if (IsSupported(GLFeature::sampler_objects
)) {
1085 const SymLoadStruct symbols
[] = {
1086 { (PRFuncPtr
*) &mSymbols
.fGenSamplers
, {{ "glGenSamplers" }} },
1087 { (PRFuncPtr
*) &mSymbols
.fDeleteSamplers
, {{ "glDeleteSamplers" }} },
1088 { (PRFuncPtr
*) &mSymbols
.fIsSampler
, {{ "glIsSampler" }} },
1089 { (PRFuncPtr
*) &mSymbols
.fBindSampler
, {{ "glBindSampler" }} },
1090 { (PRFuncPtr
*) &mSymbols
.fSamplerParameteri
, {{ "glSamplerParameteri" }} },
1091 { (PRFuncPtr
*) &mSymbols
.fSamplerParameteriv
, {{ "glSamplerParameteriv" }} },
1092 { (PRFuncPtr
*) &mSymbols
.fSamplerParameterf
, {{ "glSamplerParameterf" }} },
1093 { (PRFuncPtr
*) &mSymbols
.fSamplerParameterfv
, {{ "glSamplerParameterfv" }} },
1094 { (PRFuncPtr
*) &mSymbols
.fGetSamplerParameteriv
, {{ "glGetSamplerParameteriv" }} },
1095 { (PRFuncPtr
*) &mSymbols
.fGetSamplerParameterfv
, {{ "glGetSamplerParameterfv" }} },
1098 fnLoadForFeature(symbols
, GLFeature::sampler_objects
);
1101 // ARB_transform_feedback2/NV_transform_feedback2 is a
1102 // superset of EXT_transform_feedback/NV_transform_feedback
1103 // and adds glPauseTransformFeedback &
1104 // glResumeTransformFeedback, which are required for WebGL2.
1105 if (IsSupported(GLFeature::transform_feedback2
)) {
1106 const SymLoadStruct coreSymbols
[] = {
1107 { (PRFuncPtr
*) &mSymbols
.fBindBufferBase
, {{ "glBindBufferBase" }} },
1108 { (PRFuncPtr
*) &mSymbols
.fBindBufferRange
, {{ "glBindBufferRange" }} },
1109 { (PRFuncPtr
*) &mSymbols
.fGenTransformFeedbacks
, {{ "glGenTransformFeedbacks" }} },
1110 { (PRFuncPtr
*) &mSymbols
.fBindTransformFeedback
, {{ "glBindTransformFeedback" }} },
1111 { (PRFuncPtr
*) &mSymbols
.fDeleteTransformFeedbacks
, {{ "glDeleteTransformFeedbacks" }} },
1112 { (PRFuncPtr
*) &mSymbols
.fIsTransformFeedback
, {{ "glIsTransformFeedback" }} },
1113 { (PRFuncPtr
*) &mSymbols
.fBeginTransformFeedback
, {{ "glBeginTransformFeedback" }} },
1114 { (PRFuncPtr
*) &mSymbols
.fEndTransformFeedback
, {{ "glEndTransformFeedback" }} },
1115 { (PRFuncPtr
*) &mSymbols
.fTransformFeedbackVaryings
, {{ "glTransformFeedbackVaryings" }} },
1116 { (PRFuncPtr
*) &mSymbols
.fGetTransformFeedbackVarying
, {{ "glGetTransformFeedbackVarying" }} },
1117 { (PRFuncPtr
*) &mSymbols
.fPauseTransformFeedback
, {{ "glPauseTransformFeedback" }} },
1118 { (PRFuncPtr
*) &mSymbols
.fResumeTransformFeedback
, {{ "glResumeTransformFeedback" }} },
1121 const SymLoadStruct extSymbols
[] = {
1122 { (PRFuncPtr
*) &mSymbols
.fBindBufferBase
, {{ "glBindBufferBaseEXT", "glBindBufferBaseNV" }} },
1123 { (PRFuncPtr
*) &mSymbols
.fBindBufferRange
, {{ "glBindBufferRangeEXT", "glBindBufferRangeNV" }} },
1124 { (PRFuncPtr
*) &mSymbols
.fGenTransformFeedbacks
, {{ "glGenTransformFeedbacksNV" }} },
1125 { (PRFuncPtr
*) &mSymbols
.fBindTransformFeedback
, {{ "glBindTransformFeedbackNV" }} },
1126 { (PRFuncPtr
*) &mSymbols
.fDeleteTransformFeedbacks
, {{ "glDeleteTransformFeedbacksNV" }} },
1127 { (PRFuncPtr
*) &mSymbols
.fIsTransformFeedback
, {{ "glIsTransformFeedbackNV" }} },
1128 { (PRFuncPtr
*) &mSymbols
.fBeginTransformFeedback
, {{ "glBeginTransformFeedbackEXT", "glBeginTransformFeedbackNV" }} },
1129 { (PRFuncPtr
*) &mSymbols
.fEndTransformFeedback
, {{ "glEndTransformFeedbackEXT", "glEndTransformFeedbackNV" }} },
1130 { (PRFuncPtr
*) &mSymbols
.fTransformFeedbackVaryings
, {{ "glTransformFeedbackVaryingsEXT", "glTransformFeedbackVaryingsNV" }} },
1131 { (PRFuncPtr
*) &mSymbols
.fGetTransformFeedbackVarying
, {{ "glGetTransformFeedbackVaryingEXT", "glGetTransformFeedbackVaryingNV" }} },
1132 { (PRFuncPtr
*) &mSymbols
.fPauseTransformFeedback
, {{ "glPauseTransformFeedbackNV" }} },
1133 { (PRFuncPtr
*) &mSymbols
.fResumeTransformFeedback
, {{ "glResumeTransformFeedbackNV" }} },
1136 if (!fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::transform_feedback2
)) {
1137 // Also mark bind_buffer_offset as unsupported.
1138 MarkUnsupported(GLFeature::bind_buffer_offset
);
1142 if (IsSupported(GLFeature::bind_buffer_offset
)) {
1143 const SymLoadStruct coreSymbols
[] = {
1144 { (PRFuncPtr
*) &mSymbols
.fBindBufferOffset
, {{ "glBindBufferOffset" }} },
1147 const SymLoadStruct extSymbols
[] = {
1148 { (PRFuncPtr
*) &mSymbols
.fBindBufferOffset
,
1149 {{ "glBindBufferOffsetEXT", "glBindBufferOffsetNV" }}
1153 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::bind_buffer_offset
);
1156 if (IsSupported(GLFeature::query_counter
)) {
1157 const SymLoadStruct coreSymbols
[] = {
1158 { (PRFuncPtr
*) &mSymbols
.fQueryCounter
, {{ "glQueryCounter" }} },
1161 const SymLoadStruct extSymbols
[] = {
1162 { (PRFuncPtr
*) &mSymbols
.fQueryCounter
, {{ "glQueryCounterEXT", "glQueryCounterANGLE" }} },
1165 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::query_counter
);
1168 if (IsSupported(GLFeature::query_objects
)) {
1169 const SymLoadStruct coreSymbols
[] = {
1170 { (PRFuncPtr
*) &mSymbols
.fBeginQuery
, {{ "glBeginQuery" }} },
1171 { (PRFuncPtr
*) &mSymbols
.fGenQueries
, {{ "glGenQueries" }} },
1172 { (PRFuncPtr
*) &mSymbols
.fDeleteQueries
, {{ "glDeleteQueries" }} },
1173 { (PRFuncPtr
*) &mSymbols
.fEndQuery
, {{ "glEndQuery" }} },
1174 { (PRFuncPtr
*) &mSymbols
.fGetQueryiv
, {{ "glGetQueryiv" }} },
1175 { (PRFuncPtr
*) &mSymbols
.fGetQueryObjectuiv
, {{ "glGetQueryObjectuiv" }} },
1176 { (PRFuncPtr
*) &mSymbols
.fIsQuery
, {{ "glIsQuery" }} },
1179 const SymLoadStruct extSymbols
[] = {
1180 { (PRFuncPtr
*) &mSymbols
.fBeginQuery
, {{ "glBeginQueryEXT", "glBeginQueryANGLE" }} },
1181 { (PRFuncPtr
*) &mSymbols
.fGenQueries
, {{ "glGenQueriesEXT", "glGenQueriesANGLE" }} },
1182 { (PRFuncPtr
*) &mSymbols
.fDeleteQueries
, {{ "glDeleteQueriesEXT", "glDeleteQueriesANGLE" }} },
1183 { (PRFuncPtr
*) &mSymbols
.fEndQuery
, {{ "glEndQueryEXT", "glEndQueryANGLE" }} },
1184 { (PRFuncPtr
*) &mSymbols
.fGetQueryiv
, {{ "glGetQueryivEXT", "glGetQueryivANGLE" }} },
1185 { (PRFuncPtr
*) &mSymbols
.fGetQueryObjectuiv
, {{ "glGetQueryObjectuivEXT", "glGetQueryObjectuivANGLE" }} },
1186 { (PRFuncPtr
*) &mSymbols
.fIsQuery
, {{ "glIsQueryEXT", "glIsQueryANGLE" }} },
1189 if (!fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::query_objects
)) {
1190 MarkUnsupported(GLFeature::get_query_object_i64v
);
1191 MarkUnsupported(GLFeature::get_query_object_iv
);
1192 MarkUnsupported(GLFeature::occlusion_query
);
1193 MarkUnsupported(GLFeature::occlusion_query_boolean
);
1194 MarkUnsupported(GLFeature::occlusion_query2
);
1198 if (IsSupported(GLFeature::get_query_object_i64v
)) {
1199 const SymLoadStruct coreSymbols
[] = {
1200 { (PRFuncPtr
*) &mSymbols
.fGetQueryObjecti64v
, {{ "glGetQueryObjecti64v" }} },
1201 { (PRFuncPtr
*) &mSymbols
.fGetQueryObjectui64v
, {{ "glGetQueryObjectui64v" }} },
1204 const SymLoadStruct extSymbols
[] = {
1205 { (PRFuncPtr
*) &mSymbols
.fGetQueryObjecti64v
, {{ "glGetQueryObjecti64vEXT", "glGetQueryObjecti64vANGLE" }} },
1206 { (PRFuncPtr
*) &mSymbols
.fGetQueryObjectui64v
, {{ "glGetQueryObjectui64vEXT", "glGetQueryObjectui64vANGLE" }} },
1209 if (!fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::get_query_object_i64v
)) {
1210 MarkUnsupported(GLFeature::query_counter
);
1214 if (IsSupported(GLFeature::get_query_object_iv
)) {
1215 const SymLoadStruct coreSymbols
[] = {
1216 { (PRFuncPtr
*) &mSymbols
.fGetQueryObjectiv
, {{ "glGetQueryObjectiv" }} },
1219 const SymLoadStruct extSymbols
[] = {
1220 { (PRFuncPtr
*) &mSymbols
.fGetQueryObjectiv
, {{ "glGetQueryObjectivEXT", "glGetQueryObjectivANGLE" }} },
1223 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::get_query_object_iv
);
1226 if (IsSupported(GLFeature::clear_buffers
)) {
1227 const SymLoadStruct symbols
[] = {
1228 { (PRFuncPtr
*) &mSymbols
.fClearBufferfi
, {{ "glClearBufferfi", }} },
1229 { (PRFuncPtr
*) &mSymbols
.fClearBufferfv
, {{ "glClearBufferfv", }} },
1230 { (PRFuncPtr
*) &mSymbols
.fClearBufferiv
, {{ "glClearBufferiv", }} },
1231 { (PRFuncPtr
*) &mSymbols
.fClearBufferuiv
, {{ "glClearBufferuiv" }} },
1234 fnLoadForFeature(symbols
, GLFeature::clear_buffers
);
1237 if (IsSupported(GLFeature::copy_buffer
)) {
1238 const SymLoadStruct symbols
[] = {
1239 { (PRFuncPtr
*) &mSymbols
.fCopyBufferSubData
, {{ "glCopyBufferSubData" }} },
1242 fnLoadForFeature(symbols
, GLFeature::copy_buffer
);
1245 if (IsSupported(GLFeature::draw_buffers
)) {
1246 const SymLoadStruct coreSymbols
[] = {
1247 { (PRFuncPtr
*) &mSymbols
.fDrawBuffers
, {{ "glDrawBuffers" }} },
1250 const SymLoadStruct extSymbols
[] = {
1251 { (PRFuncPtr
*) &mSymbols
.fDrawBuffers
, {{ "glDrawBuffersARB", "glDrawBuffersEXT" }} },
1254 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::draw_buffers
);
1257 if (IsSupported(GLFeature::draw_buffers_indexed
)) {
1258 const SymLoadStruct coreSymbols
[] = {
1259 { (PRFuncPtr
*) &mSymbols
.fBlendEquationSeparatei
, {{ "glBlendEquationSeparatei" }} },
1260 { (PRFuncPtr
*) &mSymbols
.fBlendFuncSeparatei
, {{ "glBlendFuncSeparatei" }} },
1261 { (PRFuncPtr
*) &mSymbols
.fColorMaski
, {{ "glColorMaski" }} },
1262 { (PRFuncPtr
*) &mSymbols
.fDisablei
, {{ "glDisablei" }} },
1263 { (PRFuncPtr
*) &mSymbols
.fEnablei
, {{ "glEnablei" }} },
1266 const SymLoadStruct extSymbols
[] = {
1267 { (PRFuncPtr
*) &mSymbols
.fBlendEquationSeparatei
, {{ "glBlendEquationSeparateiOES" }} },
1268 { (PRFuncPtr
*) &mSymbols
.fBlendFuncSeparatei
, {{ "glBlendFuncSeparateiOES" }} },
1269 { (PRFuncPtr
*) &mSymbols
.fColorMaski
, {{ "glColorMaskiOES" }} },
1270 { (PRFuncPtr
*) &mSymbols
.fDisablei
, {{ "glDisableiOES" }} },
1271 { (PRFuncPtr
*) &mSymbols
.fEnablei
, {{ "glEnableiOES" }} },
1274 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::draw_buffers_indexed
);
1277 if (IsSupported(GLFeature::get_integer_indexed
)) {
1278 const SymLoadStruct coreSymbols
[] = {
1279 { (PRFuncPtr
*) &mSymbols
.fGetIntegeri_v
, {{ "glGetIntegeri_v" }} },
1282 const SymLoadStruct extSymbols
[] ={
1283 { (PRFuncPtr
*) &mSymbols
.fGetIntegeri_v
, {{ "glGetIntegerIndexedvEXT" }} },
1286 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::get_integer_indexed
);
1289 if (IsSupported(GLFeature::get_integer64_indexed
)) {
1290 const SymLoadStruct symbols
[] = {
1291 { (PRFuncPtr
*) &mSymbols
.fGetInteger64i_v
, {{ "glGetInteger64i_v" }} },
1294 fnLoadForFeature(symbols
, GLFeature::get_integer64_indexed
);
1297 if (IsSupported(GLFeature::gpu_shader4
)) {
1298 const SymLoadStruct symbols
[] = {
1299 { (PRFuncPtr
*) &mSymbols
.fGetVertexAttribIiv
, {{ "glGetVertexAttribIiv", "glGetVertexAttribIivEXT" }} },
1300 { (PRFuncPtr
*) &mSymbols
.fGetVertexAttribIuiv
, {{ "glGetVertexAttribIuiv", "glGetVertexAttribIuivEXT" }} },
1301 { (PRFuncPtr
*) &mSymbols
.fVertexAttribI4i
, {{ "glVertexAttribI4i", "glVertexAttribI4iEXT" }} },
1302 { (PRFuncPtr
*) &mSymbols
.fVertexAttribI4iv
, {{ "glVertexAttribI4iv", "glVertexAttribI4ivEXT" }} },
1303 { (PRFuncPtr
*) &mSymbols
.fVertexAttribI4ui
, {{ "glVertexAttribI4ui", "glVertexAttribI4uiEXT" }} },
1304 { (PRFuncPtr
*) &mSymbols
.fVertexAttribI4uiv
, {{ "glVertexAttribI4uiv", "glVertexAttribI4uivEXT" }} },
1305 { (PRFuncPtr
*) &mSymbols
.fVertexAttribIPointer
, {{ "glVertexAttribIPointer", "glVertexAttribIPointerEXT" }} },
1306 { (PRFuncPtr
*) &mSymbols
.fUniform1ui
, {{ "glUniform1ui", "glUniform1uiEXT" }} },
1307 { (PRFuncPtr
*) &mSymbols
.fUniform2ui
, {{ "glUniform2ui", "glUniform2uiEXT" }} },
1308 { (PRFuncPtr
*) &mSymbols
.fUniform3ui
, {{ "glUniform3ui", "glUniform3uiEXT" }} },
1309 { (PRFuncPtr
*) &mSymbols
.fUniform4ui
, {{ "glUniform4ui", "glUniform4uiEXT" }} },
1310 { (PRFuncPtr
*) &mSymbols
.fUniform1uiv
, {{ "glUniform1uiv", "glUniform1uivEXT" }} },
1311 { (PRFuncPtr
*) &mSymbols
.fUniform2uiv
, {{ "glUniform2uiv", "glUniform2uivEXT" }} },
1312 { (PRFuncPtr
*) &mSymbols
.fUniform3uiv
, {{ "glUniform3uiv", "glUniform3uivEXT" }} },
1313 { (PRFuncPtr
*) &mSymbols
.fUniform4uiv
, {{ "glUniform4uiv", "glUniform4uivEXT" }} },
1314 { (PRFuncPtr
*) &mSymbols
.fGetFragDataLocation
, {{ "glGetFragDataLocation", "glGetFragDataLocationEXT" }} },
1315 { (PRFuncPtr
*) &mSymbols
.fGetUniformuiv
, {{ "glGetUniformuiv", "glGetUniformuivEXT" }} },
1318 fnLoadForFeature(symbols
, GLFeature::gpu_shader4
);
1321 if (IsSupported(GLFeature::map_buffer_range
)) {
1322 const SymLoadStruct symbols
[] = {
1323 { (PRFuncPtr
*) &mSymbols
.fMapBufferRange
, {{ "glMapBufferRange" }} },
1324 { (PRFuncPtr
*) &mSymbols
.fFlushMappedBufferRange
, {{ "glFlushMappedBufferRange" }} },
1325 { (PRFuncPtr
*) &mSymbols
.fUnmapBuffer
, {{ "glUnmapBuffer" }} },
1328 fnLoadForFeature(symbols
, GLFeature::map_buffer_range
);
1331 if (IsSupported(GLFeature::texture_3D
)) {
1332 const SymLoadStruct coreSymbols
[] = {
1333 { (PRFuncPtr
*) &mSymbols
.fTexImage3D
, {{ "glTexImage3D" }} },
1334 { (PRFuncPtr
*) &mSymbols
.fTexSubImage3D
, {{ "glTexSubImage3D" }} },
1337 const SymLoadStruct extSymbols
[] = {
1338 { (PRFuncPtr
*) &mSymbols
.fTexImage3D
, {{ "glTexImage3DOES" }} },
1339 { (PRFuncPtr
*) &mSymbols
.fTexSubImage3D
, {{ "glTexSubImage3DOES" }} },
1342 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::texture_3D
);
1345 if (IsSupported(GLFeature::texture_3D_compressed
)) {
1346 const SymLoadStruct coreSymbols
[] = {
1347 { (PRFuncPtr
*) &mSymbols
.fCompressedTexImage3D
, {{ "glCompressedTexImage3D" }} },
1348 { (PRFuncPtr
*) &mSymbols
.fCompressedTexSubImage3D
, {{ "glCompressedTexSubImage3D" }} },
1351 const SymLoadStruct extSymbols
[] = {
1352 { (PRFuncPtr
*) &mSymbols
.fCompressedTexImage3D
, {{ "glCompressedTexImage3DARB", "glCompressedTexImage3DOES" }} },
1353 { (PRFuncPtr
*) &mSymbols
.fCompressedTexSubImage3D
, {{ "glCompressedTexSubImage3DARB", "glCompressedTexSubImage3DOES" }} },
1356 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::texture_3D_compressed
);
1359 if (IsSupported(GLFeature::texture_3D_copy
)) {
1360 const SymLoadStruct coreSymbols
[] = {
1361 { (PRFuncPtr
*) &mSymbols
.fCopyTexSubImage3D
, {{ "glCopyTexSubImage3D" }} },
1364 const SymLoadStruct extSymbols
[] = {
1365 { (PRFuncPtr
*) &mSymbols
.fCopyTexSubImage3D
, {{ "glCopyTexSubImage3DEXT", "glCopyTexSubImage3DOES" }} },
1368 fnLoadFeatureByCore(coreSymbols
, extSymbols
, GLFeature::texture_3D_copy
);
1371 if (IsSupported(GLFeature::uniform_buffer_object
)) {
1372 // Note: Don't query for glGetActiveUniformName because it is not
1373 // supported by GL ES 3.
1374 const SymLoadStruct symbols
[] = {
1375 { (PRFuncPtr
*) &mSymbols
.fGetUniformIndices
, {{ "glGetUniformIndices" }} },
1376 { (PRFuncPtr
*) &mSymbols
.fGetActiveUniformsiv
, {{ "glGetActiveUniformsiv" }} },
1377 { (PRFuncPtr
*) &mSymbols
.fGetUniformBlockIndex
, {{ "glGetUniformBlockIndex" }} },
1378 { (PRFuncPtr
*) &mSymbols
.fGetActiveUniformBlockiv
, {{ "glGetActiveUniformBlockiv" }} },
1379 { (PRFuncPtr
*) &mSymbols
.fGetActiveUniformBlockName
, {{ "glGetActiveUniformBlockName" }} },
1380 { (PRFuncPtr
*) &mSymbols
.fUniformBlockBinding
, {{ "glUniformBlockBinding" }} },
1383 fnLoadForFeature(symbols
, GLFeature::uniform_buffer_object
);
1386 if (IsSupported(GLFeature::uniform_matrix_nonsquare
)) {
1387 const SymLoadStruct symbols
[] = {
1388 { (PRFuncPtr
*) &mSymbols
.fUniformMatrix2x3fv
, {{ "glUniformMatrix2x3fv" }} },
1389 { (PRFuncPtr
*) &mSymbols
.fUniformMatrix2x4fv
, {{ "glUniformMatrix2x4fv" }} },
1390 { (PRFuncPtr
*) &mSymbols
.fUniformMatrix3x2fv
, {{ "glUniformMatrix3x2fv" }} },
1391 { (PRFuncPtr
*) &mSymbols
.fUniformMatrix3x4fv
, {{ "glUniformMatrix3x4fv" }} },
1392 { (PRFuncPtr
*) &mSymbols
.fUniformMatrix4x2fv
, {{ "glUniformMatrix4x2fv" }} },
1393 { (PRFuncPtr
*) &mSymbols
.fUniformMatrix4x3fv
, {{ "glUniformMatrix4x3fv" }} },
1396 fnLoadForFeature(symbols
, GLFeature::uniform_matrix_nonsquare
);
1399 if (IsSupported(GLFeature::internalformat_query
)) {
1400 const SymLoadStruct symbols
[] = {
1401 CORE_SYMBOL(GetInternalformativ
),
1404 fnLoadForFeature(symbols
, GLFeature::internalformat_query
);
1407 if (IsSupported(GLFeature::invalidate_framebuffer
)) {
1408 const SymLoadStruct symbols
[] = {
1409 { (PRFuncPtr
*) &mSymbols
.fInvalidateFramebuffer
, {{ "glInvalidateFramebuffer" }} },
1410 { (PRFuncPtr
*) &mSymbols
.fInvalidateSubFramebuffer
, {{ "glInvalidateSubFramebuffer" }} },
1413 fnLoadForFeature(symbols
, GLFeature::invalidate_framebuffer
);
1416 if (IsSupported(GLFeature::multiview
)) {
1417 const SymLoadStruct symbols
[] = {
1418 { (PRFuncPtr
*) &mSymbols
.fFramebufferTextureMultiview
, {{
1419 "glFramebufferTextureMultiviewOVR",
1420 "glFramebufferTextureMultiviewLayeredANGLE"
1424 fnLoadForFeature(symbols
, GLFeature::multiview
);
1427 if (IsSupported(GLFeature::prim_restart
)) {
1428 const SymLoadStruct symbols
[] = {
1429 { (PRFuncPtr
*) &mSymbols
.fPrimitiveRestartIndex
, {{ "glPrimitiveRestartIndex", "glPrimitiveRestartIndexNV" }} },
1432 fnLoadForFeature(symbols
, GLFeature::prim_restart
);
1435 if (IsExtensionSupported(KHR_debug
)) {
1436 const SymLoadStruct symbols
[] = {
1437 { (PRFuncPtr
*) &mSymbols
.fDebugMessageControl
, {{ "glDebugMessageControl", "glDebugMessageControlKHR", }} },
1438 { (PRFuncPtr
*) &mSymbols
.fDebugMessageInsert
, {{ "glDebugMessageInsert", "glDebugMessageInsertKHR", }} },
1439 { (PRFuncPtr
*) &mSymbols
.fDebugMessageCallback
, {{ "glDebugMessageCallback", "glDebugMessageCallbackKHR" }} },
1440 { (PRFuncPtr
*) &mSymbols
.fGetDebugMessageLog
, {{ "glGetDebugMessageLog", "glGetDebugMessageLogKHR", }} },
1441 { (PRFuncPtr
*) &mSymbols
.fGetPointerv
, {{ "glGetPointerv", "glGetPointervKHR", }} },
1442 { (PRFuncPtr
*) &mSymbols
.fPushDebugGroup
, {{ "glPushDebugGroup", "glPushDebugGroupKHR", }} },
1443 { (PRFuncPtr
*) &mSymbols
.fPopDebugGroup
, {{ "glPopDebugGroup", "glPopDebugGroupKHR", }} },
1444 { (PRFuncPtr
*) &mSymbols
.fObjectLabel
, {{ "glObjectLabel", "glObjectLabelKHR", }} },
1445 { (PRFuncPtr
*) &mSymbols
.fGetObjectLabel
, {{ "glGetObjectLabel", "glGetObjectLabelKHR", }} },
1446 { (PRFuncPtr
*) &mSymbols
.fObjectPtrLabel
, {{ "glObjectPtrLabel", "glObjectPtrLabelKHR", }} },
1447 { (PRFuncPtr
*) &mSymbols
.fGetObjectPtrLabel
, {{ "glGetObjectPtrLabel", "glGetObjectPtrLabelKHR", }} },
1450 fnLoadForExt(symbols
, KHR_debug
);
1453 if (IsExtensionSupported(NV_fence
)) {
1454 const SymLoadStruct symbols
[] = {
1455 { (PRFuncPtr
*) &mSymbols
.fGenFences
, {{ "glGenFencesNV" }} },
1456 { (PRFuncPtr
*) &mSymbols
.fDeleteFences
, {{ "glDeleteFencesNV" }} },
1457 { (PRFuncPtr
*) &mSymbols
.fSetFence
, {{ "glSetFenceNV" }} },
1458 { (PRFuncPtr
*) &mSymbols
.fTestFence
, {{ "glTestFenceNV" }} },
1459 { (PRFuncPtr
*) &mSymbols
.fFinishFence
, {{ "glFinishFenceNV" }} },
1460 { (PRFuncPtr
*) &mSymbols
.fIsFence
, {{ "glIsFenceNV" }} },
1461 { (PRFuncPtr
*) &mSymbols
.fGetFenceiv
, {{ "glGetFenceivNV" }} },
1464 fnLoadForExt(symbols
, NV_fence
);
1469 if (IsExtensionSupported(NV_texture_barrier
)) {
1470 const SymLoadStruct symbols
[] = {
1471 {(PRFuncPtr
*)&mSymbols
.fTextureBarrier
, {{"glTextureBarrierNV"}}},
1473 fnLoadForExt(symbols
, NV_texture_barrier
);
1476 if (IsSupported(GLFeature::read_buffer
)) {
1477 const SymLoadStruct symbols
[] = {CORE_SYMBOL(ReadBuffer
), END_SYMBOLS
};
1478 fnLoadForFeature(symbols
, GLFeature::read_buffer
);
1481 if (IsExtensionSupported(APPLE_framebuffer_multisample
)) {
1482 const SymLoadStruct symbols
[] = {
1483 CORE_SYMBOL(ResolveMultisampleFramebufferAPPLE
), END_SYMBOLS
};
1484 fnLoadForExt(symbols
, APPLE_framebuffer_multisample
);
1487 if (IsSupported(GLFeature::provoking_vertex
)) {
1488 const SymLoadStruct symbols
[] = {{(PRFuncPtr
*)&mSymbols
.fProvokingVertex
,
1490 "glProvokingVertex",
1491 "glProvokingVertexANGLE",
1492 "glProvokingVertexEXT",
1495 fnLoadForFeature(symbols
, GLFeature::provoking_vertex
);
1498 // Load developer symbols, don't fail if we can't find them.
1499 const SymLoadStruct devSymbols
[] = {CORE_SYMBOL(GetTexImage
),
1500 CORE_SYMBOL(GetTexLevelParameteriv
),
1502 const bool warnOnFailures
= ShouldSpew();
1503 (void)loader
.LoadSymbols(devSymbols
, warnOnFailures
);
1507 #undef CORE_EXT_SYMBOL2
1512 void GLContext::DebugCallback(GLenum source
, GLenum type
, GLuint id
,
1513 GLenum severity
, GLsizei length
,
1514 const GLchar
* message
) {
1515 nsAutoCString sourceStr
;
1517 case LOCAL_GL_DEBUG_SOURCE_API
:
1518 sourceStr
= "SOURCE_API"_ns
;
1520 case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM
:
1521 sourceStr
= "SOURCE_WINDOW_SYSTEM"_ns
;
1523 case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER
:
1524 sourceStr
= "SOURCE_SHADER_COMPILER"_ns
;
1526 case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY
:
1527 sourceStr
= "SOURCE_THIRD_PARTY"_ns
;
1529 case LOCAL_GL_DEBUG_SOURCE_APPLICATION
:
1530 sourceStr
= "SOURCE_APPLICATION"_ns
;
1532 case LOCAL_GL_DEBUG_SOURCE_OTHER
:
1533 sourceStr
= "SOURCE_OTHER"_ns
;
1536 sourceStr
= nsPrintfCString("<source 0x%04x>", source
);
1540 nsAutoCString typeStr
;
1542 case LOCAL_GL_DEBUG_TYPE_ERROR
:
1543 typeStr
= "TYPE_ERROR"_ns
;
1545 case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR
:
1546 typeStr
= "TYPE_DEPRECATED_BEHAVIOR"_ns
;
1548 case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR
:
1549 typeStr
= "TYPE_UNDEFINED_BEHAVIOR"_ns
;
1551 case LOCAL_GL_DEBUG_TYPE_PORTABILITY
:
1552 typeStr
= "TYPE_PORTABILITY"_ns
;
1554 case LOCAL_GL_DEBUG_TYPE_PERFORMANCE
:
1555 typeStr
= "TYPE_PERFORMANCE"_ns
;
1557 case LOCAL_GL_DEBUG_TYPE_OTHER
:
1558 typeStr
= "TYPE_OTHER"_ns
;
1560 case LOCAL_GL_DEBUG_TYPE_MARKER
:
1561 typeStr
= "TYPE_MARKER"_ns
;
1564 typeStr
= nsPrintfCString("<type 0x%04x>", type
);
1568 nsAutoCString sevStr
;
1570 case LOCAL_GL_DEBUG_SEVERITY_HIGH
:
1571 sevStr
= "SEVERITY_HIGH"_ns
;
1573 case LOCAL_GL_DEBUG_SEVERITY_MEDIUM
:
1574 sevStr
= "SEVERITY_MEDIUM"_ns
;
1576 case LOCAL_GL_DEBUG_SEVERITY_LOW
:
1577 sevStr
= "SEVERITY_LOW"_ns
;
1579 case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION
:
1580 sevStr
= "SEVERITY_NOTIFICATION"_ns
;
1583 sevStr
= nsPrintfCString("<severity 0x%04x>", severity
);
1587 printf_stderr("[KHR_debug: 0x%" PRIxPTR
"] ID %u: %s, %s, %s:\n %s\n",
1588 (uintptr_t)this, id
, sourceStr
.BeginReading(),
1589 typeStr
.BeginReading(), sevStr
.BeginReading(), message
);
1592 void GLContext::InitExtensions() {
1593 MOZ_GL_ASSERT(this, IsCurrent());
1595 std::vector
<nsCString
> driverExtensionList
;
1598 if (mSymbols
.fGetStringi
) {
1600 if (GetPotentialInteger(LOCAL_GL_NUM_EXTENSIONS
, (GLint
*)&count
)) {
1601 for (GLuint i
= 0; i
< count
; i
++) {
1603 const char* rawExt
= (const char*)fGetStringi(LOCAL_GL_EXTENSIONS
, i
);
1605 // We CANNOT use nsDependentCString here, because the spec doesn't
1606 // guarantee that the pointers returned are different, only that their
1607 // contents are. On Flame, each of these index string queries returns
1608 // the same address.
1609 driverExtensionList
.push_back(nsCString(rawExt
));
1615 const char* rawExts
= (const char*)fGetString(LOCAL_GL_EXTENSIONS
);
1617 nsDependentCString
exts(rawExts
);
1618 SplitByChar(exts
, ' ', &driverExtensionList
);
1621 const auto err
= fGetError();
1622 MOZ_ALWAYS_TRUE(!IsBadCallError(err
));
1624 const bool shouldDumpExts
= ShouldDumpExts();
1625 if (shouldDumpExts
) {
1626 printf_stderr("%i GL driver extensions: (*: recognized)\n",
1627 (uint32_t)driverExtensionList
.size());
1630 MarkBitfieldByStrings(driverExtensionList
, shouldDumpExts
, sExtensionNames
,
1631 &mAvailableExtensions
);
1633 if (WorkAroundDriverBugs()) {
1634 if (Vendor() == GLVendor::Qualcomm
) {
1635 // Some Adreno drivers do not report GL_OES_EGL_sync, but they really do
1637 MarkExtensionSupported(OES_EGL_sync
);
1640 if (Vendor() == GLVendor::ATI
) {
1641 // ATI drivers say this extension exists, but we can't
1642 // actually find the EGLImageTargetRenderbufferStorageOES
1643 // extension function pointer in the drivers.
1644 MarkExtensionUnsupported(OES_EGL_image
);
1647 if (Vendor() == GLVendor::Imagination
&& Renderer() == GLRenderer::SGX540
) {
1649 MarkExtensionUnsupported(OES_EGL_sync
);
1652 if (Vendor() == GLVendor::ARM
&& (Renderer() == GLRenderer::Mali400MP
||
1653 Renderer() == GLRenderer::Mali450MP
)) {
1655 MarkExtensionUnsupported(OES_EGL_image_external
);
1658 if (Renderer() == GLRenderer::AndroidEmulator
) {
1659 // the Android emulator, which we use to run B2G reftests on,
1660 // doesn't expose the OES_rgb8_rgba8 extension, but it seems to
1661 // support it (tautologically, as it only runs on desktop GL).
1662 MarkExtensionSupported(OES_rgb8_rgba8
);
1665 if (Vendor() == GLVendor::VMware
&&
1666 Renderer() == GLRenderer::GalliumLlvmpipe
) {
1667 // The llvmpipe driver that is used on linux try servers appears to have
1668 // buggy support for s3tc/dxt1 compressed textures.
1670 MarkExtensionUnsupported(EXT_texture_compression_s3tc
);
1671 MarkExtensionUnsupported(EXT_texture_compression_dxt1
);
1672 MarkExtensionUnsupported(ANGLE_texture_compression_dxt3
);
1673 MarkExtensionUnsupported(ANGLE_texture_compression_dxt5
);
1677 // Bug 1009642: On OSX Mavericks (10.9), the driver for Intel HD
1678 // 3000 appears to be buggy WRT updating sub-images of S3TC
1679 // textures with glCompressedTexSubImage2D. Works on Intel HD 4000
1680 // and Intel HD 5000/Iris that I tested.
1681 // Bug 1124996: Appears to be the same on OSX Yosemite (10.10)
1682 if (Renderer() == GLRenderer::IntelHD3000
) {
1683 MarkExtensionUnsupported(EXT_texture_compression_s3tc
);
1686 // OSX supports EXT_texture_sRGB in Legacy contexts, but not in Core
1687 // contexts. Though EXT_texture_sRGB was included into GL2.1, it *excludes*
1688 // the interactions with s3tc. Strictly speaking, you must advertize support
1689 // for EXT_texture_sRGB in order to allow for srgb+s3tc on desktop GL. The
1690 // omission of EXT_texture_sRGB in OSX Core contexts appears to be a bug.
1691 MarkExtensionSupported(EXT_texture_sRGB
);
1695 if (shouldDumpExts
) {
1696 printf_stderr("\nActivated extensions:\n");
1698 for (size_t i
= 0; i
< mAvailableExtensions
.size(); i
++) {
1699 if (!mAvailableExtensions
[i
]) continue;
1701 const char* ext
= sExtensionNames
[i
];
1702 printf_stderr("[%i] %s\n", (uint32_t)i
, ext
);
1707 void GLContext::PlatformStartup() {
1708 RegisterStrongMemoryReporter(new GfxTexturesReporter());
1711 // Common code for checking for both GL extensions and GLX extensions.
1712 bool GLContext::ListHasExtension(const GLubyte
* extensions
,
1713 const char* extension
) {
1714 // fix bug 612572 - we were crashing as we were calling this function with
1716 if (extensions
== nullptr || extension
== nullptr) return false;
1718 const GLubyte
* start
;
1720 GLubyte
* terminator
;
1722 /* Extension names should not have spaces. */
1723 where
= (GLubyte
*)strchr(extension
, ' ');
1724 if (where
|| *extension
== '\0') return false;
1727 * It takes a bit of care to be fool-proof about parsing the
1728 * OpenGL extensions string. Don't be fooled by sub-strings,
1733 where
= (GLubyte
*)strstr((const char*)start
, extension
);
1737 terminator
= where
+ strlen(extension
);
1738 if (where
== start
|| *(where
- 1) == ' ') {
1739 if (*terminator
== ' ' || *terminator
== '\0') {
1748 bool GLContext::IsFramebufferComplete(GLuint fb
, GLenum
* pStatus
) {
1751 ScopedBindFramebuffer
autoFB(this, fb
);
1752 MOZ_GL_ASSERT(this, fIsFramebuffer(fb
));
1754 GLenum status
= fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER
);
1755 if (pStatus
) *pStatus
= status
;
1757 return status
== LOCAL_GL_FRAMEBUFFER_COMPLETE
;
1760 void GLContext::AttachBuffersToFB(GLuint colorTex
, GLuint colorRB
,
1761 GLuint depthRB
, GLuint stencilRB
, GLuint fb
,
1764 MOZ_ASSERT(!(colorTex
&& colorRB
));
1766 ScopedBindFramebuffer
autoFB(this, fb
);
1767 MOZ_GL_ASSERT(this, fIsFramebuffer(fb
)); // It only counts after being bound.
1770 MOZ_GL_ASSERT(this, fIsTexture(colorTex
));
1771 MOZ_ASSERT(target
== LOCAL_GL_TEXTURE_2D
||
1772 target
== LOCAL_GL_TEXTURE_RECTANGLE_ARB
);
1773 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER
, LOCAL_GL_COLOR_ATTACHMENT0
,
1774 target
, colorTex
, 0);
1775 } else if (colorRB
) {
1776 // On the Android 4.3 emulator, IsRenderbuffer may return false incorrectly.
1777 MOZ_GL_ASSERT(this, fIsRenderbuffer(colorRB
) ||
1778 Renderer() == GLRenderer::AndroidEmulator
);
1779 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER
, LOCAL_GL_COLOR_ATTACHMENT0
,
1780 LOCAL_GL_RENDERBUFFER
, colorRB
);
1784 MOZ_GL_ASSERT(this, fIsRenderbuffer(depthRB
) ||
1785 Renderer() == GLRenderer::AndroidEmulator
);
1786 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER
, LOCAL_GL_DEPTH_ATTACHMENT
,
1787 LOCAL_GL_RENDERBUFFER
, depthRB
);
1791 MOZ_GL_ASSERT(this, fIsRenderbuffer(stencilRB
) ||
1792 Renderer() == GLRenderer::AndroidEmulator
);
1793 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER
, LOCAL_GL_STENCIL_ATTACHMENT
,
1794 LOCAL_GL_RENDERBUFFER
, stencilRB
);
1798 bool GLContext::AssembleOffscreenFBs(const GLuint colorMSRB
,
1799 const GLuint depthRB
,
1800 const GLuint stencilRB
,
1801 const GLuint texture
, GLuint
* drawFB_out
,
1802 GLuint
* readFB_out
) {
1803 if (!colorMSRB
&& !texture
) {
1804 MOZ_ASSERT(!depthRB
&& !stencilRB
);
1806 if (drawFB_out
) *drawFB_out
= 0;
1807 if (readFB_out
) *readFB_out
= 0;
1812 ScopedBindFramebuffer
autoFB(this);
1819 fGenFramebuffers(1, &readFB
);
1821 fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER
, LOCAL_GL_COLOR_ATTACHMENT0
,
1822 LOCAL_GL_TEXTURE_2D
, texture
, 0);
1827 fGenFramebuffers(1, &drawFB
);
1829 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER
, LOCAL_GL_COLOR_ATTACHMENT0
,
1830 LOCAL_GL_RENDERBUFFER
, colorMSRB
);
1834 MOZ_ASSERT(GetIntAs
<GLuint
>(LOCAL_GL_FRAMEBUFFER_BINDING
) == drawFB
);
1837 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER
, LOCAL_GL_DEPTH_ATTACHMENT
,
1838 LOCAL_GL_RENDERBUFFER
, depthRB
);
1842 fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER
, LOCAL_GL_STENCIL_ATTACHMENT
,
1843 LOCAL_GL_RENDERBUFFER
, stencilRB
);
1846 // We should be all resized. Check for framebuffer completeness.
1848 bool isComplete
= true;
1850 if (!IsFramebufferComplete(drawFB
, &status
)) {
1851 NS_WARNING("DrawFBO: Incomplete");
1852 #ifdef MOZ_GL_DEBUG_BUILD
1854 printf_stderr("Framebuffer status: %X\n", status
);
1860 if (!IsFramebufferComplete(readFB
, &status
)) {
1861 NS_WARNING("ReadFBO: Incomplete");
1862 #ifdef MOZ_GL_DEBUG_BUILD
1864 printf_stderr("Framebuffer status: %X\n", status
);
1871 *drawFB_out
= drawFB
;
1872 } else if (drawFB
) {
1873 MOZ_CRASH("drawFB created when not requested!");
1877 *readFB_out
= readFB
;
1878 } else if (readFB
) {
1879 MOZ_CRASH("readFB created when not requested!");
1885 void GLContext::MarkDestroyed() {
1886 if (IsDestroyed()) return;
1890 // Null these before they're naturally nulled after dtor, as we want GLContext
1891 // to still be alive in *their* dtors.
1892 mBlitHelper
= nullptr;
1893 mReadTexImageHelper
= nullptr;
1895 mContextLost
= true;
1901 #ifdef MOZ_GL_DEBUG_BUILD
1903 void GLContext::AssertNotPassingStackBufferToTheGL(const void* ptr
) {
1904 int somethingOnTheStack
;
1905 const void* someStackPtr
= &somethingOnTheStack
;
1906 const int page_bits
= 12;
1907 intptr_t page
= reinterpret_cast<uintptr_t>(ptr
) >> page_bits
;
1908 intptr_t someStackPage
=
1909 reinterpret_cast<uintptr_t>(someStackPtr
) >> page_bits
;
1910 uintptr_t pageDistance
= std::abs(page
- someStackPage
);
1912 // Explanation for the "distance <= 1" check here as opposed to just
1913 // an equality check.
1915 // Here we assume that pages immediately adjacent to the someStackAddress
1916 // page, are also stack pages. That allows to catch the case where the calling
1917 // frame put a buffer on the stack, and we just crossed the page boundary.
1918 // That is likely to happen, precisely, when using stack arrays. I hit that
1919 // specifically with CompositorOGL::Initialize.
1921 // In theory we could be unlucky and wrongly assert here. If that happens,
1922 // it will only affect debug builds, and looking at stacks we'll be able to
1923 // see that this assert is wrong and revert to the conservative and safe
1924 // approach of only asserting when address and someStackAddress are
1925 // on the same page.
1926 bool isStackAddress
= pageDistance
<= 1;
1927 MOZ_ASSERT(!isStackAddress
,
1928 "Please don't pass stack arrays to the GL. "
1929 "Consider using HeapCopyOfStackArray. "
1930 "See bug 1005658.");
1933 void GLContext::CreatedProgram(GLContext
* aOrigin
, GLuint aName
) {
1934 mTrackedPrograms
.AppendElement(NamedResource(aOrigin
, aName
));
1937 void GLContext::CreatedShader(GLContext
* aOrigin
, GLuint aName
) {
1938 mTrackedShaders
.AppendElement(NamedResource(aOrigin
, aName
));
1941 void GLContext::CreatedBuffers(GLContext
* aOrigin
, GLsizei aCount
,
1943 for (GLsizei i
= 0; i
< aCount
; ++i
) {
1944 mTrackedBuffers
.AppendElement(NamedResource(aOrigin
, aNames
[i
]));
1948 void GLContext::CreatedQueries(GLContext
* aOrigin
, GLsizei aCount
,
1950 for (GLsizei i
= 0; i
< aCount
; ++i
) {
1951 mTrackedQueries
.AppendElement(NamedResource(aOrigin
, aNames
[i
]));
1955 void GLContext::CreatedTextures(GLContext
* aOrigin
, GLsizei aCount
,
1957 for (GLsizei i
= 0; i
< aCount
; ++i
) {
1958 mTrackedTextures
.AppendElement(NamedResource(aOrigin
, aNames
[i
]));
1962 void GLContext::CreatedFramebuffers(GLContext
* aOrigin
, GLsizei aCount
,
1964 for (GLsizei i
= 0; i
< aCount
; ++i
) {
1965 mTrackedFramebuffers
.AppendElement(NamedResource(aOrigin
, aNames
[i
]));
1969 void GLContext::CreatedRenderbuffers(GLContext
* aOrigin
, GLsizei aCount
,
1971 for (GLsizei i
= 0; i
< aCount
; ++i
) {
1972 mTrackedRenderbuffers
.AppendElement(NamedResource(aOrigin
, aNames
[i
]));
1976 static void RemoveNamesFromArray(GLContext
* aOrigin
, GLsizei aCount
,
1977 const GLuint
* aNames
,
1978 nsTArray
<GLContext::NamedResource
>& aArray
) {
1979 for (GLsizei j
= 0; j
< aCount
; ++j
) {
1980 GLuint name
= aNames
[j
];
1981 // name 0 can be ignored
1982 if (name
== 0) continue;
1984 for (uint32_t i
= 0; i
< aArray
.Length(); ++i
) {
1985 if (aArray
[i
].name
== name
) {
1986 aArray
.RemoveElementAt(i
);
1993 void GLContext::DeletedProgram(GLContext
* aOrigin
, GLuint aName
) {
1994 RemoveNamesFromArray(aOrigin
, 1, &aName
, mTrackedPrograms
);
1997 void GLContext::DeletedShader(GLContext
* aOrigin
, GLuint aName
) {
1998 RemoveNamesFromArray(aOrigin
, 1, &aName
, mTrackedShaders
);
2001 void GLContext::DeletedBuffers(GLContext
* aOrigin
, GLsizei aCount
,
2002 const GLuint
* aNames
) {
2003 RemoveNamesFromArray(aOrigin
, aCount
, aNames
, mTrackedBuffers
);
2006 void GLContext::DeletedQueries(GLContext
* aOrigin
, GLsizei aCount
,
2007 const GLuint
* aNames
) {
2008 RemoveNamesFromArray(aOrigin
, aCount
, aNames
, mTrackedQueries
);
2011 void GLContext::DeletedTextures(GLContext
* aOrigin
, GLsizei aCount
,
2012 const GLuint
* aNames
) {
2013 RemoveNamesFromArray(aOrigin
, aCount
, aNames
, mTrackedTextures
);
2016 void GLContext::DeletedFramebuffers(GLContext
* aOrigin
, GLsizei aCount
,
2017 const GLuint
* aNames
) {
2018 RemoveNamesFromArray(aOrigin
, aCount
, aNames
, mTrackedFramebuffers
);
2021 void GLContext::DeletedRenderbuffers(GLContext
* aOrigin
, GLsizei aCount
,
2022 const GLuint
* aNames
) {
2023 RemoveNamesFromArray(aOrigin
, aCount
, aNames
, mTrackedRenderbuffers
);
2026 static void MarkContextDestroyedInArray(
2027 GLContext
* aContext
, nsTArray
<GLContext::NamedResource
>& aArray
) {
2028 for (uint32_t i
= 0; i
< aArray
.Length(); ++i
) {
2029 if (aArray
[i
].origin
== aContext
) aArray
[i
].originDeleted
= true;
2033 void GLContext::SharedContextDestroyed(GLContext
* aChild
) {
2034 MarkContextDestroyedInArray(aChild
, mTrackedPrograms
);
2035 MarkContextDestroyedInArray(aChild
, mTrackedShaders
);
2036 MarkContextDestroyedInArray(aChild
, mTrackedTextures
);
2037 MarkContextDestroyedInArray(aChild
, mTrackedFramebuffers
);
2038 MarkContextDestroyedInArray(aChild
, mTrackedRenderbuffers
);
2039 MarkContextDestroyedInArray(aChild
, mTrackedBuffers
);
2040 MarkContextDestroyedInArray(aChild
, mTrackedQueries
);
2043 static void ReportArrayContents(
2044 const char* title
, const nsTArray
<GLContext::NamedResource
>& aArray
) {
2045 if (aArray
.Length() == 0) return;
2047 printf_stderr("%s:\n", title
);
2049 nsTArray
<GLContext::NamedResource
> copy(aArray
.Clone());
2052 // Accumulate the output in a buffer to avoid interleaved output.
2055 GLContext
* lastContext
= nullptr;
2056 for (uint32_t i
= 0; i
< copy
.Length(); ++i
) {
2057 if (lastContext
!= copy
[i
].origin
) {
2059 printf_stderr("%s\n", line
.BeginReading());
2062 line
.Append(nsPrintfCString(" [%p - %s] ", copy
[i
].origin
,
2063 copy
[i
].originDeleted
? "deleted" : "live"));
2064 lastContext
= copy
[i
].origin
;
2066 line
.AppendInt(copy
[i
].name
);
2069 printf_stderr("%s\n", line
.BeginReading());
2072 void GLContext::ReportOutstandingNames() {
2073 if (!ShouldSpew()) return;
2075 printf_stderr("== GLContext %p Outstanding ==\n", this);
2077 ReportArrayContents("Outstanding Textures", mTrackedTextures
);
2078 ReportArrayContents("Outstanding Buffers", mTrackedBuffers
);
2079 ReportArrayContents("Outstanding Queries", mTrackedQueries
);
2080 ReportArrayContents("Outstanding Programs", mTrackedPrograms
);
2081 ReportArrayContents("Outstanding Shaders", mTrackedShaders
);
2082 ReportArrayContents("Outstanding Framebuffers", mTrackedFramebuffers
);
2083 ReportArrayContents("Outstanding Renderbuffers", mTrackedRenderbuffers
);
2086 #endif // ifdef MOZ_GL_DEBUG_BUILD
2088 bool GLContext::IsOffscreenSizeAllowed(const IntSize
& aSize
) const {
2089 int32_t biggerDimension
= std::max(aSize
.width
, aSize
.height
);
2090 int32_t maxAllowed
= std::min(mMaxRenderbufferSize
, mMaxTextureSize
);
2091 return biggerDimension
<= maxAllowed
;
2094 bool GLContext::IsValidOwningThread() const {
2095 if (!mOwningThreadId
) return true; // Free for all!
2096 return PlatformThread::CurrentId() == *mOwningThreadId
;
2099 GLBlitHelper
* GLContext::BlitHelper() {
2101 mBlitHelper
.reset(new GLBlitHelper(this));
2104 return mBlitHelper
.get();
2107 GLReadTexImageHelper
* GLContext::ReadTexImageHelper() {
2108 if (!mReadTexImageHelper
) {
2109 mReadTexImageHelper
= MakeUnique
<GLReadTexImageHelper
>(this);
2112 return mReadTexImageHelper
.get();
2115 void GLContext::FlushIfHeavyGLCallsSinceLastFlush() {
2116 if (!mHeavyGLCallsSinceLastFlush
) {
2119 if (MakeCurrent()) {
2125 bool GLContext::ShouldDumpExts() { return gfxEnv::MOZ_GL_DUMP_EXTS(); }
2127 bool DoesStringMatch(const char* aString
, const char* aWantedString
) {
2128 if (!aString
|| !aWantedString
) return false;
2130 const char* occurrence
= strstr(aString
, aWantedString
);
2132 // aWanted not found
2133 if (!occurrence
) return false;
2135 // aWantedString preceded by alpha character
2136 if (occurrence
!= aString
&& isalpha(*(occurrence
- 1))) return false;
2138 // aWantedVendor followed by alpha character
2139 const char* afterOccurrence
= occurrence
+ strlen(aWantedString
);
2140 if (isalpha(*afterOccurrence
)) return false;
2146 bool GLContext::ShouldSpew() { return gfxEnv::MOZ_GL_SPEW(); }
2148 void SplitByChar(const nsACString
& str
, const char delim
,
2149 std::vector
<nsCString
>* const out
) {
2152 int32_t end
= str
.FindChar(' ', start
);
2153 if (end
== -1) break;
2155 uint32_t len
= (uint32_t)end
- start
;
2156 nsDependentCSubstring
substr(str
, start
, len
);
2157 out
->push_back(nsCString(substr
));
2162 nsDependentCSubstring
substr(str
, start
);
2163 out
->push_back(nsCString(substr
));
2166 void GLContext::fCopyTexImage2D(GLenum target
, GLint level
,
2167 GLenum internalformat
, GLint x
, GLint y
,
2168 GLsizei width
, GLsizei height
, GLint border
) {
2169 if (!IsTextureSizeSafeToPassToDriver(target
, width
, height
)) {
2170 // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2171 // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2179 raw_fCopyTexImage2D(target
, level
, internalformat
, x
, y
, width
, height
,
2184 void GLContext::fGetIntegerv(const GLenum pname
, GLint
* const params
) const {
2185 const auto AssertBinding
= [&](const char* const name
, const GLenum binding
,
2186 const GLuint expected
) {
2187 if (MOZ_LIKELY(!mDebugFlags
)) return;
2189 raw_fGetIntegerv(binding
, (GLint
*)&actual
);
2190 if (actual
!= expected
) {
2191 gfxCriticalError() << "Misprediction: " << name
<< " expected "
2192 << expected
<< ", was " << actual
;
2197 case LOCAL_GL_MAX_TEXTURE_SIZE
:
2198 MOZ_ASSERT(mMaxTextureSize
> 0);
2199 *params
= mMaxTextureSize
;
2202 case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE
:
2203 MOZ_ASSERT(mMaxCubeMapTextureSize
> 0);
2204 *params
= mMaxCubeMapTextureSize
;
2207 case LOCAL_GL_MAX_RENDERBUFFER_SIZE
:
2208 MOZ_ASSERT(mMaxRenderbufferSize
> 0);
2209 *params
= mMaxRenderbufferSize
;
2212 case LOCAL_GL_VIEWPORT
:
2213 for (size_t i
= 0; i
< 4; i
++) {
2214 params
[i
] = mViewportRect
[i
];
2218 case LOCAL_GL_SCISSOR_BOX
:
2219 for (size_t i
= 0; i
< 4; i
++) {
2220 params
[i
] = mScissorRect
[i
];
2224 case LOCAL_GL_DRAW_FRAMEBUFFER_BINDING
:
2225 if (mElideDuplicateBindFramebuffers
) {
2226 static_assert(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING
==
2227 LOCAL_GL_FRAMEBUFFER_BINDING
);
2228 AssertBinding("GL_DRAW_FRAMEBUFFER_BINDING",
2229 LOCAL_GL_DRAW_FRAMEBUFFER_BINDING
, mCachedDrawFb
);
2230 *params
= static_cast<GLint
>(mCachedDrawFb
);
2235 case LOCAL_GL_READ_FRAMEBUFFER_BINDING
:
2236 if (mElideDuplicateBindFramebuffers
) {
2237 if (IsSupported(GLFeature::framebuffer_blit
)) {
2238 AssertBinding("GL_READ_FRAMEBUFFER_BINDING",
2239 LOCAL_GL_READ_FRAMEBUFFER_BINDING
, mCachedReadFb
);
2241 *params
= static_cast<GLint
>(mCachedReadFb
);
2249 raw_fGetIntegerv(pname
, params
);
2252 void GLContext::fReadPixels(GLint x
, GLint y
, GLsizei width
, GLsizei height
,
2253 GLenum format
, GLenum type
, GLvoid
* pixels
) {
2255 raw_fReadPixels(x
, y
, width
, height
, format
, type
, pixels
);
2258 // Check if GL is giving back 1.0 alpha for
2259 // RGBA reads to RGBA images from no-alpha buffers.
2261 if (WorkAroundDriverBugs() && Vendor() == gl::GLVendor::NVIDIA
&&
2262 format
== LOCAL_GL_RGBA
&& type
== LOCAL_GL_UNSIGNED_BYTE
&&
2263 !IsCoreProfile() && width
&& height
) {
2264 GLint alphaBits
= 0;
2265 fGetIntegerv(LOCAL_GL_ALPHA_BITS
, &alphaBits
);
2267 const uint32_t alphaMask
= 0xff000000;
2269 uint32_t* itr
= (uint32_t*)pixels
;
2270 uint32_t testPixel
= *itr
;
2271 if ((testPixel
& alphaMask
) != alphaMask
) {
2272 // We need to set the alpha channel to 1.0 manually.
2274 itr
+ width
* height
; // Stride is guaranteed to be width*4.
2276 for (; itr
!= itrEnd
; itr
++) {
2285 void GLContext::fDeleteFramebuffers(GLsizei n
, const GLuint
* names
) {
2286 // Avoid crash by flushing before glDeleteFramebuffers. See bug 1194923.
2287 if (mNeedsFlushBeforeDeleteFB
) {
2291 if (n
== 1 && *names
== 0) {
2292 // Deleting framebuffer 0 causes hangs on the DROID. See bug 623228.
2294 raw_fDeleteFramebuffers(n
, names
);
2296 TRACKING_CONTEXT(DeletedFramebuffers(this, n
, names
));
2299 #ifdef MOZ_WIDGET_ANDROID
2301 * Conservatively estimate whether there is enough available
2302 * contiguous virtual address space to map a newly allocated texture.
2304 static bool WillTextureMapSucceed(GLsizei width
, GLsizei height
, GLenum format
,
2306 bool willSucceed
= false;
2307 // Some drivers leave large gaps between textures, so require
2308 // there to be double the actual size of the texture available.
2309 size_t size
= width
* height
* GetBytesPerTexel(format
, type
) * 2;
2311 void* p
= mmap(nullptr, size
, PROT_NONE
, MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
2312 if (p
!= MAP_FAILED
) {
2319 #endif // MOZ_WIDGET_ANDROID
2321 void GLContext::fTexImage2D(GLenum target
, GLint level
, GLint internalformat
,
2322 GLsizei width
, GLsizei height
, GLint border
,
2323 GLenum format
, GLenum type
, const GLvoid
* pixels
) {
2324 if (!IsTextureSizeSafeToPassToDriver(target
, width
, height
)) {
2325 // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
2326 // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
2332 #if MOZ_WIDGET_ANDROID
2333 if (mTextureAllocCrashesOnMapFailure
) {
2334 // We have no way of knowing whether this texture already has
2335 // storage allocated for it, and therefore whether this check
2336 // is necessary. We must therefore assume it does not and
2337 // always perform the check.
2338 if (!WillTextureMapSucceed(width
, height
, internalformat
, type
)) {
2343 raw_fTexImage2D(target
, level
, internalformat
, width
, height
, border
, format
,
2347 UniquePtr
<Texture
> CreateTexture(GLContext
& gl
, const gfx::IntSize
& size
) {
2348 const GLenum target
= LOCAL_GL_TEXTURE_2D
;
2349 const GLenum format
= LOCAL_GL_RGBA
;
2351 auto tex
= MakeUnique
<Texture
>(gl
);
2352 ScopedBindTexture
autoTex(&gl
, tex
->name
, target
);
2354 gl
.fTexParameteri(target
, LOCAL_GL_TEXTURE_MIN_FILTER
, LOCAL_GL_LINEAR
);
2355 gl
.fTexParameteri(target
, LOCAL_GL_TEXTURE_MAG_FILTER
, LOCAL_GL_LINEAR
);
2356 gl
.fTexParameteri(target
, LOCAL_GL_TEXTURE_WRAP_S
, LOCAL_GL_CLAMP_TO_EDGE
);
2357 gl
.fTexParameteri(target
, LOCAL_GL_TEXTURE_WRAP_T
, LOCAL_GL_CLAMP_TO_EDGE
);
2359 gl
.fTexImage2D(target
, 0, format
, size
.width
, size
.height
, 0, format
,
2360 LOCAL_GL_UNSIGNED_BYTE
, nullptr);
2365 uint32_t GetBytesPerTexel(GLenum format
, GLenum type
) {
2366 // If there is no defined format or type, we're not taking up any memory
2367 if (!format
|| !type
) {
2371 if (format
== LOCAL_GL_DEPTH_COMPONENT
) {
2372 if (type
== LOCAL_GL_UNSIGNED_SHORT
)
2374 else if (type
== LOCAL_GL_UNSIGNED_INT
)
2376 } else if (format
== LOCAL_GL_DEPTH_STENCIL
) {
2377 if (type
== LOCAL_GL_UNSIGNED_INT_24_8_EXT
) return 4;
2380 if (type
== LOCAL_GL_UNSIGNED_BYTE
|| type
== LOCAL_GL_FLOAT
||
2381 type
== LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV
) {
2382 uint32_t multiplier
= type
== LOCAL_GL_UNSIGNED_BYTE
? 1 : 4;
2384 case LOCAL_GL_ALPHA
:
2385 case LOCAL_GL_LUMINANCE
:
2387 return 1 * multiplier
;
2388 case LOCAL_GL_LUMINANCE_ALPHA
:
2390 return 2 * multiplier
;
2392 return 3 * multiplier
;
2394 case LOCAL_GL_BGRA_EXT
:
2395 return 4 * multiplier
;
2399 } else if (type
== LOCAL_GL_UNSIGNED_SHORT_4_4_4_4
||
2400 type
== LOCAL_GL_UNSIGNED_SHORT_5_5_5_1
||
2401 type
== LOCAL_GL_UNSIGNED_SHORT_5_6_5
||
2402 type
== LOCAL_GL_UNSIGNED_SHORT
) {
2406 gfxCriticalError() << "Unknown texture type " << type
<< " or format "
2411 void GLContext::ResetTLSCurrentContext() {
2412 if (sCurrentContext
.init()) {
2413 sCurrentContext
.set(nullptr);
2417 bool GLContext::MakeCurrent(bool aForce
) const {
2418 if (MOZ_UNLIKELY(IsContextLost())) return false;
2420 if (MOZ_LIKELY(!aForce
)) {
2422 if (mUseTLSIsCurrent
&& sCurrentContext
.init()) {
2423 isCurrent
= (sCurrentContext
.get() == 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 if (sCurrentContext
.init()) {
2443 sCurrentContext
.set(this);
2448 void GLContext::ResetSyncCallCount(const char* resetReason
) const {
2450 printf_stderr("On %s, mSyncGLCallCount = %" PRIu64
"\n", resetReason
,
2454 mSyncGLCallCount
= 0;
2459 bool CheckContextLost(const GLContext
* const gl
) {
2460 return gl
->CheckContextLost();
2465 GLenum
GLContext::GetError() const {
2466 if (mContextLost
) return LOCAL_GL_CONTEXT_LOST
;
2468 if (mImplicitMakeCurrent
) {
2469 (void)MakeCurrent();
2472 const auto fnGetError
= [&]() {
2473 const auto ret
= mSymbols
.fGetError();
2474 if (ret
== LOCAL_GL_CONTEXT_LOST
) {
2475 OnContextLostError();
2476 mTopError
= ret
; // Promote to top!
2481 auto ret
= fnGetError();
2484 auto flushedErr
= ret
;
2486 while (flushedErr
&& !mContextLost
) {
2488 gfxCriticalError() << "Flushing glGetError still "
2489 << gfx::hexa(flushedErr
) << " after " << i
2493 flushedErr
= fnGetError();
2503 if (mDebugFlags
& DebugFlagTrace
) {
2504 const auto errStr
= GLErrorToString(ret
);
2505 printf_stderr("[gl:%p] GetError() -> %s\n", this, errStr
.c_str());
2510 GLenum
GLContext::fGetGraphicsResetStatus() const {
2514 if (mSymbols
.fGetGraphicsResetStatus
) {
2515 if (mImplicitMakeCurrent
) {
2516 (void)MakeCurrent();
2518 ret
= mSymbols
.fGetGraphicsResetStatus();
2520 if (!MakeCurrent(true)) {
2521 ret
= LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB
;
2525 if (mDebugFlags
& DebugFlagTrace
) {
2526 printf_stderr("[gl:%p] GetGraphicsResetStatus() -> 0x%04x\n", this, ret
);
2532 void GLContext::OnContextLostError() const {
2533 if (mDebugFlags
& DebugFlagTrace
) {
2534 printf_stderr("[gl:%p] CONTEXT_LOST\n", this);
2536 mContextLost
= true;
2541 /*static*/ std::string
GLContext::GLErrorToString(const GLenum err
) {
2543 case LOCAL_GL_NO_ERROR
:
2544 return "GL_NO_ERROR";
2545 case LOCAL_GL_INVALID_ENUM
:
2546 return "GL_INVALID_ENUM";
2547 case LOCAL_GL_INVALID_VALUE
:
2548 return "GL_INVALID_VALUE";
2549 case LOCAL_GL_INVALID_OPERATION
:
2550 return "GL_INVALID_OPERATION";
2551 case LOCAL_GL_STACK_OVERFLOW
:
2552 return "GL_STACK_OVERFLOW";
2553 case LOCAL_GL_STACK_UNDERFLOW
:
2554 return "GL_STACK_UNDERFLOW";
2555 case LOCAL_GL_OUT_OF_MEMORY
:
2556 return "GL_OUT_OF_MEMORY";
2557 case LOCAL_GL_TABLE_TOO_LARGE
:
2558 return "GL_TABLE_TOO_LARGE";
2559 case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION
:
2560 return "GL_INVALID_FRAMEBUFFER_OPERATION";
2561 case LOCAL_GL_CONTEXT_LOST
:
2562 return "GL_CONTEXT_LOST";
2565 const nsPrintfCString
hex("<enum 0x%04x>", err
);
2566 return hex
.BeginReading();
2571 void GLContext::BeforeGLCall_Debug(const char* const funcName
) const {
2572 MOZ_ASSERT(mDebugFlags
);
2574 if (mDebugFlags
& DebugFlagTrace
) {
2575 printf_stderr("[gl:%p] > %s\n", this, funcName
);
2578 MOZ_ASSERT(!mDebugErrorScope
);
2579 mDebugErrorScope
.reset(new LocalErrorScope(*this));
2582 void GLContext::AfterGLCall_Debug(const char* const funcName
) const {
2583 MOZ_ASSERT(mDebugFlags
);
2585 // calling fFinish() immediately after every GL call makes sure that if this
2586 // GL command crashes, the stack trace will actually point to it. Otherwise,
2587 // OpenGL being an asynchronous API, stack traces tend to be meaningless
2590 const auto err
= mDebugErrorScope
->GetError();
2591 mDebugErrorScope
= nullptr;
2596 if (mDebugFlags
& DebugFlagTrace
) {
2597 printf_stderr("[gl:%p] < %s [%s]\n", this, funcName
,
2598 GLErrorToString(err
).c_str());
2601 if (err
&& !mLocalErrorScopeStack
.size()) {
2602 const auto errStr
= GLErrorToString(err
);
2603 const auto text
= nsPrintfCString("%s: Generated unexpected %s error",
2604 funcName
, errStr
.c_str());
2605 printf_stderr("[gl:%p] %s.\n", this, text
.BeginReading());
2607 const bool abortOnError
= mDebugFlags
& DebugFlagAbortOnError
;
2608 if (abortOnError
&& err
!= LOCAL_GL_CONTEXT_LOST
) {
2609 gfxCriticalErrorOnce() << text
.BeginReading();
2611 "Aborting... (Run with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)");
2617 void GLContext::OnImplicitMakeCurrentFailure(const char* const funcName
) {
2618 gfxCriticalError() << "Ignoring call to " << funcName
<< " with failed"
2619 << " mImplicitMakeCurrent.";
2622 bool GLContext::CreateOffscreenDefaultFb(const gfx::IntSize
& size
) {
2623 mOffscreenDefaultFb
= MozFramebuffer::Create(this, size
, 0, true);
2624 return bool(mOffscreenDefaultFb
);
2627 // Some of Mesa's drivers allocate heap memory when loaded and don't
2628 // free it when unloaded; this causes Leak Sanitizer to detect leaks and
2629 // fail to unwind the stack, so suppressions don't work. This
2630 // workaround leaks a reference to the driver library so that it's never
2631 // unloaded. Because the leak isn't significant for real usage, only
2632 // ASan runs in CI, this is applied only to the software renderer.
2634 // See bug 1702394 for more details.
2635 void MesaMemoryLeakWorkaround() {
2636 #if defined(XP_LINUX) && !defined(ANDROID)
2637 Maybe
<nsAutoCString
> foundPath
;
2640 [](dl_phdr_info
* info
, size_t size
, void* data
) {
2641 auto& foundPath
= *reinterpret_cast<Maybe
<nsAutoCString
>*>(data
);
2642 nsDependentCString
thisPath(info
->dlpi_name
);
2643 if (StringEndsWith(thisPath
, "/swrast_dri.so"_ns
)) {
2644 foundPath
.emplace(thisPath
);
2652 // Deliberately leak to prevent unload
2653 Unused
<< dlopen(foundPath
->get(), RTLD_LAZY
);
2655 #endif // XP_LINUX but not ANDROID
2658 } /* namespace gl */
2659 } /* namespace mozilla */