1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "angle/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/Services.h"
16 #include "nsIObserverService.h"
17 #include "WebGLBuffer.h"
18 #include "WebGLContextUtils.h"
19 #include "WebGLFramebuffer.h"
20 #include "WebGLProgram.h"
21 #include "WebGLRenderbuffer.h"
22 #include "WebGLShader.h"
23 #include "WebGLTexture.h"
24 #include "WebGLUniformLocation.h"
25 #include "WebGLVertexArray.h"
26 #include "WebGLVertexAttribData.h"
28 #if defined(MOZ_WIDGET_COCOA)
29 #include "nsCocoaFeatures.h"
35 * Return the block size for format.
38 BlockSizeFor(GLenum format
, GLint
* const out_blockWidth
,
39 GLint
* const out_blockHeight
)
41 MOZ_ASSERT(out_blockWidth
&& out_blockHeight
);
44 case LOCAL_GL_ATC_RGB
:
45 case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA
:
46 case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA
:
47 case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
48 case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
49 case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
50 case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
55 case LOCAL_GL_ETC1_RGB8_OES
:
56 // 4x4 blocks, but no 4-multiple requirement.
65 IsCompressedFunc(WebGLTexImageFunc func
)
67 return func
== WebGLTexImageFunc::CompTexImage
||
68 func
== WebGLTexImageFunc::CompTexSubImage
;
72 * Same as ErrorInvalidEnum but uses WebGLContext::EnumName to print displayable
76 ErrorInvalidEnumWithName(WebGLContext
* ctx
, const char* msg
, GLenum glenum
,
77 WebGLTexImageFunc func
, WebGLTexDimensions dims
)
79 const char* name
= WebGLContext::EnumName(glenum
);
81 ctx
->ErrorInvalidEnum("%s: %s %s", InfoFrom(func
, dims
), msg
, name
);
83 ctx
->ErrorInvalidEnum("%s: %s 0x%04x", InfoFrom(func
, dims
), msg
,
89 * Return true if the format is valid for source calls.
92 IsAllowedFromSource(GLenum format
, WebGLTexImageFunc func
)
95 case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
96 case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
97 case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
98 case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
99 case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1
:
100 case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1
:
101 case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1
:
102 case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1
:
103 return (func
== WebGLTexImageFunc::CompTexImage
||
104 func
== WebGLTexImageFunc::CompTexSubImage
);
106 case LOCAL_GL_ATC_RGB
:
107 case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA
:
108 case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA
:
109 case LOCAL_GL_ETC1_RGB8_OES
:
110 return func
== WebGLTexImageFunc::CompTexImage
;
117 * Returns true if func is a CopyTexImage variant.
120 IsCopyFunc(WebGLTexImageFunc func
)
122 return (func
== WebGLTexImageFunc::CopyTexImage
||
123 func
== WebGLTexImageFunc::CopyTexSubImage
);
127 * Returns true if func is a SubImage variant.
130 IsSubFunc(WebGLTexImageFunc func
)
132 return (func
== WebGLTexImageFunc::TexSubImage
||
133 func
== WebGLTexImageFunc::CopyTexSubImage
||
134 func
== WebGLTexImageFunc::CompTexSubImage
);
138 * returns true is target is a texture cube map target.
141 IsTexImageCubemapTarget(GLenum texImageTarget
)
143 return (texImageTarget
>= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
144 texImageTarget
<= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
);
148 WebGLContext::ValidateBlendEquationEnum(GLenum mode
, const char* info
)
151 case LOCAL_GL_FUNC_ADD
:
152 case LOCAL_GL_FUNC_SUBTRACT
:
153 case LOCAL_GL_FUNC_REVERSE_SUBTRACT
:
158 if (IsExtensionEnabled(WebGLExtensionID::EXT_blend_minmax
))
167 ErrorInvalidEnumInfo(info
, mode
);
172 WebGLContext::ValidateBlendFuncDstEnum(GLenum factor
, const char* info
)
177 case LOCAL_GL_SRC_COLOR
:
178 case LOCAL_GL_ONE_MINUS_SRC_COLOR
:
179 case LOCAL_GL_DST_COLOR
:
180 case LOCAL_GL_ONE_MINUS_DST_COLOR
:
181 case LOCAL_GL_SRC_ALPHA
:
182 case LOCAL_GL_ONE_MINUS_SRC_ALPHA
:
183 case LOCAL_GL_DST_ALPHA
:
184 case LOCAL_GL_ONE_MINUS_DST_ALPHA
:
185 case LOCAL_GL_CONSTANT_COLOR
:
186 case LOCAL_GL_ONE_MINUS_CONSTANT_COLOR
:
187 case LOCAL_GL_CONSTANT_ALPHA
:
188 case LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA
:
192 ErrorInvalidEnumInfo(info
, factor
);
198 WebGLContext::ValidateBlendFuncSrcEnum(GLenum factor
, const char* info
)
200 if (factor
== LOCAL_GL_SRC_ALPHA_SATURATE
)
203 return ValidateBlendFuncDstEnum(factor
, info
);
207 WebGLContext::ValidateBlendFuncEnumsCompatibility(GLenum sfactor
,
211 bool sfactorIsConstantColor
= sfactor
== LOCAL_GL_CONSTANT_COLOR
||
212 sfactor
== LOCAL_GL_ONE_MINUS_CONSTANT_COLOR
;
213 bool sfactorIsConstantAlpha
= sfactor
== LOCAL_GL_CONSTANT_ALPHA
||
214 sfactor
== LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA
;
215 bool dfactorIsConstantColor
= dfactor
== LOCAL_GL_CONSTANT_COLOR
||
216 dfactor
== LOCAL_GL_ONE_MINUS_CONSTANT_COLOR
;
217 bool dfactorIsConstantAlpha
= dfactor
== LOCAL_GL_CONSTANT_ALPHA
||
218 dfactor
== LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA
;
219 if ( (sfactorIsConstantColor
&& dfactorIsConstantAlpha
) ||
220 (dfactorIsConstantColor
&& sfactorIsConstantAlpha
) )
222 ErrorInvalidOperation("%s are mutually incompatible, see section 6.8 in"
223 " the WebGL 1.0 spec", info
);
231 WebGLContext::ValidateDataOffsetSize(WebGLintptr offset
, WebGLsizeiptr size
, WebGLsizeiptr bufferSize
, const char* info
)
234 ErrorInvalidValue("%s: offset must be positive", info
);
239 ErrorInvalidValue("%s: size must be positive", info
);
243 // *** Careful *** WebGLsizeiptr is always 64-bits but GLsizeiptr
244 // is like intptr_t. On some platforms it is 32-bits.
245 CheckedInt
<GLsizeiptr
> neededBytes
= CheckedInt
<GLsizeiptr
>(offset
) + size
;
246 if (!neededBytes
.isValid() || neededBytes
.value() > bufferSize
) {
247 ErrorInvalidValue("%s: invalid range", info
);
255 * Check data ranges [readOffset, readOffset + size] and [writeOffset,
256 * writeOffset + size] for overlap.
258 * It is assumed that offset and size have already been validated with
259 * ValidateDataOffsetSize().
262 WebGLContext::ValidateDataRanges(WebGLintptr readOffset
, WebGLintptr writeOffset
, WebGLsizeiptr size
, const char* info
)
264 MOZ_ASSERT((CheckedInt
<WebGLsizeiptr
>(readOffset
) + size
).isValid());
265 MOZ_ASSERT((CheckedInt
<WebGLsizeiptr
>(writeOffset
) + size
).isValid());
267 bool separate
= (readOffset
+ size
< writeOffset
|| writeOffset
+ size
< readOffset
);
269 ErrorInvalidValue("%s: ranges [readOffset, readOffset + size) and [writeOffset, writeOffset + size) overlap");
275 WebGLContext::ValidateTextureTargetEnum(GLenum target
, const char* info
)
278 case LOCAL_GL_TEXTURE_2D
:
279 case LOCAL_GL_TEXTURE_CUBE_MAP
:
282 case LOCAL_GL_TEXTURE_3D
:
292 ErrorInvalidEnumInfo(info
, target
);
297 WebGLContext::ValidateComparisonEnum(GLenum target
, const char* info
)
302 case LOCAL_GL_LEQUAL
:
303 case LOCAL_GL_GREATER
:
304 case LOCAL_GL_GEQUAL
:
306 case LOCAL_GL_NOTEQUAL
:
307 case LOCAL_GL_ALWAYS
:
311 ErrorInvalidEnumInfo(info
, target
);
317 WebGLContext::ValidateStencilOpEnum(GLenum action
, const char* info
)
322 case LOCAL_GL_REPLACE
:
324 case LOCAL_GL_INCR_WRAP
:
326 case LOCAL_GL_DECR_WRAP
:
327 case LOCAL_GL_INVERT
:
331 ErrorInvalidEnumInfo(info
, action
);
337 WebGLContext::ValidateFaceEnum(GLenum face
, const char* info
)
342 case LOCAL_GL_FRONT_AND_BACK
:
346 ErrorInvalidEnumInfo(info
, face
);
352 WebGLContext::ValidateDrawModeEnum(GLenum mode
, const char* info
)
355 case LOCAL_GL_TRIANGLES
:
356 case LOCAL_GL_TRIANGLE_STRIP
:
357 case LOCAL_GL_TRIANGLE_FAN
:
358 case LOCAL_GL_POINTS
:
359 case LOCAL_GL_LINE_STRIP
:
360 case LOCAL_GL_LINE_LOOP
:
365 ErrorInvalidEnumInfo(info
, mode
);
371 WebGLContext::ValidateGLSLVariableName(const nsAString
& name
, const char* info
)
376 const uint32_t maxSize
= 256;
377 if (name
.Length() > maxSize
) {
378 ErrorInvalidValue("%s: Identifier is %d characters long, exceeds the"
379 " maximum allowed length of %d characters.", info
,
380 name
.Length(), maxSize
);
384 if (!ValidateGLSLString(name
, info
))
387 nsString prefix1
= NS_LITERAL_STRING("webgl_");
388 nsString prefix2
= NS_LITERAL_STRING("_webgl_");
390 if (Substring(name
, 0, prefix1
.Length()).Equals(prefix1
) ||
391 Substring(name
, 0, prefix2
.Length()).Equals(prefix2
))
393 ErrorInvalidOperation("%s: String contains a reserved GLSL prefix.",
401 bool WebGLContext::ValidateGLSLString(const nsAString
& string
, const char* info
)
403 for (uint32_t i
= 0; i
< string
.Length(); ++i
) {
404 if (!ValidateGLSLCharacter(string
.CharAt(i
))) {
405 ErrorInvalidValue("%s: String contains the illegal character"
406 " '%d'.", info
, string
.CharAt(i
));
415 * Return true if the framebuffer attachment is valid. Attachment must
416 * be one of depth/stencil/depth_stencil/color attachment.
419 WebGLContext::ValidateFramebufferAttachment(GLenum attachment
,
420 const char* funcName
)
422 if (!mBoundFramebuffer
) {
423 switch (attachment
) {
426 case LOCAL_GL_STENCIL
:
430 ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.",
431 funcName
, attachment
);
436 if (attachment
== LOCAL_GL_DEPTH_ATTACHMENT
||
437 attachment
== LOCAL_GL_STENCIL_ATTACHMENT
||
438 attachment
== LOCAL_GL_DEPTH_STENCIL_ATTACHMENT
)
443 GLenum colorAttachCount
= 1;
444 if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers
))
445 colorAttachCount
= mGLMaxColorAttachments
;
447 if (attachment
>= LOCAL_GL_COLOR_ATTACHMENT0
&&
448 attachment
< GLenum(LOCAL_GL_COLOR_ATTACHMENT0
+ colorAttachCount
))
453 ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.", funcName
,
459 * Return true if pname is valid for GetSamplerParameter calls.
462 WebGLContext::ValidateSamplerParameterName(GLenum pname
, const char* info
)
465 case LOCAL_GL_TEXTURE_MIN_FILTER
:
466 case LOCAL_GL_TEXTURE_MAG_FILTER
:
467 case LOCAL_GL_TEXTURE_WRAP_S
:
468 case LOCAL_GL_TEXTURE_WRAP_T
:
469 case LOCAL_GL_TEXTURE_WRAP_R
:
470 case LOCAL_GL_TEXTURE_MIN_LOD
:
471 case LOCAL_GL_TEXTURE_MAX_LOD
:
472 case LOCAL_GL_TEXTURE_COMPARE_MODE
:
473 case LOCAL_GL_TEXTURE_COMPARE_FUNC
:
477 ErrorInvalidEnum("%s: invalid pname: %s", info
, EnumName(pname
));
483 * Return true if pname and param are valid combination for SamplerParameter calls.
486 WebGLContext::ValidateSamplerParameterParams(GLenum pname
, const WebGLIntOrFloat
& param
, const char* info
)
488 const GLenum p
= param
.AsInt();
491 case LOCAL_GL_TEXTURE_MIN_FILTER
:
493 case LOCAL_GL_NEAREST
:
494 case LOCAL_GL_LINEAR
:
495 case LOCAL_GL_NEAREST_MIPMAP_NEAREST
:
496 case LOCAL_GL_NEAREST_MIPMAP_LINEAR
:
497 case LOCAL_GL_LINEAR_MIPMAP_NEAREST
:
498 case LOCAL_GL_LINEAR_MIPMAP_LINEAR
:
502 ErrorInvalidEnum("%s: invalid param: %s", info
, EnumName(p
));
506 case LOCAL_GL_TEXTURE_MAG_FILTER
:
508 case LOCAL_GL_NEAREST
:
509 case LOCAL_GL_LINEAR
:
513 ErrorInvalidEnum("%s: invalid param: %s", info
, EnumName(p
));
517 case LOCAL_GL_TEXTURE_WRAP_S
:
518 case LOCAL_GL_TEXTURE_WRAP_T
:
519 case LOCAL_GL_TEXTURE_WRAP_R
:
521 case LOCAL_GL_CLAMP_TO_EDGE
:
522 case LOCAL_GL_REPEAT
:
523 case LOCAL_GL_MIRRORED_REPEAT
:
527 ErrorInvalidEnum("%s: invalid param: %s", info
, EnumName(p
));
531 case LOCAL_GL_TEXTURE_MIN_LOD
:
532 case LOCAL_GL_TEXTURE_MAX_LOD
:
535 case LOCAL_GL_TEXTURE_COMPARE_MODE
:
536 switch (param
.AsInt()) {
538 case LOCAL_GL_COMPARE_REF_TO_TEXTURE
:
542 ErrorInvalidEnum("%s: invalid param: %s", info
, EnumName(p
));
546 case LOCAL_GL_TEXTURE_COMPARE_FUNC
:
548 case LOCAL_GL_LEQUAL
:
549 case LOCAL_GL_GEQUAL
:
551 case LOCAL_GL_GREATER
:
553 case LOCAL_GL_NOTEQUAL
:
554 case LOCAL_GL_ALWAYS
:
559 ErrorInvalidEnum("%s: invalid param: %s", info
, EnumName(p
));
564 ErrorInvalidEnum("%s: invalid pname: %s", info
, EnumName(pname
));
571 * Return true if format is a valid texture image format for source,
572 * taking into account enabled WebGL extensions.
575 WebGLContext::ValidateTexImageFormat(GLenum format
, WebGLTexImageFunc func
,
576 WebGLTexDimensions dims
)
578 /* Core WebGL texture formats */
579 if (format
== LOCAL_GL_ALPHA
||
580 format
== LOCAL_GL_RGB
||
581 format
== LOCAL_GL_RGBA
||
582 format
== LOCAL_GL_LUMINANCE
||
583 format
== LOCAL_GL_LUMINANCE_ALPHA
)
588 /* WebGL2 new formats */
589 if (format
== LOCAL_GL_RED
||
590 format
== LOCAL_GL_RG
||
591 format
== LOCAL_GL_RED_INTEGER
||
592 format
== LOCAL_GL_RG_INTEGER
||
593 format
== LOCAL_GL_RGB_INTEGER
||
594 format
== LOCAL_GL_RGBA_INTEGER
)
599 ErrorInvalidEnum("%s: Invalid format %s: Requires WebGL version 2.0 or"
600 " newer.", InfoFrom(func
, dims
), EnumName(format
));
604 /* WEBGL_depth_texture added formats */
605 if (format
== LOCAL_GL_DEPTH_COMPONENT
||
606 format
== LOCAL_GL_DEPTH_STENCIL
)
608 if (!IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture
)) {
609 ErrorInvalidEnum("%s: Invalid format %s: Requires that"
610 " WEBGL_depth_texture is enabled.",
611 InfoFrom(func
, dims
), EnumName(format
));
615 // If WEBGL_depth_texture is enabled, then it is not allowed to be used
616 // with the copyTexImage, or copyTexSubImage methods, and it is not
617 // allowed with texSubImage in WebGL1.
618 if ((func
== WebGLTexImageFunc::TexSubImage
&& !IsWebGL2()) ||
619 func
== WebGLTexImageFunc::CopyTexImage
||
620 func
== WebGLTexImageFunc::CopyTexSubImage
)
622 ErrorInvalidOperation("%s: format %s is not supported",
623 InfoFrom(func
, dims
), EnumName(format
));
630 // Needs to be below the depth_texture check because an invalid operation
631 // error needs to be generated instead of invalid enum.
632 // Only core formats are valid for CopyTex[Sub]Image.
633 // TODO: Revisit this once color_buffer_[half_]float lands.
634 if (IsCopyFunc(func
)) {
635 ErrorInvalidEnumWithName(this, "invalid format", format
, func
, dims
);
639 // EXT_sRGB added formats
640 if (format
== LOCAL_GL_SRGB
||
641 format
== LOCAL_GL_SRGB_ALPHA
)
643 if (IsExtensionEnabled(WebGLExtensionID::EXT_sRGB
))
646 ErrorInvalidEnum("%s: Invalid format %s: Requires that EXT_sRGB is"
647 " enabled.", InfoFrom(func
, dims
),
648 WebGLContext::EnumName(format
));
652 ErrorInvalidEnumWithName(this, "invalid format", format
, func
, dims
);
657 * Check if the given texture target is valid for TexImage.
660 WebGLContext::ValidateTexImageTarget(GLenum target
, WebGLTexImageFunc func
,
661 WebGLTexDimensions dims
)
664 case WebGLTexDimensions::Tex2D
:
665 if (target
== LOCAL_GL_TEXTURE_2D
||
666 IsTexImageCubemapTarget(target
))
671 ErrorInvalidEnumWithName(this, "invalid target", target
, func
, dims
);
674 case WebGLTexDimensions::Tex3D
:
675 if (target
== LOCAL_GL_TEXTURE_3D
)
680 ErrorInvalidEnumWithName(this, "invalid target", target
, func
, dims
);
684 MOZ_ASSERT(false, "ValidateTexImageTarget: Invalid dims");
691 * Return true if type is a valid texture image type for source,
692 * taking into account enabled WebGL extensions.
695 WebGLContext::ValidateTexImageType(GLenum type
, WebGLTexImageFunc func
,
696 WebGLTexDimensions dims
)
698 /* Core WebGL texture types */
699 if (type
== LOCAL_GL_UNSIGNED_BYTE
||
700 type
== LOCAL_GL_UNSIGNED_SHORT_5_6_5
||
701 type
== LOCAL_GL_UNSIGNED_SHORT_4_4_4_4
||
702 type
== LOCAL_GL_UNSIGNED_SHORT_5_5_5_1
)
707 /* WebGL2 new types */
708 if (type
== LOCAL_GL_BYTE
||
709 type
== LOCAL_GL_SHORT
||
710 type
== LOCAL_GL_INT
||
711 type
== LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV
||
712 type
== LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV
||
713 type
== LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV
||
714 type
== LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV
)
719 ErrorInvalidEnum("%s: Invalid type %s: Requires WebGL version 2.0 or"
720 " newer.", InfoFrom(func
, dims
),
721 WebGLContext::EnumName(type
));
725 /* OES_texture_float added types */
726 if (type
== LOCAL_GL_FLOAT
) {
727 if (IsExtensionEnabled(WebGLExtensionID::OES_texture_float
))
730 ErrorInvalidEnum("%s: Invalid type %s: Requires that OES_texture_float"
732 InfoFrom(func
, dims
), WebGLContext::EnumName(type
));
736 /* OES_texture_half_float add types */
737 if (type
== LOCAL_GL_HALF_FLOAT
) {
738 if (IsExtensionEnabled(WebGLExtensionID::OES_texture_half_float
))
741 ErrorInvalidEnum("%s: Invalid type %s: Requires that"
742 " OES_texture_half_float is enabled.",
743 InfoFrom(func
, dims
), WebGLContext::EnumName(type
));
747 /* WEBGL_depth_texture added types */
748 if (type
== LOCAL_GL_UNSIGNED_SHORT
||
749 type
== LOCAL_GL_UNSIGNED_INT
||
750 type
== LOCAL_GL_UNSIGNED_INT_24_8
)
752 if (IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture
))
755 ErrorInvalidEnum("%s: Invalid type %s: Requires that"
756 " WEBGL_depth_texture is enabled.",
757 InfoFrom(func
, dims
), WebGLContext::EnumName(type
));
761 ErrorInvalidEnumWithName(this, "invalid type", type
, func
, dims
);
766 * Validate texture image sizing extra constraints for
767 * CompressedTex(Sub)?Image.
771 WebGLContext::ValidateCompTexImageSize(GLint level
, GLenum format
,
772 GLint xoffset
, GLint yoffset
,
773 GLsizei width
, GLsizei height
,
774 GLsizei levelWidth
, GLsizei levelHeight
,
775 WebGLTexImageFunc func
,
776 WebGLTexDimensions dims
)
778 // Negative parameters must already have been handled above
779 MOZ_ASSERT(xoffset
>= 0 && yoffset
>= 0 &&
780 width
>= 0 && height
>= 0);
782 if (xoffset
+ width
> (GLint
) levelWidth
) {
783 ErrorInvalidValue("%s: xoffset + width must be <= levelWidth.",
784 InfoFrom(func
, dims
));
788 if (yoffset
+ height
> (GLint
) levelHeight
) {
789 ErrorInvalidValue("%s: yoffset + height must be <= levelHeight.",
790 InfoFrom(func
, dims
));
794 GLint blockWidth
= 1;
795 GLint blockHeight
= 1;
796 BlockSizeFor(format
, &blockWidth
, &blockHeight
);
798 // If blockWidth || blockHeight != 1, then the compressed format had
799 // block-based constraints to be checked. (For example, PVRTC is compressed
800 // but isn't a block-based format)
801 if (blockWidth
!= 1 || blockHeight
!= 1) {
802 // Offsets must be multiple of block size.
803 if (xoffset
% blockWidth
!= 0) {
804 ErrorInvalidOperation("%s: xoffset must be multiple of %d.",
805 InfoFrom(func
, dims
), blockWidth
);
809 if (yoffset
% blockHeight
!= 0) {
810 ErrorInvalidOperation("%s: yoffset must be multiple of %d.",
811 InfoFrom(func
, dims
), blockHeight
);
815 /* The size must be a multiple of blockWidth and blockHeight, or must be
816 * using offset+size that exactly hits the edge. Important for small
819 * From the WEBGL_compressed_texture_s3tc spec:
820 * When level equals zero width and height must be a multiple of 4.
821 * When level is greater than 0 width and height must be 0, 1, 2 or
822 * a multiple of 4. If they are not an INVALID_OPERATION error is
826 if (width
% blockWidth
!= 0) {
827 ErrorInvalidOperation("%s: Width of level 0 must be a multiple"
828 " of %d.", InfoFrom(func
, dims
),
833 if (height
% blockHeight
!= 0) {
834 ErrorInvalidOperation("%s: Height of level 0 must be a multiple"
835 " of %d.", InfoFrom(func
, dims
),
839 } else if (level
> 0) {
840 if (width
% blockWidth
!= 0 && width
> 2) {
841 ErrorInvalidOperation("%s: Width of level %d must be a multiple"
842 " of %d, or be 0, 1, or 2.",
843 InfoFrom(func
, dims
), level
, blockWidth
);
847 if (height
% blockHeight
!= 0 && height
> 2) {
848 ErrorInvalidOperation("%s: Height of level %d must be a"
849 " multiple of %d, or be 0, 1, or 2.",
850 InfoFrom(func
, dims
), level
, blockHeight
);
855 if (IsSubFunc(func
)) {
856 if ((xoffset
% blockWidth
) != 0) {
857 ErrorInvalidOperation("%s: xoffset must be a multiple of %d.",
858 InfoFrom(func
, dims
), blockWidth
);
862 if (yoffset
% blockHeight
!= 0) {
863 ErrorInvalidOperation("%s: yoffset must be a multiple of %d.",
864 InfoFrom(func
, dims
), blockHeight
);
871 case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1
:
872 case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1
:
873 case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1
:
874 case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1
:
875 if (!IsPOTAssumingNonnegative(width
) ||
876 !IsPOTAssumingNonnegative(height
))
878 ErrorInvalidValue("%s: Width and height must be powers of two.",
879 InfoFrom(func
, dims
));
888 * Return true if the enough data is present to satisfy compressed
889 * texture format constraints.
892 WebGLContext::ValidateCompTexImageDataSize(GLint level
, GLenum format
,
893 GLsizei width
, GLsizei height
,
895 WebGLTexImageFunc func
,
896 WebGLTexDimensions dims
)
898 // negative width and height must already have been handled above
899 MOZ_ASSERT(width
>= 0 && height
>= 0);
901 CheckedUint32 required_byteLength
= 0;
904 case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
905 case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
906 case LOCAL_GL_ATC_RGB
:
907 case LOCAL_GL_ETC1_RGB8_OES
:
908 required_byteLength
= ((CheckedUint32(width
) + 3) / 4) *
909 ((CheckedUint32(height
) + 3) / 4) * 8;
912 case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
913 case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
914 case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA
:
915 case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA
:
916 required_byteLength
= ((CheckedUint32(width
) + 3) / 4) *
917 ((CheckedUint32(height
) + 3) / 4) * 16;
920 case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1
:
921 case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1
:
922 required_byteLength
= CheckedUint32(std::max(width
, 8)) *
923 CheckedUint32(std::max(height
, 8)) / 2;
926 case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1
:
927 case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1
:
928 required_byteLength
= CheckedUint32(std::max(width
, 16)) *
929 CheckedUint32(std::max(height
, 8)) / 4;
933 if (!required_byteLength
.isValid() ||
934 required_byteLength
.value() != byteLength
)
936 ErrorInvalidValue("%s: Data size does not match dimensions.",
937 InfoFrom(func
, dims
));
945 * Validate the width, height, and depth of a texture image, \return
946 * true is valid, false otherwise.
947 * Used by all the (Compressed|Copy)?Tex(Sub)?Image functions.
948 * Target and level must have been validated before calling.
951 WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget
, GLint level
,
952 GLint width
, GLint height
, GLint depth
,
953 WebGLTexImageFunc func
,
954 WebGLTexDimensions dims
)
956 MOZ_ASSERT(level
>= 0, "level should already be validated");
958 /* Bug 966630: maxTextureSize >> level runs into "undefined"
959 * behaviour depending on ISA. For example, on Intel shifts
960 * amounts are mod 64 (in 64-bit mode on 64-bit dest) and mod 32
961 * otherwise. This means 16384 >> 0x10000001 == 8192 which isn't
962 * what would be expected. Make the required behaviour explicit by
963 * clamping to a shift of 31 bits if level is greater than that
964 * ammount. This will give 0 that if (!maxAllowedSize) is
971 auto texTarget
= TexImageTargetToTexTarget(texImageTarget
);
972 const GLuint maxTexImageSize
= MaxTextureSizeForTarget(texTarget
) >> level
;
974 const bool isCubemapTarget
= IsTexImageCubemapTarget(texImageTarget
.get());
975 const bool isSub
= IsSubFunc(func
);
977 if (!isSub
&& isCubemapTarget
&& (width
!= height
)) {
978 /* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
979 * "When the target parameter to TexImage2D is one of the
980 * six cube map two-dimensional image targets, the error
981 * INVALID_VALUE is generated if the width and height
982 * parameters are not equal."
984 ErrorInvalidValue("%s: For cube maps, width must equal height.",
985 InfoFrom(func
, dims
));
989 if (texImageTarget
== LOCAL_GL_TEXTURE_2D
|| isCubemapTarget
) {
990 /* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
991 * "If wt and ht are the specified image width and height,
992 * and if either wt or ht are less than zero, then the error
993 * INVALID_VALUE is generated."
996 ErrorInvalidValue("%s: Width must be >= 0.", InfoFrom(func
, dims
));
1001 ErrorInvalidValue("%s: Height must be >= 0.", InfoFrom(func
, dims
));
1005 /* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
1006 * "The maximum allowable width and height of a
1007 * two-dimensional texture image must be at least 2**(k−lod)
1008 * for image arrays of level zero through k, where k is the
1009 * log base 2 of MAX_TEXTURE_SIZE. and lod is the
1010 * level-of-detail of the image array. It may be zero for
1011 * image arrays of any level-of-detail greater than k. The
1012 * error INVALID_VALUE is generated if the specified image
1013 * is too large to be stored under any conditions.
1015 if (width
> (int) maxTexImageSize
) {
1016 ErrorInvalidValue("%s: The maximum width for level %d is %u.",
1017 InfoFrom(func
, dims
), level
, maxTexImageSize
);
1021 if (height
> (int) maxTexImageSize
) {
1022 ErrorInvalidValue("%s: The maximum height for level %d is %u.",
1023 InfoFrom(func
, dims
), level
, maxTexImageSize
);
1027 /* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
1028 * "If level is greater than zero, and either width or
1029 * height is not a power-of-two, the error INVALID_VALUE is
1032 * This restriction does not apply to GL ES Version 3.0+.
1034 if (!IsWebGL2() && level
> 0) {
1035 if (!IsPOTAssumingNonnegative(width
)) {
1036 ErrorInvalidValue("%s: For level > 0, width of %d must be a"
1037 " power of two.", InfoFrom(func
, dims
),
1042 if (!IsPOTAssumingNonnegative(height
)) {
1043 ErrorInvalidValue("%s: For level > 0, height of %d must be a"
1044 " power of two.", InfoFrom(func
, dims
),
1052 if (texImageTarget
== LOCAL_GL_TEXTURE_3D
) {
1054 ErrorInvalidValue("%s: Depth must be >= 0.", InfoFrom(func
, dims
));
1058 if (!IsWebGL2() && !IsPOTAssumingNonnegative(depth
)) {
1059 ErrorInvalidValue("%s: Depth of %d must be a power of two.",
1060 InfoFrom(func
, dims
), depth
);
1069 * Validate texture image sizing for Tex(Sub)?Image variants.
1071 // TODO: WebGL 2. Update this to handle 3D textures.
1073 WebGLContext::ValidateTexSubImageSize(GLint xoffset
, GLint yoffset
,
1074 GLint
/*zoffset*/, GLsizei width
,
1075 GLsizei height
, GLsizei
/*depth*/,
1076 GLsizei baseWidth
, GLsizei baseHeight
,
1077 GLsizei
/*baseDepth*/,
1078 WebGLTexImageFunc func
,
1079 WebGLTexDimensions dims
)
1081 /* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
1082 * "Taking wt and ht to be the specified width and height of the
1083 * texture array, and taking x, y, w, and h to be the xoffset,
1084 * yoffset, width, and height argument values, any of the
1085 * following relationships generates the error INVALID_VALUE:
1093 ErrorInvalidValue("%s: xoffset must be >= 0.", InfoFrom(func
, dims
));
1098 ErrorInvalidValue("%s: yoffset must be >= 0.", InfoFrom(func
, dims
));
1102 if (!CanvasUtils::CheckSaneSubrectSize(xoffset
, yoffset
, width
, height
,
1103 baseWidth
, baseHeight
))
1105 ErrorInvalidValue("%s: Subtexture rectangle out-of-bounds.",
1106 InfoFrom(func
, dims
));
1114 * Perform validation of format/type combinations for TexImage variants.
1115 * Returns true if the format/type is a valid combination, false otherwise.
1118 WebGLContext::ValidateTexImageFormatAndType(GLenum format
, GLenum type
,
1119 WebGLTexImageFunc func
,
1120 WebGLTexDimensions dims
)
1122 if (IsCompressedFunc(func
) || IsCopyFunc(func
)) {
1123 MOZ_ASSERT(type
== LOCAL_GL_NONE
&& format
== LOCAL_GL_NONE
);
1127 if (!ValidateTexImageFormat(format
, func
, dims
) ||
1128 !ValidateTexImageType(type
, func
, dims
))
1133 // Here we're reinterpreting format as an unsized internalformat;
1134 // these are the same in practice and there's no point in having the
1135 // same code implemented twice.
1136 TexInternalFormat effective
=
1137 EffectiveInternalFormatFromInternalFormatAndType(format
, type
);
1139 if (effective
!= LOCAL_GL_NONE
)
1142 ErrorInvalidOperation("%s: Invalid combination of format %s and type %s.",
1143 InfoFrom(func
, dims
), WebGLContext::EnumName(format
),
1144 WebGLContext::EnumName(type
));
1149 WebGLContext::ValidateCompTexImageInternalFormat(GLenum format
,
1150 WebGLTexImageFunc func
,
1151 WebGLTexDimensions dims
)
1153 if (!IsCompressedTextureFormat(format
)) {
1154 ErrorInvalidEnum("%s: Invalid compressed texture format: %s",
1155 InfoFrom(func
, dims
), WebGLContext::EnumName(format
));
1159 /* WEBGL_compressed_texture_atc added formats */
1160 if (format
== LOCAL_GL_ATC_RGB
||
1161 format
== LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA
||
1162 format
== LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA
)
1164 if (IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_atc
))
1167 ErrorInvalidEnum("%s: Invalid format %s: Requires that"
1168 " WEBGL_compressed_texture_atc is enabled.",
1169 InfoFrom(func
, dims
), WebGLContext::EnumName(format
));
1173 // WEBGL_compressed_texture_etc1
1174 if (format
== LOCAL_GL_ETC1_RGB8_OES
) {
1175 if (IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_etc1
))
1178 ErrorInvalidEnum("%s: Invalid format %s: Requires that"
1179 " WEBGL_compressed_texture_etc1 is enabled.",
1180 InfoFrom(func
, dims
), WebGLContext::EnumName(format
));
1185 if (format
== LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1
||
1186 format
== LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1
||
1187 format
== LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1
||
1188 format
== LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1
)
1190 if (IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_pvrtc
))
1193 ErrorInvalidEnum("%s: Invalid format %s: Requires that"
1194 " WEBGL_compressed_texture_pvrtc is enabled.",
1195 InfoFrom(func
, dims
), WebGLContext::EnumName(format
));
1200 if (format
== LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT
||
1201 format
== LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
||
1202 format
== LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
||
1203 format
== LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
)
1205 if (IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_s3tc
))
1208 ErrorInvalidEnum("%s: Invalid format %s: Requires that"
1209 " WEBGL_compressed_texture_s3tc is enabled.",
1210 InfoFrom(func
, dims
), WebGLContext::EnumName(format
));
1219 WebGLContext::ValidateCopyTexImageInternalFormat(GLenum format
,
1220 WebGLTexImageFunc func
,
1221 WebGLTexDimensions dims
)
1226 case LOCAL_GL_LUMINANCE_ALPHA
:
1227 case LOCAL_GL_LUMINANCE
:
1228 case LOCAL_GL_ALPHA
:
1231 // In CopyTexImage, internalFormat is a function parameter,
1232 // so a bad value is an INVALID_ENUM error.
1233 // In CopyTexSubImage, internalFormat is part of existing state,
1234 // so this is an INVALID_OPERATION error.
1235 GenerateWarning("%s: Invalid texture internal format: %s",
1236 InfoFrom(func
, dims
), WebGLContext::EnumName(format
));
1239 if (func
== WebGLTexImageFunc::CopyTexImage
)
1240 error
= LOCAL_GL_INVALID_ENUM
;
1242 error
= LOCAL_GL_INVALID_OPERATION
;
1244 SynthesizeGLError(error
);
1248 * Return true if format, type and jsArrayType are a valid combination.
1249 * Also returns the size for texel of format and type (in bytes) via
1252 * It is assumed that type has previously been validated.
1255 WebGLContext::ValidateTexInputData(GLenum type
, js::Scalar::Type jsArrayType
,
1256 WebGLTexImageFunc func
,
1257 WebGLTexDimensions dims
)
1259 // We're using js::Scalar::MaxTypedArrayViewType as dummy value for when
1260 // the tex source wasn't a typed array.
1261 if (jsArrayType
== js::Scalar::MaxTypedArrayViewType
)
1264 const char invalidTypedArray
[] = "%s: Invalid typed array type for given"
1265 " texture data type.";
1267 bool validInput
= false;
1269 case LOCAL_GL_UNSIGNED_BYTE
:
1270 validInput
= jsArrayType
== js::Scalar::Uint8
;
1274 validInput
= jsArrayType
== js::Scalar::Int8
;
1277 case LOCAL_GL_HALF_FLOAT
:
1278 case LOCAL_GL_UNSIGNED_SHORT
:
1279 case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4
:
1280 case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1
:
1281 case LOCAL_GL_UNSIGNED_SHORT_5_6_5
:
1282 validInput
= jsArrayType
== js::Scalar::Uint16
;
1285 case LOCAL_GL_SHORT
:
1286 validInput
= jsArrayType
== js::Scalar::Int16
;
1289 case LOCAL_GL_UNSIGNED_INT
:
1290 case LOCAL_GL_UNSIGNED_INT_24_8
:
1291 case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV
:
1292 case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV
:
1293 case LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV
:
1294 validInput
= jsArrayType
== js::Scalar::Uint32
;
1298 validInput
= jsArrayType
== js::Scalar::Int32
;
1301 case LOCAL_GL_FLOAT
:
1302 validInput
= jsArrayType
== js::Scalar::Float32
;
1310 ErrorInvalidOperation(invalidTypedArray
, InfoFrom(func
, dims
));
1316 * Checks specific for the CopyTex[Sub]Image2D functions.
1318 * - Framebuffer is complete and has valid read planes
1319 * - Copy format is a subset of framebuffer format (i.e. all required components
1323 WebGLContext::ValidateCopyTexImage(GLenum format
, WebGLTexImageFunc func
,
1324 WebGLTexDimensions dims
)
1326 MOZ_ASSERT(IsCopyFunc(func
));
1328 // Default framebuffer format
1329 GLenum fboFormat
= mOptions
.alpha
? LOCAL_GL_RGBA
: LOCAL_GL_RGB
;
1331 if (mBoundFramebuffer
) {
1332 if (!mBoundFramebuffer
->CheckAndInitializeAttachments()) {
1333 ErrorInvalidFramebufferOperation("%s: Incomplete framebuffer.",
1334 InfoFrom(func
, dims
));
1338 GLenum readPlaneBits
= LOCAL_GL_COLOR_BUFFER_BIT
;
1339 if (!mBoundFramebuffer
->HasCompletePlanes(readPlaneBits
)) {
1340 ErrorInvalidOperation("%s: Read source attachment doesn't have the"
1341 " correct color/depth/stencil type.",
1342 InfoFrom(func
, dims
));
1346 // Get the correct format for the framebuffer, as it's not the default
1348 const WebGLFramebuffer::Attachment
& color0
=
1349 mBoundFramebuffer
->GetAttachment(LOCAL_GL_COLOR_ATTACHMENT0
);
1351 fboFormat
= mBoundFramebuffer
->GetFormatForAttachment(color0
);
1354 // Make sure the format of the framebuffer is a superset of the format
1355 // requested by the CopyTex[Sub]Image2D functions.
1356 const GLComponents formatComps
= GLComponents(format
);
1357 const GLComponents fboComps
= GLComponents(fboFormat
);
1358 if (!formatComps
.IsSubsetOf(fboComps
)) {
1359 ErrorInvalidOperation("%s: Format %s is not a subset of the current"
1360 " framebuffer format, which is %s.",
1361 InfoFrom(func
, dims
), EnumName(format
),
1362 EnumName(fboFormat
));
1370 * Test the gl(Copy|Compressed)?Tex[Sub]?Image[23]() parameters for errors.
1371 * Verifies each of the parameters against the WebGL standard and enabled
1374 // TODO: Texture dims is here for future expansion in WebGL 2.0
1376 WebGLContext::ValidateTexImage(TexImageTarget texImageTarget
, GLint level
,
1377 GLenum internalFormat
, GLint xoffset
,
1378 GLint yoffset
, GLint zoffset
, GLint width
,
1379 GLint height
, GLint depth
, GLint border
,
1380 GLenum format
, GLenum type
,
1381 WebGLTexImageFunc func
,
1382 WebGLTexDimensions dims
)
1384 const char* info
= InfoFrom(func
, dims
);
1388 ErrorInvalidValue("%s: `level` must be >= 0.", info
);
1394 ErrorInvalidValue("%s: `border` must be 0.", info
);
1398 // Check incoming image format and type
1399 if (!ValidateTexImageFormatAndType(format
, type
, func
, dims
))
1402 if (!TexInternalFormat::IsValueLegal(internalFormat
)) {
1403 ErrorInvalidEnum("%s: Invalid `internalformat` enum %s.", info
,
1404 EnumName(internalFormat
));
1407 TexInternalFormat unsizedInternalFormat
=
1408 UnsizedInternalFormatFromInternalFormat(internalFormat
);
1410 if (IsCompressedFunc(func
)) {
1411 if (!ValidateCompTexImageInternalFormat(internalFormat
, func
, dims
))
1414 } else if (IsCopyFunc(func
)) {
1415 if (!ValidateCopyTexImageInternalFormat(unsizedInternalFormat
.get(),
1420 } else if (format
!= unsizedInternalFormat
) {
1422 // In WebGL2, it's OK to have `internalFormat != format` if
1423 // internalFormat is the sized internal format corresponding to the
1424 // (format, type) pair according to Table 3.2 in the OpenGL ES 3.0.3
1426 auto effectiveFormat
= EffectiveInternalFormatFromInternalFormatAndType(format
,
1428 if (internalFormat
!= effectiveFormat
) {
1429 bool exceptionallyAllowed
= false;
1430 if (internalFormat
== LOCAL_GL_SRGB8_ALPHA8
&&
1431 format
== LOCAL_GL_RGBA
&&
1432 type
== LOCAL_GL_UNSIGNED_BYTE
)
1434 exceptionallyAllowed
= true;
1436 else if (internalFormat
== LOCAL_GL_SRGB8
&&
1437 format
== LOCAL_GL_RGB
&&
1438 type
== LOCAL_GL_UNSIGNED_BYTE
)
1440 exceptionallyAllowed
= true;
1442 if (!exceptionallyAllowed
) {
1443 ErrorInvalidOperation("%s: `internalformat` does not match"
1444 " `format` and `type`.", info
);
1449 // In WebGL 1, format must be equal to internalformat.
1450 ErrorInvalidOperation("%s: `internalformat` does not match"
1451 " `format`.", info
);
1456 // Check texture image size
1457 if (!ValidateTexImageSize(texImageTarget
, level
, width
, height
, 0, func
,
1463 /* 5.14.8 Texture objects - WebGL Spec.
1464 * "If an attempt is made to call these functions with no
1465 * WebGLTexture bound (see above), an INVALID_OPERATION error
1468 WebGLTexture
* tex
= ActiveBoundTextureForTexImageTarget(texImageTarget
);
1470 ErrorInvalidOperation("%s: No texture is bound to target %s.", info
,
1471 WebGLContext::EnumName(texImageTarget
.get()));
1475 if (IsSubFunc(func
)) {
1476 if (!tex
->HasImageInfoAt(texImageTarget
, level
)) {
1477 ErrorInvalidOperation("%s: No texture image previously defined for"
1478 " target %s at level %d.", info
,
1479 WebGLContext::EnumName(texImageTarget
.get()),
1484 const auto& imageInfo
= tex
->ImageInfoAt(texImageTarget
, level
);
1485 if (!ValidateTexSubImageSize(xoffset
, yoffset
, zoffset
, width
, height
,
1486 depth
, imageInfo
.Width(),
1487 imageInfo
.Height(), 0, func
, dims
))
1493 // Additional checks for depth textures
1494 if (texImageTarget
!= LOCAL_GL_TEXTURE_2D
&&
1495 (format
== LOCAL_GL_DEPTH_COMPONENT
||
1496 format
== LOCAL_GL_DEPTH_STENCIL
))
1498 ErrorInvalidOperation("%s: With format of %s, target must be"
1499 " TEXTURE_2D.", info
,
1500 WebGLContext::EnumName(format
));
1504 // Additional checks for compressed textures
1505 if (!IsAllowedFromSource(internalFormat
, func
)) {
1506 ErrorInvalidOperation("%s: Invalid format %s for this operation.",
1507 info
, WebGLContext::EnumName(format
));
1511 // Parameters are OK
1516 WebGLContext::ValidateUniformLocation(const char* info
,
1517 WebGLUniformLocation
* loc
)
1519 if (!ValidateObjectAllowNull(info
, loc
))
1525 // The need to check specifically for !mCurrentProgram here is explained in
1527 if (!mCurrentProgram
) {
1528 ErrorInvalidOperation("%s: No program is currently bound.", info
);
1532 if (mCurrentProgram
!= loc
->Program()) {
1533 ErrorInvalidOperation("%s: This uniform location doesn't correspond to"
1534 " the current program.", info
);
1538 if (mCurrentProgram
->Generation() != loc
->ProgramGeneration()) {
1539 ErrorInvalidOperation("%s: This uniform location is obsolete since the"
1540 " program has been relinked.", info
);
1548 WebGLContext::ValidateSamplerUniformSetter(const char* info
,
1549 WebGLUniformLocation
* loc
,
1552 if (loc
->Info().type
!= LOCAL_GL_SAMPLER_2D
&&
1553 loc
->Info().type
!= LOCAL_GL_SAMPLER_CUBE
)
1558 if (value
>= 0 && value
< mGLMaxTextureUnits
)
1561 ErrorInvalidValue("%s: This uniform location is a sampler, but %d is not a"
1562 " valid texture unit.", info
, value
);
1567 WebGLContext::ValidateAttribArraySetter(const char* name
, uint32_t cnt
,
1568 uint32_t arrayLength
)
1570 if (IsContextLost())
1573 if (arrayLength
< cnt
) {
1574 ErrorInvalidOperation("%s: Array must be >= %d elements.", name
, cnt
);
1582 IsUniformSetterTypeValid(GLenum setterType
, GLenum uniformType
)
1584 switch (uniformType
) {
1586 case LOCAL_GL_BOOL_VEC2
:
1587 case LOCAL_GL_BOOL_VEC3
:
1588 case LOCAL_GL_BOOL_VEC4
:
1589 return true; // GLfloat(0.0) sets a bool to false.
1592 case LOCAL_GL_INT_SAMPLER_2D
:
1593 case LOCAL_GL_INT_SAMPLER_2D_ARRAY
:
1594 case LOCAL_GL_INT_SAMPLER_3D
:
1595 case LOCAL_GL_INT_SAMPLER_CUBE
:
1596 case LOCAL_GL_INT_VEC2
:
1597 case LOCAL_GL_INT_VEC3
:
1598 case LOCAL_GL_INT_VEC4
:
1599 case LOCAL_GL_SAMPLER_2D
:
1600 case LOCAL_GL_SAMPLER_2D_ARRAY
:
1601 case LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW
:
1602 case LOCAL_GL_SAMPLER_2D_SHADOW
:
1603 case LOCAL_GL_SAMPLER_CUBE
:
1604 case LOCAL_GL_SAMPLER_CUBE_SHADOW
:
1605 case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D
:
1606 case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY
:
1607 case LOCAL_GL_UNSIGNED_INT_SAMPLER_3D
:
1608 case LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE
:
1609 return setterType
== LOCAL_GL_INT
;
1611 case LOCAL_GL_FLOAT
:
1612 case LOCAL_GL_FLOAT_MAT2
:
1613 case LOCAL_GL_FLOAT_MAT2x3
:
1614 case LOCAL_GL_FLOAT_MAT2x4
:
1615 case LOCAL_GL_FLOAT_MAT3
:
1616 case LOCAL_GL_FLOAT_MAT3x2
:
1617 case LOCAL_GL_FLOAT_MAT3x4
:
1618 case LOCAL_GL_FLOAT_MAT4
:
1619 case LOCAL_GL_FLOAT_MAT4x2
:
1620 case LOCAL_GL_FLOAT_MAT4x3
:
1621 case LOCAL_GL_FLOAT_VEC2
:
1622 case LOCAL_GL_FLOAT_VEC3
:
1623 case LOCAL_GL_FLOAT_VEC4
:
1624 return setterType
== LOCAL_GL_FLOAT
;
1627 MOZ_ASSERT(false); // should never get here
1633 CheckUniformSizeAndType(WebGLContext
& webgl
, WebGLUniformLocation
* loc
,
1634 uint8_t setterElemSize
, GLenum setterType
,
1637 if (setterElemSize
!= loc
->ElementSize()) {
1638 webgl
.ErrorInvalidOperation("%s: Bad uniform size: %i", info
,
1639 loc
->ElementSize());
1643 if (!IsUniformSetterTypeValid(setterType
, loc
->Info().type
)) {
1644 webgl
.ErrorInvalidOperation("%s: Bad uniform type: %i", info
,
1653 CheckUniformArrayLength(WebGLContext
& webgl
, WebGLUniformLocation
* loc
,
1654 uint8_t setterElemSize
, size_t setterArraySize
,
1657 if (setterArraySize
== 0 ||
1658 setterArraySize
% setterElemSize
)
1660 webgl
.ErrorInvalidValue("%s: expected an array of length a multiple of"
1661 " %d, got an array of length %d.", info
,
1662 setterElemSize
, setterArraySize
);
1666 if (!loc
->Info().isArray
&&
1667 setterArraySize
!= setterElemSize
)
1669 webgl
.ErrorInvalidOperation("%s: expected an array of length exactly %d"
1670 " (since this uniform is not an array"
1671 " uniform), got an array of length %d.",
1672 info
, setterElemSize
, setterArraySize
);
1680 WebGLContext::ValidateUniformSetter(WebGLUniformLocation
* loc
,
1681 uint8_t setterElemSize
, GLenum setterType
,
1682 const char* info
, GLuint
* out_rawLoc
)
1684 if (IsContextLost())
1687 if (!ValidateUniformLocation(info
, loc
))
1690 if (!CheckUniformSizeAndType(*this, loc
, setterElemSize
, setterType
, info
))
1693 *out_rawLoc
= loc
->Location();
1698 WebGLContext::ValidateUniformArraySetter(WebGLUniformLocation
* loc
,
1699 uint8_t setterElemSize
,
1701 size_t setterArraySize
,
1703 GLuint
* const out_rawLoc
,
1704 GLsizei
* const out_numElementsToUpload
)
1706 if (IsContextLost())
1709 if (!ValidateUniformLocation(info
, loc
))
1712 if (!CheckUniformSizeAndType(*this, loc
, setterElemSize
, setterType
, info
))
1715 if (!CheckUniformArrayLength(*this, loc
, setterElemSize
, setterArraySize
,
1721 *out_rawLoc
= loc
->Location();
1722 *out_numElementsToUpload
= std::min((size_t)loc
->Info().arraySize
,
1723 setterArraySize
/ setterElemSize
);
1728 WebGLContext::ValidateUniformMatrixArraySetter(WebGLUniformLocation
* loc
,
1731 size_t setterArraySize
,
1732 bool setterTranspose
,
1734 GLuint
* const out_rawLoc
,
1735 GLsizei
* const out_numElementsToUpload
)
1737 uint8_t setterElemSize
= setterDims
* setterDims
;
1739 if (IsContextLost())
1742 if (!ValidateUniformLocation(info
, loc
))
1745 if (!CheckUniformSizeAndType(*this, loc
, setterElemSize
, setterType
, info
))
1748 if (!CheckUniformArrayLength(*this, loc
, setterElemSize
, setterArraySize
,
1754 if (setterTranspose
) {
1755 ErrorInvalidValue("%s: `transpose` must be false.", info
);
1759 *out_rawLoc
= loc
->Location();
1760 *out_numElementsToUpload
= std::min((size_t)loc
->Info().arraySize
,
1761 setterArraySize
/ setterElemSize
);
1766 WebGLContext::ValidateAttribIndex(GLuint index
, const char* info
)
1768 bool valid
= (index
< MaxVertexAttribs());
1771 if (index
== GLuint(-1)) {
1772 ErrorInvalidValue("%s: -1 is not a valid `index`. This value"
1773 " probably comes from a getAttribLocation()"
1774 " call, where this return value -1 means"
1775 " that the passed name didn't correspond to"
1776 " an active attribute in the specified"
1779 ErrorInvalidValue("%s: `index` must be less than"
1780 " MAX_VERTEX_ATTRIBS.", info
);
1788 WebGLContext::ValidateAttribPointer(bool integerMode
, GLuint index
, GLint size
, GLenum type
,
1789 WebGLboolean normalized
, GLsizei stride
,
1790 WebGLintptr byteOffset
, const char* info
)
1792 WebGLBuffer
* buffer
= mBoundArrayBuffer
;
1794 ErrorInvalidOperation("%s: must have valid GL_ARRAY_BUFFER binding", info
);
1798 GLsizei requiredAlignment
= 0;
1799 if (!ValidateAttribPointerType(integerMode
, type
, &requiredAlignment
, info
))
1802 // requiredAlignment should always be a power of two
1803 MOZ_ASSERT(IsPOTAssumingNonnegative(requiredAlignment
));
1804 GLsizei requiredAlignmentMask
= requiredAlignment
- 1;
1806 if (size
< 1 || size
> 4) {
1807 ErrorInvalidValue("%s: invalid element size", info
);
1811 // see WebGL spec section 6.6 "Vertex Attribute Data Stride"
1812 if (stride
< 0 || stride
> 255) {
1813 ErrorInvalidValue("%s: negative or too large stride", info
);
1817 if (byteOffset
< 0) {
1818 ErrorInvalidValue("%s: negative offset", info
);
1822 if (stride
& requiredAlignmentMask
) {
1823 ErrorInvalidOperation("%s: stride doesn't satisfy the alignment "
1824 "requirement of given type", info
);
1828 if (byteOffset
& requiredAlignmentMask
) {
1829 ErrorInvalidOperation("%s: byteOffset doesn't satisfy the alignment "
1830 "requirement of given type", info
);
1838 WebGLContext::ValidateStencilParamsForDrawCall()
1840 const char msg
[] = "%s set different front and back stencil %s. Drawing in"
1841 " this configuration is not allowed.";
1843 if (mStencilRefFront
!= mStencilRefBack
) {
1844 ErrorInvalidOperation(msg
, "stencilFuncSeparate", "reference values");
1848 if (mStencilValueMaskFront
!= mStencilValueMaskBack
) {
1849 ErrorInvalidOperation(msg
, "stencilFuncSeparate", "value masks");
1853 if (mStencilWriteMaskFront
!= mStencilWriteMaskBack
) {
1854 ErrorInvalidOperation(msg
, "stencilMaskSeparate", "write masks");
1861 static inline int32_t
1866 while (pot
< 0x40000000) {
1875 WebGLContext::InitAndValidateGL()
1880 GLenum error
= gl
->fGetError();
1881 if (error
!= LOCAL_GL_NO_ERROR
) {
1882 GenerateWarning("GL error 0x%x occurred during OpenGL context"
1883 " initialization, before WebGL initialization!", error
);
1887 mMinCapability
= Preferences::GetBool("webgl.min_capability_mode", false);
1888 mDisableExtensions
= Preferences::GetBool("webgl.disable-extensions", false);
1889 mLoseContextOnMemoryPressure
= Preferences::GetBool("webgl.lose-context-on-memory-pressure", false);
1890 mCanLoseContextInForeground
= Preferences::GetBool("webgl.can-lose-context-in-foreground", true);
1891 mRestoreWhenVisible
= Preferences::GetBool("webgl.restore-context-when-visible", true);
1893 if (MinCapabilityMode())
1894 mDisableFragHighP
= true;
1896 // These are the default values, see 6.2 State tables in the
1897 // OpenGL ES 2.0.25 spec.
1898 mColorWriteMask
[0] = 1;
1899 mColorWriteMask
[1] = 1;
1900 mColorWriteMask
[2] = 1;
1901 mColorWriteMask
[3] = 1;
1902 mDepthWriteMask
= 1;
1903 mColorClearValue
[0] = 0.f
;
1904 mColorClearValue
[1] = 0.f
;
1905 mColorClearValue
[2] = 0.f
;
1906 mColorClearValue
[3] = 0.f
;
1907 mDepthClearValue
= 1.f
;
1908 mStencilClearValue
= 0;
1909 mStencilRefFront
= 0;
1910 mStencilRefBack
= 0;
1913 // Technically, we should be setting mStencil[...] values to
1914 // `allOnes`, but either ANGLE breaks or the SGX540s on Try break.
1915 GLuint stencilBits = 0;
1916 gl->GetUIntegerv(LOCAL_GL_STENCIL_BITS, &stencilBits);
1917 GLuint allOnes = ~(UINT32_MAX << stencilBits);
1918 mStencilValueMaskFront = allOnes;
1919 mStencilValueMaskBack = allOnes;
1920 mStencilWriteMaskFront = allOnes;
1921 mStencilWriteMaskBack = allOnes;
1924 gl
->GetUIntegerv(LOCAL_GL_STENCIL_VALUE_MASK
, &mStencilValueMaskFront
);
1925 gl
->GetUIntegerv(LOCAL_GL_STENCIL_BACK_VALUE_MASK
, &mStencilValueMaskBack
);
1926 gl
->GetUIntegerv(LOCAL_GL_STENCIL_WRITEMASK
, &mStencilWriteMaskFront
);
1927 gl
->GetUIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK
, &mStencilWriteMaskBack
);
1929 AssertUintParamCorrect(gl
, LOCAL_GL_STENCIL_VALUE_MASK
, mStencilValueMaskFront
);
1930 AssertUintParamCorrect(gl
, LOCAL_GL_STENCIL_BACK_VALUE_MASK
, mStencilValueMaskBack
);
1931 AssertUintParamCorrect(gl
, LOCAL_GL_STENCIL_WRITEMASK
, mStencilWriteMaskFront
);
1932 AssertUintParamCorrect(gl
, LOCAL_GL_STENCIL_BACK_WRITEMASK
, mStencilWriteMaskBack
);
1934 mDitherEnabled
= true;
1935 mRasterizerDiscardEnabled
= false;
1936 mScissorTestEnabled
= false;
1940 mEmitContextLostErrorOnce
= true;
1941 mWebGLError
= LOCAL_GL_NO_ERROR
;
1942 mUnderlyingGLError
= LOCAL_GL_NO_ERROR
;
1944 mBound2DTextures
.Clear();
1945 mBoundCubeMapTextures
.Clear();
1946 mBound3DTextures
.Clear();
1948 mBoundArrayBuffer
= nullptr;
1949 mBoundTransformFeedbackBuffer
= nullptr;
1950 mCurrentProgram
= nullptr;
1952 mBoundFramebuffer
= nullptr;
1953 mBoundRenderbuffer
= nullptr;
1955 MakeContextCurrent();
1957 // on desktop OpenGL, we always keep vertex attrib 0 array enabled
1959 gl
->fEnableVertexAttribArray(0);
1961 if (MinCapabilityMode())
1962 mGLMaxVertexAttribs
= MINVALUE_GL_MAX_VERTEX_ATTRIBS
;
1964 gl
->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS
, &mGLMaxVertexAttribs
);
1966 if (mGLMaxVertexAttribs
< 8) {
1967 GenerateWarning("GL_MAX_VERTEX_ATTRIBS: %d is < 8!",
1968 mGLMaxVertexAttribs
);
1972 // Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
1973 // even though the hardware supports much more. The
1974 // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
1975 if (MinCapabilityMode())
1976 mGLMaxTextureUnits
= MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
;
1978 gl
->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
, &mGLMaxTextureUnits
);
1980 if (mGLMaxTextureUnits
< 8) {
1981 GenerateWarning("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d is < 8!",
1982 mGLMaxTextureUnits
);
1986 mBound2DTextures
.SetLength(mGLMaxTextureUnits
);
1987 mBoundCubeMapTextures
.SetLength(mGLMaxTextureUnits
);
1988 mBound3DTextures
.SetLength(mGLMaxTextureUnits
);
1990 if (MinCapabilityMode()) {
1991 mGLMaxTextureSize
= MINVALUE_GL_MAX_TEXTURE_SIZE
;
1992 mGLMaxCubeMapTextureSize
= MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE
;
1993 mGLMaxRenderbufferSize
= MINVALUE_GL_MAX_RENDERBUFFER_SIZE
;
1994 mGLMaxTextureImageUnits
= MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS
;
1995 mGLMaxVertexTextureImageUnits
= MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
;
1997 gl
->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE
, &mGLMaxTextureSize
);
1998 gl
->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE
, &mGLMaxCubeMapTextureSize
);
1999 gl
->fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE
, &mGLMaxRenderbufferSize
);
2000 gl
->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS
, &mGLMaxTextureImageUnits
);
2001 gl
->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
, &mGLMaxVertexTextureImageUnits
);
2004 // Calculate log2 of mGLMaxTextureSize and mGLMaxCubeMapTextureSize
2005 mGLMaxTextureSizeLog2
= 0;
2006 int32_t tempSize
= mGLMaxTextureSize
;
2007 while (tempSize
>>= 1) {
2008 ++mGLMaxTextureSizeLog2
;
2011 mGLMaxCubeMapTextureSizeLog2
= 0;
2012 tempSize
= mGLMaxCubeMapTextureSize
;
2013 while (tempSize
>>= 1) {
2014 ++mGLMaxCubeMapTextureSizeLog2
;
2017 mGLMaxTextureSize
= FloorPOT(mGLMaxTextureSize
);
2018 mGLMaxRenderbufferSize
= FloorPOT(mGLMaxRenderbufferSize
);
2020 if (MinCapabilityMode()) {
2021 mGLMaxFragmentUniformVectors
= MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS
;
2022 mGLMaxVertexUniformVectors
= MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS
;
2023 mGLMaxVaryingVectors
= MINVALUE_GL_MAX_VARYING_VECTORS
;
2025 if (gl
->IsSupported(gl::GLFeature::ES2_compatibility
)) {
2026 gl
->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS
, &mGLMaxFragmentUniformVectors
);
2027 gl
->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS
, &mGLMaxVertexUniformVectors
);
2028 gl
->fGetIntegerv(LOCAL_GL_MAX_VARYING_VECTORS
, &mGLMaxVaryingVectors
);
2030 gl
->fGetIntegerv(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
, &mGLMaxFragmentUniformVectors
);
2031 mGLMaxFragmentUniformVectors
/= 4;
2032 gl
->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS
, &mGLMaxVertexUniformVectors
);
2033 mGLMaxVertexUniformVectors
/= 4;
2035 /* We are now going to try to read GL_MAX_VERTEX_OUTPUT_COMPONENTS
2036 * and GL_MAX_FRAGMENT_INPUT_COMPONENTS, however these constants
2037 * only entered the OpenGL standard at OpenGL 3.2. So we will try
2038 * reading, and check OpenGL error for INVALID_ENUM.
2040 * On the public_webgl list, "problematic GetParameter pnames"
2041 * thread, the following formula was given:
2042 * maxVaryingVectors = min(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
2043 * GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4
2045 GLint maxVertexOutputComponents
= 0;
2046 GLint maxFragmentInputComponents
= 0;
2048 const bool ok
= (gl
->GetPotentialInteger(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS
,
2049 &maxVertexOutputComponents
) &&
2050 gl
->GetPotentialInteger(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS
,
2051 &maxFragmentInputComponents
));
2054 mGLMaxVaryingVectors
= std::min(maxVertexOutputComponents
,
2055 maxFragmentInputComponents
) / 4;
2057 mGLMaxVaryingVectors
= 16;
2058 // 16 = 64/4, and 64 is the min value for
2059 // maxVertexOutputComponents in the OpenGL 3.2 spec.
2064 // Always 1 for GLES2
2065 mMaxFramebufferColorAttachments
= 1;
2067 if (!gl
->IsGLES()) {
2068 // gl_PointSize is always available in ES2 GLSL, but has to be
2069 // specifically enabled on desktop GLSL.
2070 gl
->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE
);
2072 /* gl_PointCoord is always available in ES2 GLSL and in newer desktop
2073 * GLSL versions, but apparently not in OpenGL 2 and apparently not (due
2074 * to a driver bug) on certain NVIDIA setups. See:
2075 * http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=261472
2077 * Note that this used to cause crashes on old ATI drivers... Hopefully
2078 * not a significant anymore. See bug 602183.
2080 gl
->fEnable(LOCAL_GL_POINT_SPRITE
);
2084 if (gl
->WorkAroundDriverBugs() &&
2085 gl
->Vendor() == gl::GLVendor::ATI
&&
2086 !nsCocoaFeatures::IsAtLeastVersion(10,9))
2088 // The Mac ATI driver, in all known OSX version up to and including
2089 // 10.8, renders points sprites upside-down. (Apple bug 11778921)
2090 gl
->fPointParameterf(LOCAL_GL_POINT_SPRITE_COORD_ORIGIN
,
2091 LOCAL_GL_LOWER_LEFT
);
2095 // Check the shader validator pref
2096 NS_ENSURE_TRUE(Preferences::GetRootBranch(), false);
2098 mShaderValidation
= Preferences::GetBool("webgl.shader_validator",
2101 // initialize shader translator
2102 if (mShaderValidation
) {
2103 if (!ShInitialize()) {
2104 GenerateWarning("GLSL translator initialization failed!");
2109 // Mesa can only be detected with the GL_VERSION string, of the form
2110 // "2.1 Mesa 7.11.0"
2111 const char* versionStr
= (const char*)(gl
->fGetString(LOCAL_GL_VERSION
));
2112 mIsMesa
= strstr(versionStr
, "Mesa");
2114 // Notice that the point of calling fGetError here is not only to check for
2115 // errors, but also to reset the error flags so that a subsequent WebGL
2116 // getError call will give the correct result.
2117 error
= gl
->fGetError();
2118 if (error
!= LOCAL_GL_NO_ERROR
) {
2119 GenerateWarning("GL error 0x%x occurred during WebGL context"
2120 " initialization!", error
);
2127 // Todo: Bug 898404: Only allow WebGL2 on GL>=3.0 on desktop GL.
2131 // Default value for all disabled vertex attributes is [0, 0, 0, 1]
2132 for (int32_t index
= 0; index
< mGLMaxVertexAttribs
; ++index
) {
2133 VertexAttrib4f(index
, 0, 0, 0, 1);
2136 mDefaultVertexArray
= WebGLVertexArray::Create(this);
2137 mDefaultVertexArray
->mAttribs
.SetLength(mGLMaxVertexAttribs
);
2138 mBoundVertexArray
= mDefaultVertexArray
;
2140 if (mLoseContextOnMemoryPressure
)
2141 mContextObserver
->RegisterMemoryPressureEvent();
2146 } // namespace mozilla