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"
11 #include "GLContext.h"
12 #include "jsfriendapi.h"
13 #include "mozilla/CheckedInt.h"
14 #include "mozilla/Preferences.h"
15 #include "mozilla/StaticPrefs_webgl.h"
16 #include "nsPrintfCString.h"
17 #include "WebGLBuffer.h"
18 #include "WebGLContextUtils.h"
19 #include "WebGLFramebuffer.h"
20 #include "WebGLProgram.h"
21 #include "WebGLRenderbuffer.h"
22 #include "WebGLSampler.h"
23 #include "WebGLShader.h"
24 #include "WebGLTexture.h"
25 #include "WebGLValidateStrings.h"
26 #include "WebGLVertexArray.h"
28 #if defined(MOZ_WIDGET_COCOA)
29 # include "nsCocoaFeatures.h"
33 // Minimum value constants defined in GLES 2.0.25 $6.2 "State Tables":
34 const uint32_t kMinMaxVertexAttribs
= 8; // Page 164
35 const uint32_t kMinMaxVertexUniformVectors
= 128; // Page 164
36 const uint32_t kMinMaxFragmentUniformVectors
= 16; // Page 164
37 const uint32_t kMinMaxVaryingVectors
= 8; // Page 164
39 const uint32_t kMinMaxVertexTextureImageUnits
= 0; // Page 164
40 const uint32_t kMinMaxFragmentTextureImageUnits
= 8; // Page 164
41 const uint32_t kMinMaxCombinedTextureImageUnits
= 8; // Page 164
43 const uint32_t kMinMaxDrawBuffers
= 4;
45 // These few deviate from the spec: (The minimum values in the spec are
47 const uint32_t kMinMaxTextureSize
= 1024; // ES2 spec says `64` (p162)
48 const uint32_t kMinMaxCubeMapTextureSize
= 512; // ES2 spec says `16` (p162)
49 const uint32_t kMinMaxRenderbufferSize
= 1024; // ES2 spec says `1` (p164)
51 // Minimum value constants defined in GLES 3.0.4 $6.2 "State Tables":
52 const uint32_t kMinMax3DTextureSize
= 256;
53 const uint32_t kMinMaxArrayTextureLayers
= 256;
56 // "Common" but usable values to avoid WebGL fingerprinting:
57 const uint32_t kCommonMaxTextureSize
= 2048;
58 const uint32_t kCommonMaxCubeMapTextureSize
= 2048;
59 const uint32_t kCommonMaxRenderbufferSize
= 2048;
61 const uint32_t kCommonMaxVertexTextureImageUnits
= 8;
62 const uint32_t kCommonMaxFragmentTextureImageUnits
= 8;
63 const uint32_t kCommonMaxCombinedTextureImageUnits
= 16;
65 const uint32_t kCommonMaxVertexAttribs
= 16;
66 const uint32_t kCommonMaxVertexUniformVectors
= 256;
67 const uint32_t kCommonMaxFragmentUniformVectors
= 224;
68 const uint32_t kCommonMaxVaryingVectors
= 8;
70 const uint32_t kCommonMaxViewportDims
= 4096;
72 // The following ranges came from a 2013 Moto E and an old macbook.
73 const float kCommonAliasedPointSizeRangeMin
= 1;
74 const float kCommonAliasedPointSizeRangeMax
= 63;
75 const float kCommonAliasedLineWidthRangeMin
= 1;
76 const float kCommonAliasedLineWidthRangeMax
= 1;
79 static bool RestrictCap(T
* const cap
, const T restrictedVal
) {
80 if (*cap
< restrictedVal
) {
81 return false; // already too low!
92 bool WebGLContext::ValidateBlendEquationEnum(GLenum mode
, const char* info
) {
94 case LOCAL_GL_FUNC_ADD
:
95 case LOCAL_GL_FUNC_SUBTRACT
:
96 case LOCAL_GL_FUNC_REVERSE_SUBTRACT
:
102 IsExtensionEnabled(WebGLExtensionID::EXT_blend_minmax
)) {
112 ErrorInvalidEnumInfo(info
, mode
);
116 bool WebGLContext::ValidateBlendFuncEnumsCompatibility(GLenum sfactor
,
119 bool sfactorIsConstantColor
= sfactor
== LOCAL_GL_CONSTANT_COLOR
||
120 sfactor
== LOCAL_GL_ONE_MINUS_CONSTANT_COLOR
;
121 bool sfactorIsConstantAlpha
= sfactor
== LOCAL_GL_CONSTANT_ALPHA
||
122 sfactor
== LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA
;
123 bool dfactorIsConstantColor
= dfactor
== LOCAL_GL_CONSTANT_COLOR
||
124 dfactor
== LOCAL_GL_ONE_MINUS_CONSTANT_COLOR
;
125 bool dfactorIsConstantAlpha
= dfactor
== LOCAL_GL_CONSTANT_ALPHA
||
126 dfactor
== LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA
;
127 if ((sfactorIsConstantColor
&& dfactorIsConstantAlpha
) ||
128 (dfactorIsConstantColor
&& sfactorIsConstantAlpha
)) {
129 ErrorInvalidOperation(
130 "%s are mutually incompatible, see section 6.8 in"
131 " the WebGL 1.0 spec",
139 bool WebGLContext::ValidateStencilOpEnum(GLenum action
, const char* info
) {
143 case LOCAL_GL_REPLACE
:
145 case LOCAL_GL_INCR_WRAP
:
147 case LOCAL_GL_DECR_WRAP
:
148 case LOCAL_GL_INVERT
:
152 ErrorInvalidEnumInfo(info
, action
);
157 bool WebGLContext::ValidateFaceEnum(const GLenum face
) {
161 case LOCAL_GL_FRONT_AND_BACK
:
165 ErrorInvalidEnumInfo("face", face
);
170 bool WebGLContext::ValidateAttribArraySetter(uint32_t setterElemSize
,
171 uint32_t arrayLength
) {
172 if (IsContextLost()) return false;
174 if (arrayLength
< setterElemSize
) {
175 ErrorInvalidValue("Array must have >= %d elements.", setterElemSize
);
182 // ---------------------
184 static webgl::Limits
MakeLimits(const WebGLContext
& webgl
) {
185 webgl::Limits limits
;
187 for (const auto i
: IntegerRange(UnderlyingValue(WebGLExtensionID::Max
))) {
188 const auto ext
= WebGLExtensionID(i
);
189 limits
.supportedExtensions
[ext
] = webgl
.IsExtensionSupported(ext
);
192 gl::GLContext
& gl
= *webgl
.GL();
197 // Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
198 // even though the hardware supports much more. The
199 // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
200 gl
.GetUIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
,
201 &limits
.maxTexUnits
);
203 gl
.GetUIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE
, &limits
.maxTex2dSize
);
204 gl
.GetUIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &limits
.maxTexCubeSize
);
205 gl
.GetUIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS
, &limits
.maxVertexAttribs
);
206 gl
.GetUIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS
, limits
.maxViewportDims
.data());
208 if (!gl
.IsCoreProfile()) {
209 gl
.fGetFloatv(LOCAL_GL_ALIASED_LINE_WIDTH_RANGE
,
210 limits
.lineWidthRange
.data());
214 const GLenum driverPName
= gl
.IsCoreProfile()
215 ? LOCAL_GL_POINT_SIZE_RANGE
216 : LOCAL_GL_ALIASED_POINT_SIZE_RANGE
;
217 gl
.fGetFloatv(driverPName
, limits
.pointSizeRange
.data());
220 if (webgl
.IsWebGL2()) {
221 gl
.GetUIntegerv(LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS
,
222 &limits
.maxTexArrayLayers
);
223 gl
.GetUIntegerv(LOCAL_GL_MAX_3D_TEXTURE_SIZE
, &limits
.maxTex3dSize
);
224 gl
.GetUIntegerv(LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS
,
225 &limits
.maxTransformFeedbackSeparateAttribs
);
226 gl
.GetUIntegerv(LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS
,
227 &limits
.maxUniformBufferBindings
);
228 gl
.GetUIntegerv(LOCAL_GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
,
229 &limits
.uniformBufferOffsetAlignment
);
232 if (limits
.supportedExtensions
233 [WebGLExtensionID::WEBGL_compressed_texture_astc
]) {
234 limits
.astcHdr
= gl
.IsExtensionSupported(
235 gl::GLContext::KHR_texture_compression_astc_hdr
);
238 if (webgl
.IsWebGL2() ||
239 limits
.supportedExtensions
[WebGLExtensionID::WEBGL_draw_buffers
]) {
240 gl
.GetUIntegerv(LOCAL_GL_MAX_DRAW_BUFFERS
, &limits
.maxColorDrawBuffers
);
243 if (limits
.supportedExtensions
[WebGLExtensionID::EXT_disjoint_timer_query
]) {
244 gl
.fGetQueryiv(LOCAL_GL_TIME_ELAPSED_EXT
, LOCAL_GL_QUERY_COUNTER_BITS
,
245 (int32_t*)&limits
.queryCounterBitsTimeElapsed
);
246 gl
.fGetQueryiv(LOCAL_GL_TIMESTAMP_EXT
, LOCAL_GL_QUERY_COUNTER_BITS
,
247 (int32_t*)&limits
.queryCounterBitsTimestamp
);
250 if (limits
.supportedExtensions
[WebGLExtensionID::OVR_multiview2
]) {
251 gl
.GetUIntegerv(LOCAL_GL_MAX_VIEWS_OVR
, &limits
.maxMultiviewLayers
);
257 bool WebGLContext::InitAndValidateGL(FailureReason
* const out_failReason
) {
258 MOZ_RELEASE_ASSERT(gl
, "GFX: GL not initialized");
260 // Unconditionally create a new format usage authority. This is
261 // important when restoring contexts and extensions need to add
262 // formats back into the authority.
263 mFormatUsage
= CreateFormatUsage(gl
);
265 *out_failReason
= {"FEATURE_FAILURE_WEBGL_FORMAT",
266 "Failed to create mFormatUsage."};
270 GLenum error
= gl
->fGetError();
271 if (error
!= LOCAL_GL_NO_ERROR
) {
272 const nsPrintfCString
reason(
273 "GL error 0x%x occurred during OpenGL context"
274 " initialization, before WebGL initialization!",
276 *out_failReason
= {"FEATURE_FAILURE_WEBGL_GLERR_1", reason
};
280 mLoseContextOnMemoryPressure
=
281 StaticPrefs::webgl_lose_context_on_memory_pressure();
282 mCanLoseContextInForeground
=
283 StaticPrefs::webgl_can_lose_context_in_foreground();
285 // These are the default values, see 6.2 State tables in the
286 // OpenGL ES 2.0.25 spec.
287 mDriverColorMask
= mColorWriteMask
;
288 mColorClearValue
[0] = 0.f
;
289 mColorClearValue
[1] = 0.f
;
290 mColorClearValue
[2] = 0.f
;
291 mColorClearValue
[3] = 0.f
;
292 mDepthWriteMask
= true;
293 mDepthClearValue
= 1.f
;
294 mStencilClearValue
= 0;
295 mStencilRefFront
= 0;
301 // Technically, we should be setting mStencil[...] values to
302 // `allOnes`, but either ANGLE breaks or the SGX540s on Try break.
303 GLuint stencilBits = 0;
304 gl->GetUIntegerv(LOCAL_GL_STENCIL_BITS, &stencilBits);
305 GLuint allOnes = ~(UINT32_MAX << stencilBits);
306 mStencilValueMaskFront = allOnes;
307 mStencilValueMaskBack = allOnes;
308 mStencilWriteMaskFront = allOnes;
309 mStencilWriteMaskBack = allOnes;
312 gl
->GetUIntegerv(LOCAL_GL_STENCIL_VALUE_MASK
, &mStencilValueMaskFront
);
313 gl
->GetUIntegerv(LOCAL_GL_STENCIL_BACK_VALUE_MASK
, &mStencilValueMaskBack
);
314 gl
->GetUIntegerv(LOCAL_GL_STENCIL_WRITEMASK
, &mStencilWriteMaskFront
);
315 gl
->GetUIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK
, &mStencilWriteMaskBack
);
317 AssertUintParamCorrect(gl
, LOCAL_GL_STENCIL_VALUE_MASK
,
318 mStencilValueMaskFront
);
319 AssertUintParamCorrect(gl
, LOCAL_GL_STENCIL_BACK_VALUE_MASK
,
320 mStencilValueMaskBack
);
321 AssertUintParamCorrect(gl
, LOCAL_GL_STENCIL_WRITEMASK
,
322 mStencilWriteMaskFront
);
323 AssertUintParamCorrect(gl
, LOCAL_GL_STENCIL_BACK_WRITEMASK
,
324 mStencilWriteMaskBack
);
326 mDitherEnabled
= true;
327 mRasterizerDiscardEnabled
= false;
328 mScissorTestEnabled
= false;
330 mDepthTestEnabled
= 0;
331 mDriverDepthTest
= false;
332 mStencilTestEnabled
= 0;
333 mDriverStencilTest
= false;
335 mGenerateMipmapHint
= LOCAL_GL_DONT_CARE
;
339 mDefaultFB_DrawBuffer0
= LOCAL_GL_BACK
;
340 mDefaultFB_ReadBuffer
= LOCAL_GL_BACK
;
342 mWebGLError
= LOCAL_GL_NO_ERROR
;
344 mBound2DTextures
.Clear();
345 mBoundCubeMapTextures
.Clear();
346 mBound3DTextures
.Clear();
347 mBound2DArrayTextures
.Clear();
348 mBoundSamplers
.Clear();
350 mBoundArrayBuffer
= nullptr;
351 mCurrentProgram
= nullptr;
353 mBoundDrawFramebuffer
= nullptr;
354 mBoundReadFramebuffer
= nullptr;
356 // -----------------------
358 auto limits
= MakeLimits(*this);
362 if (limits
.maxVertexAttribs
< 8) {
363 const nsPrintfCString
reason("GL_MAX_VERTEX_ATTRIBS: %d is < 8!",
364 limits
.maxVertexAttribs
);
365 *out_failReason
= {"FEATURE_FAILURE_WEBGL_V_ATRB", reason
};
369 if (limits
.maxTexUnits
< 8) {
370 const nsPrintfCString
reason(
371 "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %u is < 8!", limits
.maxTexUnits
);
372 *out_failReason
= {"FEATURE_FAILURE_WEBGL_T_UNIT", reason
};
376 mBound2DTextures
.SetLength(limits
.maxTexUnits
);
377 mBoundCubeMapTextures
.SetLength(limits
.maxTexUnits
);
378 mBound3DTextures
.SetLength(limits
.maxTexUnits
);
379 mBound2DArrayTextures
.SetLength(limits
.maxTexUnits
);
380 mBoundSamplers
.SetLength(limits
.maxTexUnits
);
384 gl
->GetUIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE
, &mGLMaxRenderbufferSize
);
385 gl
->GetUIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS
,
386 &mGLMaxFragmentTextureImageUnits
);
387 gl
->GetUIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
,
388 &mGLMaxVertexTextureImageUnits
);
393 mGLMaxFragmentUniformVectors
=
394 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS
);
395 mGLMaxVertexUniformVectors
=
396 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS
);
397 if (gl
->Version() >= 300) {
398 mGLMaxVertexOutputVectors
=
399 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS
) / 4;
400 mGLMaxFragmentInputVectors
=
401 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS
) / 4;
403 mGLMaxFragmentInputVectors
=
404 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_VARYING_VECTORS
);
405 mGLMaxVertexOutputVectors
= mGLMaxFragmentInputVectors
;
408 mGLMaxFragmentUniformVectors
=
409 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
) / 4;
410 mGLMaxVertexUniformVectors
=
411 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS
) / 4;
413 if (gl
->Version() >= 320) {
414 mGLMaxVertexOutputVectors
=
415 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS
) / 4;
416 mGLMaxFragmentInputVectors
=
417 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS
) / 4;
419 // Same enum val as GL2's GL_MAX_VARYING_FLOATS.
420 mGLMaxFragmentInputVectors
=
421 gl
->GetIntAs
<uint32_t>(LOCAL_GL_MAX_VARYING_COMPONENTS
) / 4;
422 mGLMaxVertexOutputVectors
= mGLMaxFragmentInputVectors
;
428 if (StaticPrefs::webgl_min_capability_mode()) {
431 ok
&= RestrictCap(&mGLMaxVertexTextureImageUnits
,
432 kMinMaxVertexTextureImageUnits
);
433 ok
&= RestrictCap(&mGLMaxFragmentTextureImageUnits
,
434 kMinMaxFragmentTextureImageUnits
);
435 ok
&= RestrictCap(&limits
.maxTexUnits
, kMinMaxCombinedTextureImageUnits
);
437 ok
&= RestrictCap(&limits
.maxVertexAttribs
, kMinMaxVertexAttribs
);
438 ok
&= RestrictCap(&mGLMaxVertexUniformVectors
, kMinMaxVertexUniformVectors
);
439 ok
&= RestrictCap(&mGLMaxFragmentUniformVectors
,
440 kMinMaxFragmentUniformVectors
);
441 ok
&= RestrictCap(&mGLMaxVertexOutputVectors
, kMinMaxVaryingVectors
);
442 ok
&= RestrictCap(&mGLMaxFragmentInputVectors
, kMinMaxVaryingVectors
);
444 ok
&= RestrictCap(&limits
.maxColorDrawBuffers
, kMinMaxDrawBuffers
);
446 ok
&= RestrictCap(&limits
.maxTex2dSize
, kMinMaxTextureSize
);
447 ok
&= RestrictCap(&limits
.maxTexCubeSize
, kMinMaxCubeMapTextureSize
);
448 ok
&= RestrictCap(&limits
.maxTex3dSize
, kMinMax3DTextureSize
);
450 ok
&= RestrictCap(&limits
.maxTexArrayLayers
, kMinMaxArrayTextureLayers
);
451 ok
&= RestrictCap(&mGLMaxRenderbufferSize
, kMinMaxRenderbufferSize
);
454 GenerateWarning("Unable to restrict WebGL limits to minimums.");
458 mDisableFragHighP
= true;
459 } else if (mResistFingerprinting
) {
462 ok
&= RestrictCap(&limits
.maxTex2dSize
, kCommonMaxTextureSize
);
463 ok
&= RestrictCap(&limits
.maxTexCubeSize
, kCommonMaxCubeMapTextureSize
);
464 ok
&= RestrictCap(&mGLMaxRenderbufferSize
, kCommonMaxRenderbufferSize
);
466 ok
&= RestrictCap(&mGLMaxVertexTextureImageUnits
,
467 kCommonMaxVertexTextureImageUnits
);
468 ok
&= RestrictCap(&mGLMaxFragmentTextureImageUnits
,
469 kCommonMaxFragmentTextureImageUnits
);
470 ok
&= RestrictCap(&limits
.maxTexUnits
, kCommonMaxCombinedTextureImageUnits
);
472 ok
&= RestrictCap(&limits
.maxVertexAttribs
, kCommonMaxVertexAttribs
);
473 ok
&= RestrictCap(&mGLMaxVertexUniformVectors
,
474 kCommonMaxVertexUniformVectors
);
475 ok
&= RestrictCap(&mGLMaxFragmentUniformVectors
,
476 kCommonMaxFragmentUniformVectors
);
477 ok
&= RestrictCap(&mGLMaxVertexOutputVectors
, kCommonMaxVaryingVectors
);
478 ok
&= RestrictCap(&mGLMaxFragmentInputVectors
, kCommonMaxVaryingVectors
);
480 if (limits
.lineWidthRange
[0] <= kCommonAliasedLineWidthRangeMin
) {
481 limits
.lineWidthRange
[0] = kCommonAliasedLineWidthRangeMin
;
485 if (limits
.pointSizeRange
[0] <= kCommonAliasedPointSizeRangeMin
) {
486 limits
.pointSizeRange
[0] = kCommonAliasedPointSizeRangeMin
;
492 RestrictCap(&limits
.lineWidthRange
[1], kCommonAliasedLineWidthRangeMax
);
494 RestrictCap(&limits
.pointSizeRange
[1], kCommonAliasedPointSizeRangeMax
);
495 ok
&= RestrictCap(&limits
.maxViewportDims
[0], kCommonMaxViewportDims
);
496 ok
&= RestrictCap(&limits
.maxViewportDims
[1], kCommonMaxViewportDims
);
500 "Unable to restrict WebGL limits in order to resist fingerprinting");
505 mLimits
= Some(limits
);
509 if (gl
->IsCompatibilityProfile()) {
510 gl
->fEnable(LOCAL_GL_POINT_SPRITE
);
514 gl
->fEnable(LOCAL_GL_PROGRAM_POINT_SIZE
);
518 if (gl
->WorkAroundDriverBugs() && gl
->Vendor() == gl::GLVendor::ATI
&&
519 !nsCocoaFeatures::IsAtLeastVersion(10, 9)) {
520 // The Mac ATI driver, in all known OSX version up to and including
521 // 10.8, renders points sprites upside-down. (Apple bug 11778921)
522 gl
->fPointParameterf(LOCAL_GL_POINT_SPRITE_COORD_ORIGIN
,
523 LOCAL_GL_LOWER_LEFT
);
527 if (gl
->IsSupported(gl::GLFeature::seamless_cube_map_opt_in
)) {
528 gl
->fEnable(LOCAL_GL_TEXTURE_CUBE_MAP_SEAMLESS
);
531 // initialize shader translator
532 if (!sh::Initialize()) {
533 *out_failReason
= {"FEATURE_FAILURE_WEBGL_GLSL",
534 "GLSL translator initialization failed!"};
538 // Mesa can only be detected with the GL_VERSION string, of the form
540 const char* versionStr
= (const char*)(gl
->fGetString(LOCAL_GL_VERSION
));
541 mIsMesa
= strstr(versionStr
, "Mesa");
543 // Notice that the point of calling fGetError here is not only to check for
544 // errors, but also to reset the error flags so that a subsequent WebGL
545 // getError call will give the correct result.
546 error
= gl
->fGetError();
547 if (error
!= LOCAL_GL_NO_ERROR
) {
548 const nsPrintfCString
reason(
549 "GL error 0x%x occurred during WebGL context"
552 *out_failReason
= {"FEATURE_FAILURE_WEBGL_GLERR_2", reason
};
556 if (IsWebGL2() && !InitWebGL2(out_failReason
)) {
557 // Todo: Bug 898404: Only allow WebGL2 on GL>=3.0 on desktop GL.
561 if (!gl
->IsSupported(gl::GLFeature::vertex_array_object
)) {
562 *out_failReason
= {"FEATURE_FAILURE_WEBGL_VAOS",
563 "Requires vertex_array_object."};
567 // OpenGL core profiles remove the default VAO object from version
568 // 4.0.0. We create a default VAO for all core profiles,
569 // regardless of version.
572 // (https://www.opengl.org/registry/doc/glspec40.core.20100311.pdf)
573 // in Section E.2.2 "Removed Features", pg 397: "[...] The default
574 // vertex array object (the name zero) is also deprecated. [...]"
575 mDefaultVertexArray
= WebGLVertexArray::Create(this);
576 mDefaultVertexArray
->BindVertexArray();
578 mPrimRestartTypeBytes
= 0;
580 mGenericVertexAttribTypes
.assign(limits
.maxVertexAttribs
,
581 webgl::AttribBaseType::Float
);
582 mGenericVertexAttribTypeInvalidator
.InvalidateCaches();
584 static const float kDefaultGenericVertexAttribData
[4] = {0, 0, 0, 1};
585 memcpy(mGenericVertexAttrib0Data
, kDefaultGenericVertexAttribData
,
586 sizeof(mGenericVertexAttrib0Data
));
588 mFakeVertexAttrib0BufferObject
= 0;
590 mNeedsIndexValidation
=
591 !gl
->IsSupported(gl::GLFeature::robust_buffer_access_behavior
);
592 switch (StaticPrefs::webgl_force_index_validation()) {
594 mNeedsIndexValidation
= false;
597 mNeedsIndexValidation
= true;
600 MOZ_ASSERT(StaticPrefs::webgl_force_index_validation() == 0);
604 for (auto& cur
: mExtensions
) {
611 bool WebGLContext::ValidateFramebufferTarget(GLenum target
) const {
614 case LOCAL_GL_FRAMEBUFFER
:
617 case LOCAL_GL_DRAW_FRAMEBUFFER
:
618 case LOCAL_GL_READ_FRAMEBUFFER
:
619 isValid
= IsWebGL2();
627 if (MOZ_LIKELY(isValid
)) {
631 ErrorInvalidEnumArg("target", target
);
635 } // namespace mozilla