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