Bug 1908759 - Don't use UTS 46 ToUnicode from nsDocShell::AttemptURIFixup. r=necko...
[gecko.git] / dom / canvas / WebGLContextValidate.cpp
blobe5197db8079a00a7587f710f2209115eae103a5e
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"
8 #include <algorithm>
9 #include "GLSLANG/ShaderLang.h"
10 #include "CanvasUtils.h"
11 #include "gfxEnv.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"
29 ////////////////////
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
43 // ridiculously low)
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;
52 ////////////////////
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;
75 template <class T>
76 static bool RestrictCap(T* const cap, const T restrictedVal) {
77 if (*cap < restrictedVal) {
78 return false; // already too low!
81 *cap = restrictedVal;
82 return true;
85 ////////////////////
87 namespace mozilla {
89 bool WebGLContext::ValidateBlendEquationEnum(GLenum mode, const char* info) {
90 switch (mode) {
91 case LOCAL_GL_FUNC_ADD:
92 case LOCAL_GL_FUNC_SUBTRACT:
93 case LOCAL_GL_FUNC_REVERSE_SUBTRACT:
94 return true;
96 case LOCAL_GL_MIN:
97 case LOCAL_GL_MAX:
98 if (IsWebGL2() ||
99 IsExtensionEnabled(WebGLExtensionID::EXT_blend_minmax)) {
100 return true;
103 break;
105 default:
106 break;
109 ErrorInvalidEnumInfo(info, mode);
110 return false;
113 bool WebGLContext::ValidateBlendFuncEnumsCompatibility(GLenum sfactor,
114 GLenum dfactor,
115 const char* info) {
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",
129 info);
130 return false;
133 return true;
136 bool WebGLContext::ValidateStencilOpEnum(GLenum action, const char* info) {
137 switch (action) {
138 case LOCAL_GL_KEEP:
139 case LOCAL_GL_ZERO:
140 case LOCAL_GL_REPLACE:
141 case LOCAL_GL_INCR:
142 case LOCAL_GL_INCR_WRAP:
143 case LOCAL_GL_DECR:
144 case LOCAL_GL_DECR_WRAP:
145 case LOCAL_GL_INVERT:
146 return true;
148 default:
149 ErrorInvalidEnumInfo(info, action);
150 return false;
154 bool WebGLContext::ValidateFaceEnum(const GLenum face) {
155 switch (face) {
156 case LOCAL_GL_FRONT:
157 case LOCAL_GL_BACK:
158 case LOCAL_GL_FRONT_AND_BACK:
159 return true;
161 default:
162 ErrorInvalidEnumInfo("face", face);
163 return false;
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);
173 return false;
176 return true;
179 // ---------------------
181 static webgl::Limits MakeLimits(const WebGLContext& webgl) {
182 webgl::Limits limits;
184 gl::GLContext& gl = *webgl.GL();
186 // -
188 for (const auto i : IntegerRange(UnderlyingValue(WebGLExtensionID::Max))) {
189 const auto ext = WebGLExtensionID(i);
190 limits.supportedExtensions[ext] = webgl.IsExtensionSupported(ext);
193 // -
194 // WebGL 1
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);
256 return limits;
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);
266 if (!mFormatUsage) {
267 *out_failReason = {"FEATURE_FAILURE_WEBGL_FORMAT",
268 "Failed to create mFormatUsage."};
269 return false;
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!",
277 error);
278 *out_failReason = {"FEATURE_FAILURE_WEBGL_GLERR_1", reason};
279 return false;
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);
313 // Bindings, etc.
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);
331 // -
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};
337 return false;
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};
344 return false;
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);
353 ////////////////
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);
361 ////////////////
363 if (gl->IsGLES()) {
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;
373 } else {
374 mGLMaxFragmentInputVectors =
375 gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VARYING_VECTORS);
376 mGLMaxVertexOutputVectors = mGLMaxFragmentInputVectors;
378 } else {
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;
389 } else {
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;
397 ////////////////
399 if (StaticPrefs::webgl_min_capability_mode()) {
400 bool ok = true;
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);
424 if (!ok) {
425 GenerateWarning("Unable to restrict WebGL limits to minimums.");
426 return false;
429 mDisableFragHighP = true;
430 } else if (mResistFingerprinting) {
431 bool ok = true;
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;
453 } else {
454 ok = false;
456 if (limits.pointSizeRange[0] <= kCommonAliasedPointSizeRangeMin) {
457 limits.pointSizeRange[0] = kCommonAliasedPointSizeRangeMin;
458 } else {
459 ok = false;
462 ok &=
463 RestrictCap(&limits.lineWidthRange[1], kCommonAliasedLineWidthRangeMax);
464 ok &=
465 RestrictCap(&limits.pointSizeRange[1], kCommonAliasedPointSizeRangeMax);
466 ok &= RestrictCap(&limits.maxViewportDim, kCommonMaxViewportDims);
468 if (!ok) {
469 GenerateWarning(
470 "Unable to restrict WebGL limits in order to resist fingerprinting");
471 return false;
475 mLimits = Some(limits);
477 ////////////////
479 if (gl->IsCompatibilityProfile()) {
480 gl->fEnable(LOCAL_GL_POINT_SPRITE);
483 if (!gl->IsGLES()) {
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!"};
495 return false;
498 // Mesa can only be detected with the GL_VERSION string, of the form
499 // "2.1 Mesa 7.11.0"
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"
510 " initialization!",
511 error);
512 *out_failReason = {"FEATURE_FAILURE_WEBGL_GLERR_2", reason};
513 return false;
516 if (IsWebGL2() && !InitWebGL2(out_failReason)) {
517 // Todo: Bug 898404: Only allow WebGL2 on GL>=3.0 on desktop GL.
518 return false;
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.
525 // GL Spec 4.0.0:
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;
534 // -
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 =
565 (env.as_str != "0");
566 printf_stderr(
567 "mBug_DrawArraysInstancedUserAttribFetchAffectedByFirst: %i -> %i\n",
568 int(was), int(mBug_DrawArraysInstancedUserAttribFetchAffectedByFirst));
571 // -
573 mNeedsIndexValidation =
574 !gl->IsSupported(gl::GLFeature::robust_buffer_access_behavior);
575 switch (StaticPrefs::webgl_force_index_validation()) {
576 case -1:
577 mNeedsIndexValidation = false;
578 break;
579 case 1:
580 mNeedsIndexValidation = true;
581 break;
582 default:
583 MOZ_ASSERT(StaticPrefs::webgl_force_index_validation() == 0);
584 break;
587 for (auto& cur : mExtensions) {
588 cur = {};
591 return true;
594 bool WebGLContext::ValidateFramebufferTarget(GLenum target) const {
595 bool isValid = true;
596 switch (target) {
597 case LOCAL_GL_FRAMEBUFFER:
598 break;
600 case LOCAL_GL_DRAW_FRAMEBUFFER:
601 case LOCAL_GL_READ_FRAMEBUFFER:
602 isValid = IsWebGL2();
603 break;
605 default:
606 isValid = false;
607 break;
610 if (MOZ_LIKELY(isValid)) {
611 return true;
614 ErrorInvalidEnumArg("target", target);
615 return false;
618 } // namespace mozilla