1 /* -*- Mode: C++; tab-width: 4; 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/. */
10 #include <type_traits>
11 #include <unordered_map>
15 #include "ImageContainer.h"
16 #include "mozilla/Casting.h"
17 #include "mozilla/CheckedInt.h"
18 #include "mozilla/MathAlgorithms.h"
19 #include "mozilla/Range.h"
20 #include "mozilla/RefCounted.h"
21 #include "mozilla/ResultVariant.h"
22 #include "mozilla/gfx/2D.h"
23 #include "mozilla/gfx/BuildConstants.h"
24 #include "mozilla/gfx/Point.h"
25 #include "mozilla/gfx/Rect.h"
26 #include "mozilla/ipc/Shmem.h"
27 #include "mozilla/layers/LayersSurfaces.h"
32 #include "mozilla/dom/WebGLRenderingContextBinding.h"
33 #include "mozilla/ipc/SharedMemoryBasic.h"
35 // Manual reflection of WebIDL typedefs that are different from their
36 // OpenGL counterparts.
37 typedef int64_t WebGLsizeiptr
;
38 typedef int64_t WebGLintptr
;
39 typedef bool WebGLboolean
;
45 class GLContext
; // This is going to be needed a lot.
49 // Prevent implicit conversions into calloc and malloc. (mozilla namespace
52 template <typename DestT
>
53 class ForbidNarrowing final
{
57 template <typename SrcT
>
58 MOZ_IMPLICIT
ForbidNarrowing(SrcT val
) : mVal(val
) {
60 std::numeric_limits
<SrcT
>::min() >= std::numeric_limits
<DestT
>::min(),
61 "SrcT must be narrower than DestT.");
63 std::numeric_limits
<SrcT
>::max() <= std::numeric_limits
<DestT
>::max(),
64 "SrcT must be narrower than DestT.");
67 explicit operator DestT() const { return mVal
; }
70 inline void* malloc(const ForbidNarrowing
<size_t> s
) {
71 return ::malloc(size_t(s
));
74 inline void* calloc(const ForbidNarrowing
<size_t> n
,
75 const ForbidNarrowing
<size_t> size
) {
76 return ::calloc(size_t(n
), size_t(size
));
83 template <typename From
>
84 class AutoAssertCastT final
{
88 explicit AutoAssertCastT(const From val
) : mVal(val
) {}
90 template <typename To
>
92 return AssertedCast
<To
>(mVal
);
98 template <typename From
>
99 inline auto AutoAssertCast(const From val
) {
100 return detail::AutoAssertCastT
<From
>(val
);
104 template <typename T
>
105 struct QueueParamTraits
;
106 class TexUnpackBytes
;
107 class TexUnpackImage
;
108 class TexUnpackSurface
;
111 class ClientWebGLContext
;
112 struct WebGLTexPboOffset
;
115 class WebGLFramebuffer
;
118 class WebGLRenderbuffer
;
123 class WebGLTransformFeedback
;
124 class WebGLVertexArray
;
128 class VRefCounted
: public RefCounted
<VRefCounted
> {
130 virtual ~VRefCounted() = default;
132 #ifdef MOZ_REFCOUNTED_LEAK_CHECKING
133 virtual const char* typeName() const = 0;
134 virtual size_t typeSize() const = 0;
141 * Implementing WebGL (or OpenGL ES 2.0) on top of desktop OpenGL requires
142 * emulating the vertex attrib 0 array when it's not enabled. Indeed,
143 * OpenGL ES 2.0 allows drawing without vertex attrib 0 array enabled, but
144 * desktop OpenGL does not allow that.
146 enum class WebGLVertexAttrib0Status
: uint8_t {
147 Default
, // default status - no emulation needed
148 EmulatedUninitializedArray
, // need an artificial attrib 0 array, but
149 // contents may be left uninitialized
150 EmulatedInitializedArray
// need an artificial attrib 0 array, and contents
151 // must be initialized
155 * The formats that may participate, either as source or destination formats,
156 * in WebGL texture conversions. This includes:
157 * - all the formats accepted by WebGL.texImage2D, e.g. RGBA4444
158 * - additional formats provided by extensions, e.g. RGB32F
159 * - additional source formats, depending on browser details, used when
160 * uploading textures from DOM elements. See gfxImageSurface::Format().
162 enum class WebGLTexelFormat
: uint8_t {
163 // returned by SurfaceFromElementResultToImageSurface to indicate absence of
166 // common value for formats for which format conversions are not supported
167 FormatNotSupportingAnyConversion
,
168 // dummy pseudo-format meaning "use the other format".
169 // For example, if SrcFormat=Auto and DstFormat=RGB8, then the source
170 // is implicitly treated as being RGB8 itself.
174 A16F
, // OES_texture_half_float
175 A32F
, // OES_texture_float
177 R16F
, // OES_texture_half_float
178 R32F
, // OES_texture_float
181 RA16F
, // OES_texture_half_float
182 RA32F
, // OES_texture_float
190 RGB16F
, // OES_texture_half_float
191 RGB32F
, // OES_texture_float
196 RGBA16F
, // OES_texture_half_float
197 RGBA32F
, // OES_texture_float
198 // DOM element source only formats.
204 enum class WebGLTexImageFunc
: uint8_t {
213 enum class WebGLTexDimensions
: uint8_t { Tex2D
, Tex3D
};
215 // Please keep extensions in alphabetic order.
216 enum class WebGLExtensionID
: uint8_t {
217 ANGLE_instanced_arrays
,
219 EXT_color_buffer_float
,
220 EXT_color_buffer_half_float
,
221 EXT_disjoint_timer_query
,
224 EXT_shader_texture_lod
,
226 EXT_texture_compression_bptc
,
227 EXT_texture_compression_rgtc
,
228 EXT_texture_filter_anisotropic
,
231 OES_element_index_uint
,
232 OES_fbo_render_mipmap
,
233 OES_standard_derivatives
,
235 OES_texture_float_linear
,
236 OES_texture_half_float
,
237 OES_texture_half_float_linear
,
238 OES_vertex_array_object
,
240 WEBGL_color_buffer_float
,
241 WEBGL_compressed_texture_astc
,
242 WEBGL_compressed_texture_etc
,
243 WEBGL_compressed_texture_etc1
,
244 WEBGL_compressed_texture_pvrtc
,
245 WEBGL_compressed_texture_s3tc
,
246 WEBGL_compressed_texture_s3tc_srgb
,
247 WEBGL_debug_renderer_info
,
251 WEBGL_explicit_present
,
257 // Like UniquePtr<>, but for void* and malloc/calloc/free.
261 static inline UniqueBuffer
Alloc(const size_t byteSize
) {
262 return {malloc(byteSize
)};
265 UniqueBuffer() : mBuffer(nullptr) {}
267 MOZ_IMPLICIT
UniqueBuffer(void* buffer
) : mBuffer(buffer
) {}
269 ~UniqueBuffer() { free(mBuffer
); }
271 UniqueBuffer(UniqueBuffer
&& other
) {
272 this->mBuffer
= other
.mBuffer
;
273 other
.mBuffer
= nullptr;
276 UniqueBuffer
& operator=(UniqueBuffer
&& other
) {
278 this->mBuffer
= other
.mBuffer
;
279 other
.mBuffer
= nullptr;
283 UniqueBuffer
& operator=(void* newBuffer
) {
285 this->mBuffer
= newBuffer
;
289 explicit operator bool() const { return bool(mBuffer
); }
291 void* get() const { return mBuffer
; }
293 explicit UniqueBuffer(const UniqueBuffer
& other
) =
294 delete; // construct using std::move()!
295 UniqueBuffer
& operator=(const UniqueBuffer
& other
) =
296 delete; // assign using std::move()!
300 struct FormatUsageInfo
;
302 static constexpr GLenum kErrorPerfWarning
= 0x10001;
304 struct SampleableInfo final
{
305 const char* incompleteReason
= nullptr;
307 const webgl::FormatUsageInfo
* usage
= nullptr;
308 bool isDepthTexCompare
= false;
310 bool IsComplete() const { return bool(levels
); }
313 enum class AttribBaseType
: uint8_t {
314 Boolean
, // Can convert from anything.
315 Float
, // Also includes NormU?Int
319 webgl::AttribBaseType
ToAttribBaseType(GLenum
);
320 const char* ToString(AttribBaseType
);
322 enum class UniformBaseType
: uint8_t {
327 const char* ToString(UniformBaseType
);
329 typedef uint64_t ObjectId
;
331 enum class BufferKind
: uint8_t {
341 struct FloatOrInt final
// For TexParameter[fi] and friends.
347 explicit FloatOrInt(GLint x
= 0) : isFloat(false), f(x
), i(x
) {}
349 explicit FloatOrInt(GLfloat x
) : isFloat(true), f(x
), i(roundf(x
)) {}
351 FloatOrInt
& operator=(const FloatOrInt
& x
) {
352 memcpy(this, &x
, sizeof(x
));
357 using WebGLTexUnpackVariant
=
358 Variant
<UniquePtr
<webgl::TexUnpackBytes
>,
359 UniquePtr
<webgl::TexUnpackSurface
>,
360 UniquePtr
<webgl::TexUnpackImage
>, WebGLTexPboOffset
>;
362 using MaybeWebGLTexUnpackVariant
= Maybe
<WebGLTexUnpackVariant
>;
364 struct WebGLContextOptions
{
367 bool stencil
= false;
368 bool premultipliedAlpha
= true;
369 bool antialias
= true;
370 bool preserveDrawingBuffer
= false;
371 bool failIfMajorPerformanceCaveat
= false;
372 bool xrCompatible
= false;
373 dom::WebGLPowerPreference powerPreference
=
374 dom::WebGLPowerPreference::Default
;
375 bool shouldResistFingerprinting
= true;
376 bool enableDebugRendererInfo
= false;
378 WebGLContextOptions();
379 WebGLContextOptions(const WebGLContextOptions
&) = default;
381 bool operator==(const WebGLContextOptions
&) const;
382 bool operator!=(const WebGLContextOptions
& rhs
) const {
383 return !(*this == rhs
);
389 template <typename _T
>
396 template <typename U
, typename V
>
397 static Maybe
<avec2
> From(const U _x
, const V _y
) {
398 const auto x
= CheckedInt
<T
>(_x
);
399 const auto y
= CheckedInt
<T
>(_y
);
400 if (!x
.isValid() || !y
.isValid()) return {};
401 return Some(avec2(x
.value(), y
.value()));
404 template <typename U
>
405 static auto From(const U
& val
) {
406 return From(val
.x
, val
.y
);
408 template <typename U
>
409 static auto FromSize(const U
& val
) {
410 return From(val
.width
, val
.height
);
414 avec2(const T _x
, const T _y
) : x(_x
), y(_y
) {}
416 bool operator==(const avec2
& rhs
) const { return x
== rhs
.x
&& y
== rhs
.y
; }
417 bool operator!=(const avec2
& rhs
) const { return !(*this == rhs
); }
420 avec2 operator OP(const avec2& rhs) const { \
421 return {x OP rhs.x, y OP rhs.y}; \
423 avec2 operator OP(const T rhs) const { return {x OP rhs, y OP rhs}; }
432 avec2
Clamp(const avec2
& min
, const avec2
& max
) const {
433 return {mozilla::Clamp(x
, min
.x
, max
.x
), mozilla::Clamp(y
, min
.y
, max
.y
)};
436 // mozilla::Clamp doesn't work on floats, so be clear that this is a min+max
438 avec2
ClampMinMax(const avec2
& min
, const avec2
& max
) const {
439 const auto ClampScalar
= [](const T v
, const T min
, const T max
) {
440 return std::max(min
, std::min(v
, max
));
442 return {ClampScalar(x
, min
.x
, max
.x
), ClampScalar(y
, min
.y
, max
.y
)};
445 template <typename U
>
446 U
StaticCast() const {
447 return {static_cast<typename
U::T
>(x
), static_cast<typename
U::T
>(y
)};
451 template <typename T
>
452 avec2
<T
> MinExtents(const avec2
<T
>& a
, const avec2
<T
>& b
) {
453 return {std::min(a
.x
, b
.x
), std::min(a
.y
, b
.y
)};
456 template <typename T
>
457 avec2
<T
> MaxExtents(const avec2
<T
>& a
, const avec2
<T
>& b
) {
458 return {std::max(a
.x
, b
.x
), std::max(a
.y
, b
.y
)};
463 template <typename _T
>
471 template <typename U
, typename V
>
472 static Maybe
<avec3
> From(const U _x
, const V _y
, const V _z
) {
473 const auto x
= CheckedInt
<T
>(_x
);
474 const auto y
= CheckedInt
<T
>(_y
);
475 const auto z
= CheckedInt
<T
>(_z
);
476 if (!x
.isValid() || !y
.isValid() || !z
.isValid()) return {};
477 return Some(avec3(x
.value(), y
.value(), z
.value()));
480 template <typename U
>
481 static auto From(const U
& val
) {
482 return From(val
.x
, val
.y
, val
.z
);
486 avec3(const T _x
, const T _y
, const T _z
) : x(_x
), y(_y
), z(_z
) {}
488 bool operator==(const avec3
& rhs
) const {
489 return x
== rhs
.x
&& y
== rhs
.y
&& z
== rhs
.z
;
491 bool operator!=(const avec3
& rhs
) const { return !(*this == rhs
); }
494 typedef avec2
<int32_t> ivec2
;
495 typedef avec3
<int32_t> ivec3
;
496 typedef avec2
<uint32_t> uvec2
;
497 typedef avec3
<uint32_t> uvec3
;
499 inline ivec2
AsVec(const gfx::IntSize
& s
) { return {s
.width
, s
.height
}; }
505 struct PackingInfo final
{
509 bool operator<(const PackingInfo
& x
) const {
510 if (format
!= x
.format
) return format
< x
.format
;
512 return type
< x
.type
;
515 bool operator==(const PackingInfo
& x
) const {
516 return (format
== x
.format
&& type
== x
.type
);
520 struct DriverUnpackInfo final
{
521 GLenum internalFormat
= 0;
522 GLenum unpackFormat
= 0;
523 GLenum unpackType
= 0;
525 PackingInfo
ToPacking() const { return {unpackFormat
, unpackType
}; }
528 struct PixelPackState final
{
529 uint32_t alignment
= 4;
530 uint32_t rowLength
= 0;
531 uint32_t skipRows
= 0;
532 uint32_t skipPixels
= 0;
535 struct ReadPixelsDesc final
{
538 PackingInfo pi
= {LOCAL_GL_RGBA
, LOCAL_GL_UNSIGNED_BYTE
};
539 PixelPackState packState
;
544 template <typename E
>
550 struct BitRef final
{
554 explicit operator bool() const { return bits
.mBits
& mask
; }
556 auto& operator=(const bool val
) {
566 uint64_t Mask(const E i
) const {
567 return uint64_t{1} << static_cast<uint64_t>(i
);
571 BitRef
operator[](const E i
) { return {*this, Mask(i
)}; }
572 bool operator[](const E i
) const { return mBits
& Mask(i
); }
575 class ExtensionBits
: public EnumMask
<WebGLExtensionID
> {};
579 enum class ContextLossReason
: uint8_t {
585 inline bool ReadContextLossReason(const uint8_t val
,
586 ContextLossReason
* const out
) {
587 if (val
> static_cast<uint8_t>(ContextLossReason::Guilty
)) {
590 *out
= static_cast<ContextLossReason
>(val
);
596 struct InitContextDesc final
{
597 bool isWebgl2
= false;
598 bool resistFingerprinting
= false;
600 WebGLContextOptions options
;
601 uint32_t principalKey
= 0;
604 struct Limits final
{
605 ExtensionBits supportedExtensions
;
608 uint32_t maxTexUnits
= 0;
609 uint32_t maxTex2dSize
= 0;
610 uint32_t maxTexCubeSize
= 0;
611 uint32_t maxVertexAttribs
= 0;
612 std::array
<uint32_t, 2> maxViewportDims
= {};
613 std::array
<float, 2> pointSizeRange
= {{1, 1}};
614 std::array
<float, 2> lineWidthRange
= {{1, 1}};
617 uint32_t maxTexArrayLayers
= 0;
618 uint32_t maxTex3dSize
= 0;
619 uint32_t maxTransformFeedbackSeparateAttribs
= 0;
620 uint32_t maxUniformBufferBindings
= 0;
621 uint32_t uniformBufferOffsetAlignment
= 0;
624 bool astcHdr
= false;
625 uint32_t maxColorDrawBuffers
= 1;
626 uint64_t queryCounterBitsTimeElapsed
= 0;
627 uint64_t queryCounterBitsTimestamp
= 0;
628 uint32_t maxMultiviewLayers
= 0;
631 struct InitContextResult final
{
633 WebGLContextOptions options
;
634 webgl::Limits limits
;
635 EnumMask
<layers::SurfaceDescriptor::Type
> uploadableSdTypes
;
640 struct ErrorInfo final
{
645 struct ShaderPrecisionFormat final
{
653 enum class LossStatus
{
663 struct CompileResult final
{
666 nsCString translatedSource
;
667 bool success
= false;
672 struct OpaqueFramebufferOptions final
{
673 bool depthStencil
= true;
674 bool antialias
= true;
682 GLenum elemType
= 0; // `type`
683 uint32_t elemCount
= 0; // `size`
687 struct ActiveAttribInfo final
: public ActiveInfo
{
688 int32_t location
= -1;
689 AttribBaseType baseType
= AttribBaseType::Float
;
692 struct ActiveUniformInfo final
: public ActiveInfo
{
693 std::unordered_map
<uint32_t, uint32_t>
694 locByIndex
; // Uniform array locations are sparse.
695 int32_t block_index
= -1;
696 int32_t block_offset
= -1; // In block, offset.
697 int32_t block_arrayStride
= -1;
698 int32_t block_matrixStride
= -1;
699 bool block_isRowMajor
= false;
702 struct ActiveUniformBlockInfo final
{
704 // BLOCK_BINDING is dynamic state
705 uint32_t dataSize
= 0;
706 std::vector
<uint32_t> activeUniformIndices
;
707 bool referencedByVertexShader
= false;
708 bool referencedByFragmentShader
= false;
711 struct LinkActiveInfo final
{
712 std::vector
<ActiveAttribInfo
> activeAttribs
;
713 std::vector
<ActiveUniformInfo
> activeUniforms
;
714 std::vector
<ActiveUniformBlockInfo
> activeUniformBlocks
;
715 std::vector
<ActiveInfo
> activeTfVaryings
;
718 struct LinkResult final
{
721 bool success
= false;
722 LinkActiveInfo active
;
723 GLenum tfBufferMode
= 0;
728 /// 4x32-bit primitives, with a type tag.
729 struct TypedQuad final
{
730 alignas(alignof(float)) uint8_t data
[4 * sizeof(float)] = {};
731 webgl::AttribBaseType type
= webgl::AttribBaseType::Float
;
734 /// [1-16]x32-bit primitives, with a type tag.
735 struct GetUniformData final
{
736 alignas(alignof(float)) uint8_t data
[4 * 4 * sizeof(float)] = {};
740 struct FrontBufferSnapshotIpc final
{
742 mozilla::ipc::Shmem shmem
= {};
745 struct ReadPixelsResult
{
746 gfx::IntRect subrect
= {};
747 size_t byteStride
= 0;
750 struct ReadPixelsResultIpc final
: public ReadPixelsResult
{
751 mozilla::ipc::Shmem shmem
= {};
754 struct VertAttribPointerDesc final
{
755 bool intFunc
= false;
756 uint8_t channels
= 4;
757 bool normalized
= false;
758 uint8_t byteStrideOrZero
= 0;
759 GLenum type
= LOCAL_GL_FLOAT
;
760 uint64_t byteOffset
= 0;
763 struct VertAttribPointerCalculated final
{
764 uint8_t byteSize
= 4 * 4;
765 uint8_t byteStride
= 4 * 4; // at-most 255
766 webgl::AttribBaseType baseType
= webgl::AttribBaseType::Float
;
771 // return value for the InitializeCanvasRenderer message
779 * Represents a block of memory that it may or may not own. The
780 * inner data type must be trivially copyable by memcpy.
782 template <typename T
= uint8_t>
783 class RawBuffer final
{
784 const T
* mBegin
= nullptr;
789 using ElementType
= T
;
792 * If aTakeData is true, RawBuffer will delete[] the memory when destroyed.
794 explicit RawBuffer(const Range
<const T
>& data
, UniqueBuffer
&& owned
= {})
795 : mBegin(data
.begin().get()),
797 mOwned(std::move(owned
)) {}
799 explicit RawBuffer(const size_t len
) : mLen(len
) {}
801 ~RawBuffer() = default;
803 Range
<const T
> Data() const { return {mBegin
, mLen
}; }
804 const auto& begin() const { return mBegin
; }
805 const auto& size() const { return mLen
; }
807 void Shrink(const size_t newLen
) {
808 if (mLen
<= newLen
) return;
812 RawBuffer() = default;
814 RawBuffer(const RawBuffer
&) = delete;
815 RawBuffer
& operator=(const RawBuffer
&) = delete;
817 RawBuffer(RawBuffer
&&) = default;
818 RawBuffer
& operator=(RawBuffer
&&) = default;
823 struct CopyableRange final
: public Range
<const uint8_t> {};
829 #define FOREACH_ID(X) \
830 X(FuncScopeIdError) \
831 X(compressedTexImage2D) \
832 X(compressedTexImage3D) \
833 X(compressedTexSubImage2D) \
834 X(compressedTexSubImage3D) \
835 X(copyTexSubImage2D) \
836 X(copyTexSubImage3D) \
838 X(drawArraysInstanced) \
840 X(drawElementsInstanced) \
841 X(drawRangeElements) \
842 X(renderbufferStorage) \
843 X(renderbufferStorageMultisample) \
859 X(vertexAttribI4iv) \
860 X(vertexAttribI4ui) \
861 X(vertexAttribI4uiv) \
862 X(vertexAttribIPointer) \
863 X(vertexAttribPointer)
867 enum class FuncScopeId
{
873 static constexpr const char* const FUNCSCOPE_NAME_BY_ID
[] = {
881 inline auto GetFuncScopeName(const FuncScopeId id
) {
882 return FUNCSCOPE_NAME_BY_ID
[static_cast<size_t>(id
)];
887 template <typename C
, typename K
>
888 inline auto MaybeFind(C
& container
, const K
& key
)
889 -> decltype(&(container
.find(key
)->second
)) {
890 const auto itr
= container
.find(key
);
891 if (itr
== container
.end()) return nullptr;
892 return &(itr
->second
);
895 template <typename C
, typename K
>
896 inline typename
C::mapped_type
Find(
897 const C
& container
, const K
& key
,
898 const typename
C::mapped_type notFound
= {}) {
899 const auto itr
= container
.find(key
);
900 if (itr
== container
.end()) return notFound
;
906 template <typename T
, typename U
>
907 inline Maybe
<T
> MaybeAs(const U val
) {
908 const auto checked
= CheckedInt
<T
>(val
);
909 if (!checked
.isValid()) return {};
910 return Some(checked
.value());
915 inline GLenum
ImageToTexTarget(const GLenum imageTarget
) {
916 switch (imageTarget
) {
917 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
918 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
919 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
920 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
921 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
922 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
923 return LOCAL_GL_TEXTURE_CUBE_MAP
;
929 inline bool IsTexTarget3D(const GLenum texTarget
) {
931 case LOCAL_GL_TEXTURE_2D_ARRAY
:
932 case LOCAL_GL_TEXTURE_3D
:
948 struct TexImageSource
{
949 const dom::ArrayBufferView
* mView
= nullptr;
950 GLuint mViewElemOffset
= 0;
951 GLuint mViewElemLengthOverride
= 0;
953 const WebGLintptr
* mPboOffset
= nullptr;
955 const dom::ImageBitmap
* mImageBitmap
= nullptr;
956 const dom::ImageData
* mImageData
= nullptr;
958 const dom::Element
* mDomElem
= nullptr;
959 ErrorResult
* mOut_error
= nullptr;
962 struct WebGLPixelStore final
{
963 uint32_t mUnpackImageHeight
= 0;
964 uint32_t mUnpackSkipImages
= 0;
965 uint32_t mUnpackRowLength
= 0;
966 uint32_t mUnpackSkipRows
= 0;
967 uint32_t mUnpackSkipPixels
= 0;
968 uint32_t mUnpackAlignment
= 4;
969 GLenum mColorspaceConversion
=
970 dom::WebGLRenderingContext_Binding::BROWSER_DEFAULT_WEBGL
;
972 bool mPremultiplyAlpha
= false;
973 bool mRequireFastPath
= false;
975 static void AssertDefault(gl::GLContext
& gl
, const bool isWebgl2
) {
976 WebGLPixelStore expected
;
977 MOZ_ASSERT(expected
.AssertCurrent(gl
, isWebgl2
));
981 void Apply(gl::GLContext
&, bool isWebgl2
, const uvec3
& uploadSize
) const;
982 bool AssertCurrent(gl::GLContext
&, bool isWebgl2
) const;
984 WebGLPixelStore
ForUseWith(const GLenum target
, const uvec3
& uploadSize
,
985 const Maybe
<uvec2
>& structuredSrcSize
) const {
988 if (!IsTexTarget3D(target
)) {
989 ret
.mUnpackSkipImages
= 0;
990 ret
.mUnpackImageHeight
= 0;
993 if (structuredSrcSize
) {
994 ret
.mUnpackRowLength
= structuredSrcSize
->x
;
997 if (!ret
.mUnpackRowLength
) {
998 ret
.mUnpackRowLength
= uploadSize
.x
;
1000 if (!ret
.mUnpackImageHeight
) {
1001 ret
.mUnpackImageHeight
= uploadSize
.y
;
1003 if (!IsTexTarget3D(target
)) {
1004 // 2D targets don't enforce skipRows+height<=imageHeight.
1005 ret
.mUnpackImageHeight
+= ret
.mUnpackSkipRows
;
1012 CheckedInt
<size_t> UsedPixelsPerRow(const uvec3
& size
) const {
1013 if (!size
.x
|| !size
.y
|| !size
.z
) return 0;
1014 return CheckedInt
<size_t>(mUnpackSkipPixels
) + size
.x
;
1017 CheckedInt
<size_t> FullRowsNeeded(const uvec3
& size
) const {
1018 if (!size
.x
|| !size
.y
|| !size
.z
) return 0;
1020 // The spec guarantees:
1021 // * SKIP_PIXELS + width <= ROW_LENGTH.
1022 // * SKIP_ROWS + height <= IMAGE_HEIGHT.
1023 MOZ_ASSERT(mUnpackImageHeight
);
1025 CheckedInt
<size_t>(mUnpackSkipImages
) * mUnpackImageHeight
;
1026 skipFullRows
+= mUnpackSkipRows
;
1028 // Full rows in the final image, excluding the tail.
1029 auto usedFullRows
= CheckedInt
<size_t>(size
.z
- 1) * mUnpackImageHeight
;
1030 usedFullRows
+= size
.y
- 1;
1032 return skipFullRows
+ usedFullRows
;
1036 struct TexImageData final
{
1037 WebGLPixelStore unpackState
;
1039 Maybe
<uint64_t> pboOffset
;
1043 const dom::Element
* domElem
= nullptr;
1044 ErrorResult
* out_domElemError
= nullptr;
1049 struct TexUnpackBlobDesc final
{
1050 GLenum imageTarget
= LOCAL_GL_TEXTURE_2D
;
1052 gfxAlphaType srcAlphaType
= gfxAlphaType::NonPremult
;
1054 Maybe
<RawBuffer
<>> cpuData
;
1055 Maybe
<uint64_t> pboOffset
;
1058 RefPtr
<layers::Image
> image
;
1059 Maybe
<layers::SurfaceDescriptor
> sd
;
1060 RefPtr
<gfx::DataSourceSurface
> dataSurf
;
1062 WebGLPixelStore unpacking
;
1064 void Shrink(const webgl::PackingInfo
&);
1067 } // namespace webgl
1069 // ---------------------------------------
1072 template <typename T
, size_t N
>
1073 inline Range
<const T
> MakeRange(T (&arr
)[N
]) {
1077 template <typename T
>
1078 inline Range
<const T
> MakeRange(const dom::Sequence
<T
>& seq
) {
1079 return {seq
.Elements(), seq
.Length()};
1082 template <typename T
>
1083 inline Range
<const T
> MakeRange(const RawBuffer
<T
>& from
) {
1087 // abv = ArrayBufferView
1088 template <typename T
>
1089 inline auto MakeRangeAbv(const T
& abv
)
1090 -> Range
<const typename
T::element_type
> {
1092 return {abv
.Data(), abv
.Length()};
1097 constexpr auto kUniversalAlignment
= alignof(std::max_align_t
);
1099 template <typename T
>
1100 inline size_t AlignmentOffset(const size_t alignment
, const T posOrPtr
) {
1101 MOZ_ASSERT(alignment
);
1102 const auto begin
= reinterpret_cast<uintptr_t>(posOrPtr
);
1103 const auto wholeMultiples
= (begin
+ (alignment
- 1)) / alignment
;
1104 const auto aligned
= wholeMultiples
* alignment
;
1105 return aligned
- begin
;
1108 template <typename T
>
1109 inline size_t ByteSize(const Range
<T
>& range
) {
1110 return range
.length() * sizeof(T
);
1113 Maybe
<Range
<const uint8_t>> GetRangeFromView(const dom::ArrayBufferView
& view
,
1115 GLuint elemCountOverride
);
1119 template <typename T
>
1120 RawBuffer
<T
> RawBufferView(const Range
<T
>& range
) {
1121 return RawBuffer
<T
>{range
};
1126 Maybe
<webgl::ErrorInfo
> CheckBindBufferRange(
1127 const GLenum target
, const GLuint index
, const bool isBuffer
,
1128 const uint64_t offset
, const uint64_t size
, const webgl::Limits
& limits
);
1130 Maybe
<webgl::ErrorInfo
> CheckFramebufferAttach(const GLenum bindImageTarget
,
1131 const GLenum curTexTarget
,
1132 const uint32_t mipLevel
,
1133 const uint32_t zLayerBase
,
1134 const uint32_t zLayerCount
,
1135 const webgl::Limits
& limits
);
1137 Result
<webgl::VertAttribPointerCalculated
, webgl::ErrorInfo
>
1138 CheckVertexAttribPointer(bool isWebgl2
, const webgl::VertAttribPointerDesc
&);
1140 uint8_t ElemTypeComponents(GLenum elemType
);
1142 inline std::string
ToString(const nsACString
& text
) {
1143 return {text
.BeginReading(), text
.Length()};
1146 inline void Memcpy(const RangedPtr
<uint8_t>& destBytes
,
1147 const RangedPtr
<const uint8_t>& srcBytes
,
1148 const size_t byteSize
) {
1149 // Trigger range asserts
1150 (void)(srcBytes
+ byteSize
);
1151 (void)(destBytes
+ byteSize
);
1153 memcpy(destBytes
.get(), srcBytes
.get(), byteSize
);
1158 } // namespace mozilla