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/. */
13 #include <type_traits>
14 #include <unordered_map>
18 #include "ImageContainer.h"
19 #include "mozilla/Casting.h"
20 #include "mozilla/CheckedInt.h"
21 #include "mozilla/MathAlgorithms.h"
22 #include "mozilla/Range.h"
23 #include "mozilla/RefCounted.h"
24 #include "mozilla/Result.h"
25 #include "mozilla/ResultVariant.h"
26 #include "mozilla/gfx/2D.h"
27 #include "mozilla/gfx/BuildConstants.h"
28 #include "mozilla/gfx/Logging.h"
29 #include "mozilla/gfx/Point.h"
30 #include "mozilla/gfx/Rect.h"
31 #include "mozilla/ipc/Shmem.h"
32 #include "mozilla/layers/LayersSurfaces.h"
37 #include "mozilla/dom/WebGLRenderingContextBinding.h"
38 #include "mozilla/ipc/SharedMemoryBasic.h"
39 #include "TiedFields.h"
41 // Manual reflection of WebIDL typedefs that are different from their
42 // OpenGL counterparts.
43 using WebGLsizeiptr
= int64_t;
44 using WebGLintptr
= int64_t;
45 using WebGLboolean
= bool;
51 class GLContext
; // This is going to be needed a lot.
55 // Prevent implicit conversions into calloc and malloc. (mozilla namespace
58 template <typename DestT
>
59 class ForbidNarrowing final
{
63 template <typename SrcT
>
64 MOZ_IMPLICIT
ForbidNarrowing(SrcT val
) : mVal(val
) {
66 std::numeric_limits
<SrcT
>::min() >= std::numeric_limits
<DestT
>::min(),
67 "SrcT must be narrower than DestT.");
69 std::numeric_limits
<SrcT
>::max() <= std::numeric_limits
<DestT
>::max(),
70 "SrcT must be narrower than DestT.");
73 explicit operator DestT() const { return mVal
; }
76 inline void* malloc(const ForbidNarrowing
<size_t> s
) {
77 return ::malloc(size_t(s
));
80 inline void* calloc(const ForbidNarrowing
<size_t> n
,
81 const ForbidNarrowing
<size_t> size
) {
82 return ::calloc(size_t(n
), size_t(size
));
89 template <typename From
>
90 class AutoAssertCastT final
{
94 explicit AutoAssertCastT(const From val
) : mVal(val
) {}
96 template <typename To
>
98 return AssertedCast
<To
>(mVal
);
102 } // namespace detail
104 template <typename From
>
105 inline auto AutoAssertCast(const From val
) {
106 return detail::AutoAssertCastT
<From
>(val
);
109 const char* GetEnumName(GLenum val
, const char* defaultRet
= "<unknown>");
110 std::string
EnumString(GLenum val
);
113 template <typename T
>
114 struct QueueParamTraits
;
115 class TexUnpackBytes
;
116 class TexUnpackImage
;
117 class TexUnpackSurface
;
120 class ClientWebGLContext
;
121 struct WebGLTexPboOffset
;
124 class WebGLFramebuffer
;
127 class WebGLRenderbuffer
;
132 class WebGLTransformFeedback
;
133 class WebGLVertexArray
;
137 class VRefCounted
: public RefCounted
<VRefCounted
> {
139 virtual ~VRefCounted() = default;
141 #ifdef MOZ_REFCOUNTED_LEAK_CHECKING
142 virtual const char* typeName() const = 0;
143 virtual size_t typeSize() const = 0;
150 * Implementing WebGL (or OpenGL ES 2.0) on top of desktop OpenGL requires
151 * emulating the vertex attrib 0 array when it's not enabled. Indeed,
152 * OpenGL ES 2.0 allows drawing without vertex attrib 0 array enabled, but
153 * desktop OpenGL does not allow that.
155 enum class WebGLVertexAttrib0Status
: uint8_t {
156 Default
, // default status - no emulation needed
157 EmulatedUninitializedArray
, // need an artificial attrib 0 array, but
158 // contents may be left uninitialized
159 EmulatedInitializedArray
// need an artificial attrib 0 array, and contents
160 // must be initialized
164 * The formats that may participate, either as source or destination formats,
165 * in WebGL texture conversions. This includes:
166 * - all the formats accepted by WebGL.texImage2D, e.g. RGBA4444
167 * - additional formats provided by extensions, e.g. RGB32F
168 * - additional source formats, depending on browser details, used when
169 * uploading textures from DOM elements. See gfxImageSurface::Format().
171 enum class WebGLTexelFormat
: uint8_t {
172 // returned by SurfaceFromElementResultToImageSurface to indicate absence of
175 // common value for formats for which format conversions are not supported
176 FormatNotSupportingAnyConversion
,
177 // dummy pseudo-format meaning "use the other format".
178 // For example, if SrcFormat=Auto and DstFormat=RGB8, then the source
179 // is implicitly treated as being RGB8 itself.
183 A16F
, // OES_texture_half_float
184 A32F
, // OES_texture_float
186 R16F
, // OES_texture_half_float
187 R32F
, // OES_texture_float
190 RA16F
, // OES_texture_half_float
191 RA32F
, // OES_texture_float
199 RGB16F
, // OES_texture_half_float
200 RGB32F
, // OES_texture_float
205 RGBA16F
, // OES_texture_half_float
206 RGBA32F
, // OES_texture_float
207 // DOM element source only formats.
213 enum class WebGLTexImageFunc
: uint8_t {
222 enum class WebGLTexDimensions
: uint8_t { Tex2D
, Tex3D
};
224 // Please keep extensions in alphabetic order.
225 enum class WebGLExtensionID
: uint8_t {
226 ANGLE_instanced_arrays
,
228 EXT_color_buffer_float
,
229 EXT_color_buffer_half_float
,
230 EXT_disjoint_timer_query
,
233 EXT_shader_texture_lod
,
235 EXT_texture_compression_bptc
,
236 EXT_texture_compression_rgtc
,
237 EXT_texture_filter_anisotropic
,
240 OES_draw_buffers_indexed
,
241 OES_element_index_uint
,
242 OES_fbo_render_mipmap
,
243 OES_standard_derivatives
,
245 OES_texture_float_linear
,
246 OES_texture_half_float
,
247 OES_texture_half_float_linear
,
248 OES_vertex_array_object
,
250 WEBGL_color_buffer_float
,
251 WEBGL_compressed_texture_astc
,
252 WEBGL_compressed_texture_etc
,
253 WEBGL_compressed_texture_etc1
,
254 WEBGL_compressed_texture_pvrtc
,
255 WEBGL_compressed_texture_s3tc
,
256 WEBGL_compressed_texture_s3tc_srgb
,
257 WEBGL_debug_renderer_info
,
261 WEBGL_explicit_present
,
266 class UniqueBuffer final
{
267 // Like UniquePtr<>, but for void* and malloc/calloc/free.
268 void* mBuffer
= nullptr;
271 static inline UniqueBuffer
Take(void* buffer
) {
273 ret
.mBuffer
= buffer
;
277 UniqueBuffer() = default;
279 ~UniqueBuffer() { reset(); }
281 UniqueBuffer(UniqueBuffer
&& rhs
) { *this = std::move(rhs
); }
283 UniqueBuffer
& operator=(UniqueBuffer
&& rhs
) {
285 this->mBuffer
= rhs
.mBuffer
;
286 rhs
.mBuffer
= nullptr;
290 explicit operator bool() const { return bool(mBuffer
); }
292 void* get() const { return mBuffer
; }
295 // Believe it or not, when `free` unconditional, it was showing up
296 // in profiles, nearly 20% of time spent in MethodDispatcther<UniformData>
306 struct FormatUsageInfo
;
308 static constexpr GLenum kErrorPerfWarning
= 0x10001;
310 struct SampleableInfo final
{
311 const char* incompleteReason
= nullptr;
313 const webgl::FormatUsageInfo
* usage
= nullptr;
314 bool isDepthTexCompare
= false;
316 bool IsComplete() const { return bool(levels
); }
319 enum class AttribBaseType
: uint8_t {
320 Boolean
, // Can convert from anything.
321 Float
, // Also includes NormU?Int
325 webgl::AttribBaseType
ToAttribBaseType(GLenum
);
326 const char* ToString(AttribBaseType
);
328 enum class UniformBaseType
: uint8_t {
333 const char* ToString(UniformBaseType
);
335 using ObjectId
= uint64_t;
337 enum class BufferKind
: uint8_t {
347 struct FloatOrInt final
// For TexParameter[fi] and friends.
349 bool isFloat
= false;
350 uint8_t padding
[3] = {};
354 explicit FloatOrInt(GLint x
= 0) : isFloat(false), f(x
), i(x
) {}
356 explicit FloatOrInt(GLfloat x
) : isFloat(true), f(x
), i(roundf(x
)) {}
358 auto MutTiedFields() { return std::tie(isFloat
, padding
, f
, i
); }
363 struct WebGLContextOptions final
{
366 bool stencil
= false;
367 bool premultipliedAlpha
= true;
369 bool antialias
= true;
370 bool preserveDrawingBuffer
= false;
371 bool failIfMajorPerformanceCaveat
= false;
372 bool xrCompatible
= false;
374 dom::WebGLPowerPreference powerPreference
=
375 dom::WebGLPowerPreference::Default
;
376 bool ignoreColorSpace
= true;
377 dom::PredefinedColorSpace colorSpace
= dom::PredefinedColorSpace::Srgb
;
378 bool shouldResistFingerprinting
= true;
380 bool enableDebugRendererInfo
= false;
382 auto MutTiedFields() {
391 preserveDrawingBuffer
,
392 failIfMajorPerformanceCaveat
,
398 shouldResistFingerprinting
,
400 enableDebugRendererInfo
);
406 WebGLContextOptions();
407 WebGLContextOptions(const WebGLContextOptions
&) = default;
409 using Self
= WebGLContextOptions
;
410 friend bool operator==(const Self
& a
, const Self
& b
) {
411 return TiedFields(a
) == TiedFields(b
);
413 friend bool operator!=(const Self
& a
, const Self
& b
) { return !(a
== b
); }
418 inline ColorSpace2
ToColorSpace2(const dom::PredefinedColorSpace cs
) {
420 case dom::PredefinedColorSpace::Srgb
:
421 return ColorSpace2::SRGB
;
422 case dom::PredefinedColorSpace::Display_p3
:
423 return ColorSpace2::DISPLAY_P3
;
424 case dom::PredefinedColorSpace::EndGuard_
:
427 MOZ_CRASH("Exhaustive switch");
434 template <typename _T
>
441 auto MutTiedFields() { return std::tie(x
, y
); }
443 template <typename U
, typename V
>
444 static Maybe
<avec2
> From(const U _x
, const V _y
) {
445 const auto x
= CheckedInt
<T
>(_x
);
446 const auto y
= CheckedInt
<T
>(_y
);
447 if (!x
.isValid() || !y
.isValid()) return {};
448 return Some(avec2(x
.value(), y
.value()));
451 template <typename U
>
452 static auto From(const U
& val
) {
453 return From(val
.x
, val
.y
);
455 template <typename U
>
456 static auto FromSize(const U
& val
) {
457 return From(val
.width
, val
.height
);
461 avec2(const T _x
, const T _y
) : x(_x
), y(_y
) {}
463 bool operator==(const avec2
& rhs
) const { return x
== rhs
.x
&& y
== rhs
.y
; }
464 bool operator!=(const avec2
& rhs
) const { return !(*this == rhs
); }
467 avec2 operator OP(const avec2& rhs) const { \
468 return {x OP rhs.x, y OP rhs.y}; \
470 avec2 operator OP(const T rhs) const { return {x OP rhs, y OP rhs}; }
479 avec2
Clamp(const avec2
& min
, const avec2
& max
) const {
480 return {mozilla::Clamp(x
, min
.x
, max
.x
), mozilla::Clamp(y
, min
.y
, max
.y
)};
483 // mozilla::Clamp doesn't work on floats, so be clear that this is a min+max
485 avec2
ClampMinMax(const avec2
& min
, const avec2
& max
) const {
486 const auto ClampScalar
= [](const T v
, const T min
, const T max
) {
487 return std::max(min
, std::min(v
, max
));
489 return {ClampScalar(x
, min
.x
, max
.x
), ClampScalar(y
, min
.y
, max
.y
)};
492 template <typename U
>
493 U
StaticCast() const {
494 return {static_cast<typename
U::T
>(x
), static_cast<typename
U::T
>(y
)};
498 template <typename T
>
499 avec2
<T
> MinExtents(const avec2
<T
>& a
, const avec2
<T
>& b
) {
500 return {std::min(a
.x
, b
.x
), std::min(a
.y
, b
.y
)};
503 template <typename T
>
504 avec2
<T
> MaxExtents(const avec2
<T
>& a
, const avec2
<T
>& b
) {
505 return {std::max(a
.x
, b
.x
), std::max(a
.y
, b
.y
)};
510 template <typename _T
>
518 auto MutTiedFields() { return std::tie(x
, y
, z
); }
520 template <typename U
, typename V
>
521 static Maybe
<avec3
> From(const U _x
, const V _y
, const V _z
) {
522 const auto x
= CheckedInt
<T
>(_x
);
523 const auto y
= CheckedInt
<T
>(_y
);
524 const auto z
= CheckedInt
<T
>(_z
);
525 if (!x
.isValid() || !y
.isValid() || !z
.isValid()) return {};
526 return Some(avec3(x
.value(), y
.value(), z
.value()));
529 template <typename U
>
530 static auto From(const U
& val
) {
531 return From(val
.x
, val
.y
, val
.z
);
535 avec3(const T _x
, const T _y
, const T _z
) : x(_x
), y(_y
), z(_z
) {}
537 bool operator==(const avec3
& rhs
) const {
538 return x
== rhs
.x
&& y
== rhs
.y
&& z
== rhs
.z
;
540 bool operator!=(const avec3
& rhs
) const { return !(*this == rhs
); }
543 using ivec2
= avec2
<int32_t>;
544 using ivec3
= avec3
<int32_t>;
545 using uvec2
= avec2
<uint32_t>;
546 using uvec3
= avec3
<uint32_t>;
548 inline ivec2
AsVec(const gfx::IntSize
& s
) { return {s
.width
, s
.height
}; }
554 struct PackingInfo final
{
558 auto MutTiedFields() { return std::tie(format
, type
); }
560 using Self
= PackingInfo
;
561 friend bool operator<(const Self
& a
, const Self
& b
) {
562 return TiedFields(a
) < TiedFields(b
);
564 friend bool operator==(const Self
& a
, const Self
& b
) {
565 return TiedFields(a
) == TiedFields(b
);
569 friend T
& operator<<(T
& s
, const PackingInfo
& pi
) {
570 s
<< "PackingInfo{format: " << EnumString(pi
.format
)
571 << ", type: " << EnumString(pi
.type
) << "}";
576 struct DriverUnpackInfo final
{
577 GLenum internalFormat
= 0;
578 GLenum unpackFormat
= 0;
579 GLenum unpackType
= 0;
581 PackingInfo
ToPacking() const { return {unpackFormat
, unpackType
}; }
586 template <typename E
>
592 struct BitRef final
{
596 explicit operator bool() const { return bits
.mBits
& mask
; }
598 auto& operator=(const bool val
) {
608 uint64_t Mask(const E i
) const {
609 return uint64_t{1} << static_cast<uint64_t>(i
);
613 BitRef
operator[](const E i
) { return {*this, Mask(i
)}; }
614 bool operator[](const E i
) const { return mBits
& Mask(i
); }
617 class ExtensionBits
: public EnumMask
<WebGLExtensionID
> {};
621 enum class ContextLossReason
: uint8_t {
627 inline bool ReadContextLossReason(const uint8_t val
,
628 ContextLossReason
* const out
) {
629 if (val
> static_cast<uint8_t>(ContextLossReason::Guilty
)) {
632 *out
= static_cast<ContextLossReason
>(val
);
638 struct InitContextDesc final
{
639 bool isWebgl2
= false;
640 bool resistFingerprinting
= false;
642 WebGLContextOptions options
;
643 uint32_t principalKey
= 0;
646 constexpr uint32_t kMaxTransformFeedbackSeparateAttribs
= 4;
648 struct Limits final
{
649 ExtensionBits supportedExtensions
;
652 uint32_t maxTexUnits
= 0;
653 uint32_t maxTex2dSize
= 0;
654 uint32_t maxTexCubeSize
= 0;
655 uint32_t maxVertexAttribs
= 0;
656 uint32_t maxViewportDim
= 0;
657 std::array
<float, 2> pointSizeRange
= {{1, 1}};
658 std::array
<float, 2> lineWidthRange
= {{1, 1}};
661 uint32_t maxTexArrayLayers
= 0;
662 uint32_t maxTex3dSize
= 0;
663 uint32_t maxUniformBufferBindings
= 0;
664 uint32_t uniformBufferOffsetAlignment
= 0;
667 bool astcHdr
= false;
668 uint32_t maxColorDrawBuffers
= 1;
669 uint64_t queryCounterBitsTimeElapsed
= 0;
670 uint64_t queryCounterBitsTimestamp
= 0;
671 uint32_t maxMultiviewLayers
= 0;
674 struct InitContextResult final
{
676 WebGLContextOptions options
;
677 webgl::Limits limits
;
678 EnumMask
<layers::SurfaceDescriptor::Type
> uploadableSdTypes
;
683 struct ErrorInfo final
{
688 struct ShaderPrecisionFormat final
{
696 enum class LossStatus
{
706 struct CompileResult final
{
709 nsCString translatedSource
;
710 bool success
= false;
715 struct OpaqueFramebufferOptions final
{
716 bool depthStencil
= true;
717 bool antialias
= true;
724 struct SwapChainOptions final
{
725 layers::RemoteTextureId remoteTextureId
;
726 layers::RemoteTextureOwnerId remoteTextureOwnerId
;
728 bool forceAsyncPresent
= false;
729 // Pad to sizeof(u64):
730 uint16_t padding1
= 0;
731 uint32_t padding2
= 0;
733 auto MutTiedFields() {
734 return std::tie(remoteTextureId
, remoteTextureOwnerId
, bgra
,
735 forceAsyncPresent
, padding1
, padding2
);
742 GLenum elemType
= 0; // `type`
743 uint32_t elemCount
= 0; // `size`
747 struct ActiveAttribInfo final
: public ActiveInfo
{
748 int32_t location
= -1;
749 AttribBaseType baseType
= AttribBaseType::Float
;
752 struct ActiveUniformInfo final
: public ActiveInfo
{
753 std::unordered_map
<uint32_t, uint32_t>
754 locByIndex
; // Uniform array locations are sparse.
755 int32_t block_index
= -1;
756 int32_t block_offset
= -1; // In block, offset.
757 int32_t block_arrayStride
= -1;
758 int32_t block_matrixStride
= -1;
759 bool block_isRowMajor
= false;
762 struct ActiveUniformBlockInfo final
{
764 // BLOCK_BINDING is dynamic state
765 uint32_t dataSize
= 0;
766 std::vector
<uint32_t> activeUniformIndices
;
767 bool referencedByVertexShader
= false;
768 bool referencedByFragmentShader
= false;
771 struct LinkActiveInfo final
{
772 std::vector
<ActiveAttribInfo
> activeAttribs
;
773 std::vector
<ActiveUniformInfo
> activeUniforms
;
774 std::vector
<ActiveUniformBlockInfo
> activeUniformBlocks
;
775 std::vector
<ActiveInfo
> activeTfVaryings
;
778 struct LinkResult final
{
781 bool success
= false;
782 LinkActiveInfo active
;
783 GLenum tfBufferMode
= 0;
788 /// 4x32-bit primitives, with a type tag.
789 struct TypedQuad final
{
790 alignas(alignof(float)) std::array
<uint8_t, 4 * sizeof(float)> data
= {};
791 webgl::AttribBaseType type
= webgl::AttribBaseType::Float
;
792 uint8_t padding
[3] = {};
794 constexpr auto MutTiedFields() { return std::tie(data
, type
, padding
); }
797 /// [1-16]x32-bit primitives, with a type tag.
798 struct GetUniformData final
{
799 alignas(alignof(float)) uint8_t data
[4 * 4 * sizeof(float)] = {};
803 struct FrontBufferSnapshotIpc final
{
805 Maybe
<mozilla::ipc::Shmem
> shmem
= {};
808 struct ReadPixelsResult
{
809 gfx::IntRect subrect
= {};
810 size_t byteStride
= 0;
813 struct ReadPixelsResultIpc final
: public ReadPixelsResult
{
814 Maybe
<mozilla::ipc::Shmem
> shmem
= {};
817 struct VertAttribPointerDesc final
{
818 bool intFunc
= false;
819 uint8_t channels
= 4;
820 bool normalized
= false;
821 uint8_t byteStrideOrZero
= 0;
822 GLenum type
= LOCAL_GL_FLOAT
;
823 uint64_t byteOffset
= 0;
825 auto MutTiedFields() {
826 return std::tie(intFunc
, channels
, normalized
, byteStrideOrZero
, type
,
831 struct VertAttribPointerCalculated final
{
832 uint8_t byteSize
= 4 * 4;
833 uint8_t byteStride
= 4 * 4; // at-most 255
834 webgl::AttribBaseType baseType
= webgl::AttribBaseType::Float
;
840 * Represents a block of memory that it may or may not own. The
841 * inner data type must be trivially copyable by memcpy.
843 template <typename T
= uint8_t>
844 class RawBuffer final
{
845 const T
* mBegin
= nullptr;
850 using ElementType
= T
;
853 * If aTakeData is true, RawBuffer will delete[] the memory when destroyed.
855 explicit RawBuffer(const Range
<const T
>& data
, UniqueBuffer
&& owned
= {})
856 : mBegin(data
.begin().get()),
858 mOwned(std::move(owned
)) {}
860 explicit RawBuffer(const size_t len
) : mLen(len
) {}
862 ~RawBuffer() = default;
864 Range
<const T
> Data() const { return {mBegin
, mLen
}; }
865 const auto& begin() const { return mBegin
; }
866 const auto& size() const { return mLen
; }
868 void Shrink(const size_t newLen
) {
869 if (mLen
<= newLen
) return;
873 RawBuffer() = default;
875 RawBuffer(const RawBuffer
&) = delete;
876 RawBuffer
& operator=(const RawBuffer
&) = delete;
878 RawBuffer(RawBuffer
&&) = default;
879 RawBuffer
& operator=(RawBuffer
&&) = default;
883 inline Range
<T
> ShmemRange(const mozilla::ipc::Shmem
& shmem
) {
884 return {shmem
.get
<T
>(), shmem
.Size
<T
>()};
889 template <typename C
, typename K
>
890 inline auto MaybeFind(C
& container
, const K
& key
)
891 -> decltype(&(container
.find(key
)->second
)) {
892 const auto itr
= container
.find(key
);
893 if (itr
== container
.end()) return nullptr;
894 return &(itr
->second
);
897 template <typename C
, typename K
>
898 inline typename
C::mapped_type
Find(
899 const C
& container
, const K
& key
,
900 const typename
C::mapped_type notFound
= {}) {
901 const auto itr
= container
.find(key
);
902 if (itr
== container
.end()) return notFound
;
908 template <typename T
, typename U
>
909 inline Maybe
<T
> MaybeAs(const U val
) {
910 const auto checked
= CheckedInt
<T
>(val
);
911 if (!checked
.isValid()) return {};
912 return Some(checked
.value());
917 inline GLenum
ImageToTexTarget(const GLenum imageTarget
) {
918 switch (imageTarget
) {
919 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
920 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
921 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
922 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
923 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
924 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
925 return LOCAL_GL_TEXTURE_CUBE_MAP
;
931 inline bool IsTexTarget3D(const GLenum texTarget
) {
933 case LOCAL_GL_TEXTURE_2D_ARRAY
:
934 case LOCAL_GL_TEXTURE_3D
:
948 class OffscreenCanvas
;
951 struct TexImageSource
{
952 const dom::ArrayBufferView
* mView
= nullptr;
953 GLuint mViewElemOffset
= 0;
954 GLuint mViewElemLengthOverride
= 0;
956 const WebGLintptr
* mPboOffset
= nullptr;
958 const dom::ImageBitmap
* mImageBitmap
= nullptr;
959 const dom::ImageData
* mImageData
= nullptr;
961 const dom::OffscreenCanvas
* mOffscreenCanvas
= nullptr;
963 const dom::Element
* mDomElem
= nullptr;
964 ErrorResult
* mOut_error
= nullptr;
969 template <class DerivedT
>
971 bool operator!=(const DerivedT
& rhs
) const {
972 const auto self
= reinterpret_cast<const DerivedT
*>(this);
973 return !(*self
== rhs
);
977 struct PixelPackingState
: public DeriveNotEq
<PixelPackingState
> {
978 uint32_t alignmentInTypeElems
= 4; // ALIGNMENT isn't naive byte alignment!
979 uint32_t rowLength
= 0;
980 uint32_t imageHeight
= 0;
981 uint32_t skipPixels
= 0;
982 uint32_t skipRows
= 0;
983 uint32_t skipImages
= 0;
985 auto MutTiedFields() {
986 return std::tie(alignmentInTypeElems
, rowLength
, imageHeight
, skipPixels
,
987 skipRows
, skipImages
);
990 using Self
= PixelPackingState
;
991 friend bool operator==(const Self
& a
, const Self
& b
) {
992 return TiedFields(a
) == TiedFields(b
);
995 static void AssertDefaultUnpack(gl::GLContext
& gl
, const bool isWebgl2
) {
996 PixelPackingState
{}.AssertCurrentUnpack(gl
, isWebgl2
);
999 void ApplyUnpack(gl::GLContext
&, bool isWebgl2
,
1000 const uvec3
& uploadSize
) const;
1001 bool AssertCurrentUnpack(gl::GLContext
&, bool isWebgl2
) const;
1004 struct PixelUnpackStateWebgl final
: public PixelPackingState
{
1005 GLenum colorspaceConversion
=
1006 dom::WebGLRenderingContext_Binding::BROWSER_DEFAULT_WEBGL
;
1008 bool premultiplyAlpha
= false;
1009 bool requireFastPath
= false;
1010 uint8_t padding
= {};
1012 auto MutTiedFields() {
1013 return std::tuple_cat(PixelPackingState::MutTiedFields(),
1014 std::tie(colorspaceConversion
, flipY
,
1015 premultiplyAlpha
, requireFastPath
, padding
));
1019 struct ExplicitPixelPackingState final
{
1020 struct Metrics final
{
1021 uvec3 usedSize
= {};
1022 size_t bytesPerPixel
= 0;
1024 // (srcStrideAndRowOverride.x, otherwise ROW_LENGTH != 0, otherwise size.x)
1025 // ...aligned to ALIGNMENT.
1026 size_t bytesPerRowStride
= 0;
1028 // structuredSrcSize.y, otherwise IMAGE_HEIGHT*(SKIP_IMAGES+size.z)
1029 size_t totalRows
= 0;
1031 // This ensures that no one else needs to do CheckedInt math.
1032 size_t totalBytesUsed
= 0;
1033 size_t totalBytesStrided
= 0;
1036 // It's so important that these aren't modified once evaluated.
1037 const PixelPackingState state
;
1038 const Metrics metrics
;
1040 static Result
<ExplicitPixelPackingState
, std::string
> ForUseWith(
1041 const PixelPackingState
&, GLenum target
, const uvec3
& subrectSize
,
1042 const webgl::PackingInfo
&, const Maybe
<size_t> bytesPerRowStrideOverride
);
1045 struct ReadPixelsDesc final
{
1048 PackingInfo pi
= {LOCAL_GL_RGBA
, LOCAL_GL_UNSIGNED_BYTE
};
1049 PixelPackingState packState
;
1051 auto MutTiedFields() { return std::tie(srcOffset
, size
, pi
, packState
); }
1054 } // namespace webgl
1058 struct TexUnpackBlobDesc final
{
1059 GLenum imageTarget
= LOCAL_GL_TEXTURE_2D
;
1061 gfxAlphaType srcAlphaType
= gfxAlphaType::NonPremult
;
1063 Maybe
<RawBuffer
<>> cpuData
;
1064 Maybe
<uint64_t> pboOffset
;
1066 Maybe
<uvec2
> structuredSrcSize
;
1067 RefPtr
<layers::Image
> image
;
1068 Maybe
<layers::SurfaceDescriptor
> sd
;
1069 RefPtr
<gfx::DataSourceSurface
> dataSurf
;
1071 webgl::PixelUnpackStateWebgl unpacking
;
1072 bool applyUnpackTransforms
= true;
1076 auto ExplicitUnpacking(const webgl::PackingInfo
& pi
,
1077 const Maybe
<size_t> bytesPerRowStrideOverride
) const {
1078 return ExplicitPixelPackingState::ForUseWith(this->unpacking
,
1079 this->imageTarget
, this->size
,
1080 pi
, bytesPerRowStrideOverride
);
1083 void Shrink(const webgl::PackingInfo
&);
1086 } // namespace webgl
1088 // ---------------------------------------
1091 template <typename T
, size_t N
>
1092 inline Range
<const T
> MakeRange(T (&arr
)[N
]) {
1096 template <typename T
>
1097 inline Range
<const T
> MakeRange(const dom::Sequence
<T
>& seq
) {
1098 return {seq
.Elements(), seq
.Length()};
1101 template <typename T
>
1102 inline Range
<const T
> MakeRange(const RawBuffer
<T
>& from
) {
1106 // abv = ArrayBufferView
1107 template <typename T
>
1108 inline auto MakeRangeAbv(const T
& abv
)
1109 -> Range
<const typename
T::element_type
> {
1111 return {abv
.Data(), abv
.Length()};
1116 constexpr auto kUniversalAlignment
= alignof(std::max_align_t
);
1118 template <typename T
>
1119 inline size_t AlignmentOffset(const size_t alignment
, const T posOrPtr
) {
1120 MOZ_ASSERT(alignment
);
1121 const auto begin
= reinterpret_cast<uintptr_t>(posOrPtr
);
1122 const auto wholeMultiples
= (begin
+ (alignment
- 1)) / alignment
;
1123 const auto aligned
= wholeMultiples
* alignment
;
1124 return aligned
- begin
;
1127 template <typename T
>
1128 inline size_t ByteSize(const Range
<T
>& range
) {
1129 return range
.length() * sizeof(T
);
1132 Maybe
<Range
<const uint8_t>> GetRangeFromView(const dom::ArrayBufferView
& view
,
1134 GLuint elemCountOverride
);
1138 template <typename T
>
1139 RawBuffer
<T
> RawBufferView(const Range
<T
>& range
) {
1140 return RawBuffer
<T
>{range
};
1145 Maybe
<webgl::ErrorInfo
> CheckBindBufferRange(
1146 const GLenum target
, const GLuint index
, const bool isBuffer
,
1147 const uint64_t offset
, const uint64_t size
, const webgl::Limits
& limits
);
1149 Maybe
<webgl::ErrorInfo
> CheckFramebufferAttach(const GLenum bindImageTarget
,
1150 const GLenum curTexTarget
,
1151 const uint32_t mipLevel
,
1152 const uint32_t zLayerBase
,
1153 const uint32_t zLayerCount
,
1154 const webgl::Limits
& limits
);
1156 Result
<webgl::VertAttribPointerCalculated
, webgl::ErrorInfo
>
1157 CheckVertexAttribPointer(bool isWebgl2
, const webgl::VertAttribPointerDesc
&);
1159 uint8_t ElemTypeComponents(GLenum elemType
);
1161 inline std::string
ToString(const nsACString
& text
) {
1162 return {text
.BeginReading(), text
.Length()};
1165 inline void Memcpy(const RangedPtr
<uint8_t>& destBytes
,
1166 const RangedPtr
<const uint8_t>& srcBytes
,
1167 const size_t byteSize
) {
1168 // Trigger range asserts
1169 (void)(srcBytes
+ byteSize
);
1170 (void)(destBytes
+ byteSize
);
1172 memcpy(destBytes
.get(), srcBytes
.get(), byteSize
);
1175 template <class T
, class U
>
1176 inline void Memcpy(const Range
<T
>* const destRange
,
1177 const RangedPtr
<U
>& srcBegin
) {
1178 Memcpy(destRange
->begin(), srcBegin
, destRange
->length());
1180 template <class T
, class U
>
1181 inline void Memcpy(const RangedPtr
<T
>* const destBegin
,
1182 const Range
<U
>& srcRange
) {
1183 Memcpy(destBegin
, srcRange
->begin(), srcRange
->length());
1190 // In theory, this number can be unbounded based on the driver. However, no
1191 // driver appears to expose more than 8. We might as well stop there too, for
1193 // (http://opengl.gpuinfo.org/gl_stats_caps_single.php?listreportsbycap=GL_MAX_COLOR_ATTACHMENTS)
1194 inline constexpr size_t kMaxDrawBuffers
= 8;
1196 union UniformDataVal
{
1202 } // namespace webgl
1206 template <class T
, size_t InlineCapacity
>
1207 struct InliningAllocator
{
1208 using value_type
= T
;
1212 typedef InliningAllocator
<U
, InlineCapacity
> other
;
1216 std::array
<T
, InlineCapacity
> mInlined
= {};
1219 InliningAllocator() = default;
1220 InliningAllocator(const InliningAllocator
&) = delete;
1221 InliningAllocator(InliningAllocator
&&) = delete;
1222 InliningAllocator
& operator=(const InliningAllocator
&) = delete;
1223 InliningAllocator
& operator=(InliningAllocator
&&) = delete;
1225 T
* allocate(const size_t n
) {
1227 if (n
<= mInlined
.size()) {
1228 p
= mInlined
.data(); // You better be using memmove not memcpy!
1234 void deallocate(T
* const p
, size_t) {
1235 if (p
!= mInlined
.data()) {
1240 template <class T
, size_t N
>
1241 using inlining_vector
= std::vector
<T
, InliningAllocator
<T
, N
>>;
1243 } // namespace mozilla