1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "WebGLContext.h"
9 #include "GLSLANG/ShaderLang.h"
10 #include "CanvasUtils.h"
12 #include "GLContext.h"
13 #include "jsfriendapi.h"
14 #include "mozilla/CheckedInt.h"
15 #include "mozilla/Preferences.h"
16 #include "mozilla/StaticPrefs_webgl.h"
17 #include "nsPrintfCString.h"
18 #include "WebGLBuffer.h"
19 #include "WebGLContextUtils.h"
20 #include "WebGLFramebuffer.h"
21 #include "WebGLProgram.h"
22 #include "WebGLRenderbuffer.h"
23 #include "WebGLSampler.h"
24 #include "WebGLShader.h"
25 #include "WebGLTexture.h"
26 #include "WebGLValidateStrings.h"
27 #include "WebGLVertexArray.h"
30 // Minimum value constants defined in GLES 2.0.25 $6.2 "State Tables":
31 const uint32_t kMinMaxVertexAttribs
= 8; // Page 164
32 const uint32_t kMinMaxVertexUniformVectors
= 128; // Page 164
33 const uint32_t kMinMaxFragmentUniformVectors
= 16; // Page 164
34 const uint32_t kMinMaxVaryingVectors
= 8; // Page 164
36 const uint32_t kMinMaxVertexTextureImageUnits
= 0; // Page 164
37 const uint32_t kMinMaxFragmentTextureImageUnits
= 8; // Page 164
38 const uint32_t kMinMaxCombinedTextureImageUnits
= 8; // Page 164
40 const uint32_t kMinMaxDrawBuffers
= 4;
42 // These few deviate from the spec: (The minimum values in the spec are
44 const uint32_t kMinMaxTextureSize
= 1024; // ES2 spec says `64` (p162)
45 const uint32_t kMinMaxCubeMapTextureSize
= 512; // ES2 spec says `16` (p162)
46 const uint32_t kMinMaxRenderbufferSize
= 1024; // ES2 spec says `1` (p164)
48 // Minimum value constants defined in GLES 3.0.4 $6.2 "State Tables":
49 const uint32_t kMinMax3DTextureSize
= 256;
50 const uint32_t kMinMaxArrayTextureLayers
= 256;
53 // "Common" but usable values to avoid WebGL fingerprinting:
54 const uint32_t kCommonMaxTextureSize
= 2048;
55 const uint32_t kCommonMaxCubeMapTextureSize
= 2048;
56 const uint32_t kCommonMaxRenderbufferSize
= 2048;
58 const uint32_t kCommonMaxVertexTextureImageUnits
= 8;
59 const uint32_t kCommonMaxFragmentTextureImageUnits
= 8;
60 const uint32_t kCommonMaxCombinedTextureImageUnits
= 16;
62 const uint32_t kCommonMaxVertexAttribs
= 16;
63 const uint32_t kCommonMaxVertexUniformVectors
= 256;
64 const uint32_t kCommonMaxFragmentUniformVectors
= 224;
65 const uint32_t kCommonMaxVaryingVectors
= 8;
67 const uint32_t kCommonMaxViewportDims
= 4096;
69 // The following ranges came from a 2013 Moto E and an old macbook.
70 const float kCommonAliasedPointSizeRangeMin
= 1;
71 const float kCommonAliasedPointSizeRangeMax
= 63;
72 const float kCommonAliasedLineWidthRangeMin
= 1;
73 const float kCommonAliasedLineWidthRangeMax
= 1;
76 static bool RestrictCap(T
* const cap
, const T restrictedVal
) {
77 if (*cap
< restrictedVal
) {
78 return false; // already too low!
89 bool WebGLContext::ValidateBlendEquationEnum(GLenum mode
, const char* info
) {
91 case LOCAL_GL_FUNC_ADD
:
92 case LOCAL_GL_FUNC_SUBTRACT
:
93 case LOCAL_GL_FUNC_REVERSE_SUBTRACT
:
99 IsExtensionEnabled(WebGLExtensionID::EXT_blend_minmax
)) {
109 ErrorInvalidEnumInfo(info
, mode
);
113 bool WebGLContext::ValidateBlendFuncEnumsCompatibility(GLenum sfactor
,
116 bool sfactorIsConstantColor
= sfactor
== LOCAL_GL_CONSTANT_COLOR
||
117 sfactor
== LOCAL_GL_ONE_MINUS_CONSTANT_COLOR
;
118 bool sfactorIsConstantAlpha
= sfactor
== LOCAL_GL_CONSTANT_ALPHA
||
119 sfactor
== LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA
;
120 bool dfactorIsConstantColor
= dfactor
== LOCAL_GL_CONSTANT_COLOR
||
121 dfactor
== LOCAL_GL_ONE_MINUS_CONSTANT_COLOR
;
122 bool dfactorIsConstantAlpha
= dfactor
== LOCAL_GL_CONSTANT_ALPHA
||
123 dfactor
== LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA
;
124 if ((sfactorIsConstantColor
&& dfactorIsConstantAlpha
) ||
125 (dfactorIsConstantColor
&& sfactorIsConstantAlpha
)) {
126 ErrorInvalidOperation(
127 "%s are mutually incompatible, see section 6.8 in"
128 " the WebGL 1.0 spec",
136 bool WebGLContext::ValidateStencilOpEnum(GLenum action
, const char* info
) {
140 case LOCAL_GL_REPLACE
:
142 case LOCAL_GL_INCR_WRAP
:
144 case LOCAL_GL_DECR_WRAP
:
145 case LOCAL_GL_INVERT
:
149 ErrorInvalidEnumInfo(info
, action
);
154 bool WebGLContext::ValidateFaceEnum(const GLenum face
) {
158 case LOCAL_GL_FRONT_AND_BACK
:
162 ErrorInvalidEnumInfo("face", face
);
167 bool WebGLContext::ValidateAttribArraySetter(uint32_t setterElemSize
,
168 uint32_t arrayLength
) {
169 if (IsContextLost()) return false;
171 if (arrayLength
< setterElemSize
) {
172 ErrorInvalidValue("Array must have >= %d elements.", setterElemSize
);
179 // ---------------------
181 static webgl::Limits
MakeLimits(const WebGLContext
& webgl
) {
182 webgl::Limits limits
;
184 gl::GLContext
& gl
= *webgl
.GL();
188 for (const auto i
: IntegerRange(UnderlyingValue(WebGLExtensionID::Max
))) {
189 const auto ext
= WebGLExtensionID(i
);
190 limits
.supportedExtensions
[ext
] = webgl
.IsExtensionSupported(ext
);
196 // Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
197 // even though the hardware supports much more. The
198 // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
199 gl
.GetUIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
200 &limits
.maxTexUnits
);
201 limits
.maxTexUnits
= std::min(
202 limits
.maxTexUnits
, uint32_t{UINT8_MAX
}); // We want to use uint8_t.
204 gl
.GetUIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE
, &limits
.maxTex2dSize
);
205 gl
.GetUIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &limits
.maxTexCubeSize
);
206 gl
.GetUIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS
, &limits
.maxVertexAttribs
);
208 auto dims
= std::array
<uint32_t, 2>{};
209 gl
.GetUIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS
, dims
.data());
210 limits
.maxViewportDim
= std::min(dims
[0], dims
[1]);
212 if (!gl
.IsCoreProfile()) {
213 gl
.fGetFloatv(LOCAL_GL_ALIASED_LINE_WIDTH_RANGE
,
214 limits
.lineWidthRange
.data());
218 const GLenum driverPName
= gl
.IsCoreProfile()
219 ? LOCAL_GL_POINT_SIZE_RANGE
220 : LOCAL_GL_ALIASED_POINT_SIZE_RANGE
;
221 gl
.fGetFloatv(driverPName
, limits
.pointSizeRange
.data());
224 if (webgl
.IsWebGL2()) {
225 gl
.GetUIntegerv(LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS
,
226 &limits
.maxTexArrayLayers
);
227 gl
.GetUIntegerv(LOCAL_GL_MAX_3D_TEXTURE_SIZE
, &limits
.maxTex3dSize
);
228 gl
.GetUIntegerv(LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS
,
229 &limits
.maxUniformBufferBindings
);
230 gl
.GetUIntegerv(LOCAL_GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
231 &limits
.uniformBufferOffsetAlignment
);
234 if (limits
.supportedExtensions
235 [WebGLExtensionID::WEBGL_compressed_texture_astc
]) {
236 limits
.astcHdr
= gl
.IsExtensionSupported(
237 gl::GLContext::KHR_texture_compression_astc_hdr
);
240 if (webgl
.IsWebGL2() ||
241 limits
.supportedExtensions
[WebGLExtensionID::WEBGL_draw_buffers
]) {
242 gl
.GetUIntegerv(LOCAL_GL_MAX_DRAW_BUFFERS
, &limits
.maxColorDrawBuffers
);
245 if (limits
.supportedExtensions
[WebGLExtensionID::EXT_disjoint_timer_query
]) {
246 gl
.fGetQueryiv(LOCAL_GL_TIME_ELAPSED_EXT
, LOCAL_GL_QUERY_COUNTER_BITS
,
247 (int32_t*)&limits
.queryCounterBitsTimeElapsed
);
248 gl
.fGetQueryiv(LOCAL_GL_TIMESTAMP_EXT
, LOCAL_GL_QUERY_COUNTER_BITS
,
249 (int32_t*)&limits
.queryCounterBitsTimestamp
);
252 if (limits
.supportedExtensions
[WebGLExtensionID::OVR_multiview2
]) {
253 gl
.GetUIntegerv(LOCAL_GL_MAX_VIEWS_OVR
, &limits
.maxMultiviewLayers
);
259 bool WebGLContext::InitAndValidateGL(FailureReason
* const out_failReason
) {
260 MOZ_RELEASE_ASSERT(gl
, "GFX: GL not initialized");
262 // Unconditionally create a new format usage authority. This is
263 // important when restoring contexts and extensions need to add
264 // formats back into the authority.
265 mFormatUsage
= CreateFormatUsage(gl
);
267 *out_failReason
= {"FEATURE_FAILURE_WEBGL_FORMAT",
268 "Failed to create mFormatUsage."};
272 GLenum error
= gl
->fGetError();
273 if (error
!= LOCAL_GL_NO_ERROR
) {
274 const nsPrintfCString
reason(
275 "GL error 0x%x occurred during OpenGL context"
276 " initialization, before WebGL initialization!",
278 *out_failReason
= {"FEATURE_FAILURE_WEBGL_GLERR_1", reason
};
282 mLoseContextOnMemoryPressure
=
283 StaticPrefs::webgl_lose_context_on_memory_pressure();
284 mCanLoseContextInForeground
=
285 StaticPrefs::webgl_can_lose_context_in_foreground();
288 // Technically, we should be setting mStencil[...] values to
289 // `allOnes`, but either ANGLE breaks or the SGX540s on Try break.
290 GLuint stencilBits = 0;
291 gl->GetUIntegerv(LOCAL_GL_STENCIL_BITS, &stencilBits);
292 GLuint allOnes = ~(UINT32_MAX << stencilBits);
293 mStencilValueMaskFront = allOnes;
294 mStencilValueMaskBack = allOnes;
295 mStencilWriteMaskFront = allOnes;
296 mStencilWriteMaskBack = allOnes;
299 gl
->GetUIntegerv(LOCAL_GL_STENCIL_VALUE_MASK
, &mStencilValueMaskFront
);
300 gl
->GetUIntegerv(LOCAL_GL_STENCIL_BACK_VALUE_MASK
, &mStencilValueMaskBack
);
301 gl
->GetUIntegerv(LOCAL_GL_STENCIL_WRITEMASK
, &mStencilWriteMaskFront
);
302 gl
->GetUIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK
, &mStencilWriteMaskBack
);
304 AssertUintParamCorrect(gl
, LOCAL_GL_STENCIL_VALUE_MASK
,
305 mStencilValueMaskFront
);
306 AssertUintParamCorrect(gl
, LOCAL_GL_STENCIL_BACK_VALUE_MASK
,
307 mStencilValueMaskBack
);
308 AssertUintParamCorrect(gl
, LOCAL_GL_STENCIL_WRITEMASK
,
309 mStencilWriteMaskFront
);
310 AssertUintParamCorrect(gl
, LOCAL_GL_STENCIL_BACK_WRITEMASK
,
311 mStencilWriteMaskBack
);
315 mBound2DTextures
.Clear();
316 mBoundCubeMapTextures
.Clear();
317 mBound3DTextures
.Clear();
318 mBound2DArrayTextures
.Clear();
319 mBoundSamplers
.Clear();
321 mBoundArrayBuffer
= nullptr;
322 mCurrentProgram
= nullptr;
324 mBoundDrawFramebuffer
= nullptr;
325 mBoundReadFramebuffer
= nullptr;
327 // -----------------------
329 auto limits
= MakeLimits(*this);
333 if (limits
.maxVertexAttribs
< 8) {
334 const nsPrintfCString
reason("GL_MAX_VERTEX_ATTRIBS: %d is < 8!",
335 limits
.maxVertexAttribs
);
336 *out_failReason
= {"FEATURE_FAILURE_WEBGL_V_ATRB", reason
};
340 if (limits
.maxTexUnits
< 8) {
341 const nsPrintfCString
reason(
342 "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %u is < 8!", limits
.maxTexUnits
);
343 *out_failReason
= {"FEATURE_FAILURE_WEBGL_T_UNIT", reason
};
347 mBound2DTextures
.SetLength(limits
.maxTexUnits
);
348 mBoundCubeMapTextures
.SetLength(limits
.maxTexUnits
);
349 mBound3DTextures
.SetLength(limits
.maxTexUnits
);
350 mBound2DArrayTextures
.SetLength(limits
.maxTexUnits
);
351 mBoundSamplers
.SetLength(limits
.maxTexUnits
);
355 gl
->GetUIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE
, &mGLMaxRenderbufferSize
);
356 gl
->GetUIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS
,
357 &mGLMaxFragmentTextureImageUnits
);
358 gl
->GetUIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
359 &mGLMaxVertexTextureImageUnits
);
364 mGLMaxFragmentUniformVectors
=
365 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS
);
366 mGLMaxVertexUniformVectors
=
367 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS
);
368 if (gl
->Version() >= 300) {
369 mGLMaxVertexOutputVectors
=
370 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS
) / 4;
371 mGLMaxFragmentInputVectors
=
372 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS
) / 4;
374 mGLMaxFragmentInputVectors
=
375 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_VARYING_VECTORS
);
376 mGLMaxVertexOutputVectors
= mGLMaxFragmentInputVectors
;
379 mGLMaxFragmentUniformVectors
=
380 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
) / 4;
381 mGLMaxVertexUniformVectors
=
382 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS
) / 4;
384 if (gl
->Version() >= 320) {
385 mGLMaxVertexOutputVectors
=
386 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS
) / 4;
387 mGLMaxFragmentInputVectors
=
388 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS
) / 4;
390 // Same enum val as GL2's GL_MAX_VARYING_FLOATS.
391 mGLMaxFragmentInputVectors
=
392 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_VARYING_COMPONENTS
) / 4;
393 mGLMaxVertexOutputVectors
= mGLMaxFragmentInputVectors
;
399 if (StaticPrefs::webgl_min_capability_mode()) {
402 ok
&= RestrictCap(&mGLMaxVertexTextureImageUnits
,
403 kMinMaxVertexTextureImageUnits
);
404 ok
&= RestrictCap(&mGLMaxFragmentTextureImageUnits
,
405 kMinMaxFragmentTextureImageUnits
);
406 ok
&= RestrictCap(&limits
.maxTexUnits
, kMinMaxCombinedTextureImageUnits
);
408 ok
&= RestrictCap(&limits
.maxVertexAttribs
, kMinMaxVertexAttribs
);
409 ok
&= RestrictCap(&mGLMaxVertexUniformVectors
, kMinMaxVertexUniformVectors
);
410 ok
&= RestrictCap(&mGLMaxFragmentUniformVectors
,
411 kMinMaxFragmentUniformVectors
);
412 ok
&= RestrictCap(&mGLMaxVertexOutputVectors
, kMinMaxVaryingVectors
);
413 ok
&= RestrictCap(&mGLMaxFragmentInputVectors
, kMinMaxVaryingVectors
);
415 ok
&= RestrictCap(&limits
.maxColorDrawBuffers
, kMinMaxDrawBuffers
);
417 ok
&= RestrictCap(&limits
.maxTex2dSize
, kMinMaxTextureSize
);
418 ok
&= RestrictCap(&limits
.maxTexCubeSize
, kMinMaxCubeMapTextureSize
);
419 ok
&= RestrictCap(&limits
.maxTex3dSize
, kMinMax3DTextureSize
);
421 ok
&= RestrictCap(&limits
.maxTexArrayLayers
, kMinMaxArrayTextureLayers
);
422 ok
&= RestrictCap(&mGLMaxRenderbufferSize
, kMinMaxRenderbufferSize
);
425 GenerateWarning("Unable to restrict WebGL limits to minimums.");
429 mDisableFragHighP
= true;
430 } else if (mResistFingerprinting
) {
433 ok
&= RestrictCap(&limits
.maxTex2dSize
, kCommonMaxTextureSize
);
434 ok
&= RestrictCap(&limits
.maxTexCubeSize
, kCommonMaxCubeMapTextureSize
);
435 ok
&= RestrictCap(&mGLMaxRenderbufferSize
, kCommonMaxRenderbufferSize
);
437 ok
&= RestrictCap(&mGLMaxVertexTextureImageUnits
,
438 kCommonMaxVertexTextureImageUnits
);
439 ok
&= RestrictCap(&mGLMaxFragmentTextureImageUnits
,
440 kCommonMaxFragmentTextureImageUnits
);
441 ok
&= RestrictCap(&limits
.maxTexUnits
, kCommonMaxCombinedTextureImageUnits
);
443 ok
&= RestrictCap(&limits
.maxVertexAttribs
, kCommonMaxVertexAttribs
);
444 ok
&= RestrictCap(&mGLMaxVertexUniformVectors
,
445 kCommonMaxVertexUniformVectors
);
446 ok
&= RestrictCap(&mGLMaxFragmentUniformVectors
,
447 kCommonMaxFragmentUniformVectors
);
448 ok
&= RestrictCap(&mGLMaxVertexOutputVectors
, kCommonMaxVaryingVectors
);
449 ok
&= RestrictCap(&mGLMaxFragmentInputVectors
, kCommonMaxVaryingVectors
);
451 if (limits
.lineWidthRange
[0] <= kCommonAliasedLineWidthRangeMin
) {
452 limits
.lineWidthRange
[0] = kCommonAliasedLineWidthRangeMin
;
456 if (limits
.pointSizeRange
[0] <= kCommonAliasedPointSizeRangeMin
) {
457 limits
.pointSizeRange
[0] = kCommonAliasedPointSizeRangeMin
;
463 RestrictCap(&limits
.lineWidthRange
[1], kCommonAliasedLineWidthRangeMax
);
465 RestrictCap(&limits
.pointSizeRange
[1], kCommonAliasedPointSizeRangeMax
);
466 ok
&= RestrictCap(&limits
.maxViewportDim
, kCommonMaxViewportDims
);
470 "Unable to restrict WebGL limits in order to resist fingerprinting");
475 mLimits
= Some(limits
);
479 if (gl
->IsCompatibilityProfile()) {
480 gl
->fEnable(LOCAL_GL_POINT_SPRITE
);
484 gl
->fEnable(LOCAL_GL_PROGRAM_POINT_SIZE
);
487 if (gl
->IsSupported(gl::GLFeature::seamless_cube_map_opt_in
)) {
488 gl
->fEnable(LOCAL_GL_TEXTURE_CUBE_MAP_SEAMLESS
);
491 // initialize shader translator
492 if (!sh::Initialize()) {
493 *out_failReason
= {"FEATURE_FAILURE_WEBGL_GLSL",
494 "GLSL translator initialization failed!"};
498 // Mesa can only be detected with the GL_VERSION string, of the form
500 const char* versionStr
= (const char*)(gl
->fGetString(LOCAL_GL_VERSION
));
501 mIsMesa
= strstr(versionStr
, "Mesa");
503 // Notice that the point of calling fGetError here is not only to check for
504 // errors, but also to reset the error flags so that a subsequent WebGL
505 // getError call will give the correct result.
506 error
= gl
->fGetError();
507 if (error
!= LOCAL_GL_NO_ERROR
) {
508 const nsPrintfCString
reason(
509 "GL error 0x%x occurred during WebGL context"
512 *out_failReason
= {"FEATURE_FAILURE_WEBGL_GLERR_2", reason
};
516 if (IsWebGL2() && !InitWebGL2(out_failReason
)) {
517 // Todo: Bug 898404: Only allow WebGL2 on GL>=3.0 on desktop GL.
521 // OpenGL core profiles remove the default VAO object from version
522 // 4.0.0. We create a default VAO for all core profiles,
523 // regardless of version.
526 // (https://www.opengl.org/registry/doc/glspec40.core.20100311.pdf)
527 // in Section E.2.2 "Removed Features", pg 397: "[...] The default
528 // vertex array object (the name zero) is also deprecated. [...]"
529 mDefaultVertexArray
= WebGLVertexArray::Create(this);
530 mDefaultVertexArray
->BindVertexArray();
532 mPrimRestartTypeBytes
= 0;
536 mGenericVertexAttribTypes
.assign(limits
.maxVertexAttribs
,
537 webgl::AttribBaseType::Float
);
538 mGenericVertexAttribTypeInvalidator
.InvalidateCaches();
540 static const float kDefaultGenericVertexAttribData
[4] = {0, 0, 0, 1};
541 memcpy(mGenericVertexAttrib0Data
, kDefaultGenericVertexAttribData
,
542 sizeof(mGenericVertexAttrib0Data
));
544 mFakeVertexAttrib0BufferObject
= 0;
546 mNeedsLegacyVertexAttrib0Handling
= gl
->IsCompatibilityProfile();
547 if (gl
->WorkAroundDriverBugs() && kIsMacOS
) {
548 // Failures in conformance/attribs/gl-disabled-vertex-attrib.
549 // Even in Core profiles on NV. Sigh.
550 mNeedsLegacyVertexAttrib0Handling
|= (gl
->Vendor() == gl::GLVendor::NVIDIA
);
552 mBug_DrawArraysInstancedUserAttribFetchAffectedByFirst
|=
553 (gl
->Vendor() == gl::GLVendor::Intel
);
555 // Failures for programs with no attribs:
556 // conformance/attribs/gl-vertex-attrib-unconsumed-out-of-bounds.html
557 mMaybeNeedsLegacyVertexAttrib0Handling
= true;
559 mMaybeNeedsLegacyVertexAttrib0Handling
|= mNeedsLegacyVertexAttrib0Handling
;
561 if (const auto& env
=
562 gfxEnv::MOZ_WEBGL_WORKAROUND_FIRST_AFFECTS_INSTANCE_ID()) {
563 const auto was
= mBug_DrawArraysInstancedUserAttribFetchAffectedByFirst
;
564 mBug_DrawArraysInstancedUserAttribFetchAffectedByFirst
=
567 "mBug_DrawArraysInstancedUserAttribFetchAffectedByFirst: %i -> %i\n",
568 int(was
), int(mBug_DrawArraysInstancedUserAttribFetchAffectedByFirst
));
573 mNeedsIndexValidation
=
574 !gl
->IsSupported(gl::GLFeature::robust_buffer_access_behavior
);
575 switch (StaticPrefs::webgl_force_index_validation()) {
577 mNeedsIndexValidation
= false;
580 mNeedsIndexValidation
= true;
583 MOZ_ASSERT(StaticPrefs::webgl_force_index_validation() == 0);
587 for (auto& cur
: mExtensions
) {
594 bool WebGLContext::ValidateFramebufferTarget(GLenum target
) const {
597 case LOCAL_GL_FRAMEBUFFER
:
600 case LOCAL_GL_DRAW_FRAMEBUFFER
:
601 case LOCAL_GL_READ_FRAMEBUFFER
:
602 isValid
= IsWebGL2();
610 if (MOZ_LIKELY(isValid
)) {
614 ErrorInvalidEnumArg("target", target
);
618 } // namespace mozilla