Bug 1700051: part 26) Correct typo in comment of `mozInlineSpellWordUtil::BuildSoftTe...
[gecko.git] / dom / canvas / WebGLTypes.h
blob9e436bf7166be8689fbe61c871eb7e2fcf9469f4
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/. */
6 #ifndef WEBGLTYPES_H_
7 #define WEBGLTYPES_H_
9 #include <limits>
10 #include <type_traits>
11 #include <unordered_map>
12 #include <vector>
14 #include "GLDefs.h"
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"
28 #include "gfxTypes.h"
30 #include "nsTArray.h"
31 #include "nsString.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;
41 // -
43 namespace mozilla {
44 namespace gl {
45 class GLContext; // This is going to be needed a lot.
46 } // namespace gl
48 // -
49 // Prevent implicit conversions into calloc and malloc. (mozilla namespace
50 // only!)
52 template <typename DestT>
53 class ForbidNarrowing final {
54 DestT mVal;
56 public:
57 template <typename SrcT>
58 MOZ_IMPLICIT ForbidNarrowing(SrcT val) : mVal(val) {
59 static_assert(
60 std::numeric_limits<SrcT>::min() >= std::numeric_limits<DestT>::min(),
61 "SrcT must be narrower than DestT.");
62 static_assert(
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));
79 // -
81 namespace detail {
83 template <typename From>
84 class AutoAssertCastT final {
85 const From mVal;
87 public:
88 explicit AutoAssertCastT(const From val) : mVal(val) {}
90 template <typename To>
91 operator To() const {
92 return AssertedCast<To>(mVal);
96 } // namespace detail
98 template <typename From>
99 inline auto AutoAssertCast(const From val) {
100 return detail::AutoAssertCastT<From>(val);
103 namespace webgl {
104 template <typename T>
105 struct QueueParamTraits;
106 class TexUnpackBytes;
107 class TexUnpackImage;
108 class TexUnpackSurface;
109 } // namespace webgl
111 class ClientWebGLContext;
112 struct WebGLTexPboOffset;
113 class WebGLTexture;
114 class WebGLBuffer;
115 class WebGLFramebuffer;
116 class WebGLProgram;
117 class WebGLQuery;
118 class WebGLRenderbuffer;
119 class WebGLSampler;
120 class WebGLShader;
121 class WebGLSync;
122 class WebGLTexture;
123 class WebGLTransformFeedback;
124 class WebGLVertexArray;
126 // -
128 class VRefCounted : public RefCounted<VRefCounted> {
129 public:
130 virtual ~VRefCounted() = default;
132 #ifdef MOZ_REFCOUNTED_LEAK_CHECKING
133 virtual const char* typeName() const = 0;
134 virtual size_t typeSize() const = 0;
135 #endif
138 // -
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
164 // image data
165 None,
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.
171 Auto,
172 // 1-channel formats
174 A16F, // OES_texture_half_float
175 A32F, // OES_texture_float
177 R16F, // OES_texture_half_float
178 R32F, // OES_texture_float
179 // 2-channel formats
180 RA8,
181 RA16F, // OES_texture_half_float
182 RA32F, // OES_texture_float
183 RG8,
184 RG16F,
185 RG32F,
186 // 3-channel formats
187 RGB8,
188 RGB565,
189 RGB11F11F10F,
190 RGB16F, // OES_texture_half_float
191 RGB32F, // OES_texture_float
192 // 4-channel formats
193 RGBA8,
194 RGBA5551,
195 RGBA4444,
196 RGBA16F, // OES_texture_half_float
197 RGBA32F, // OES_texture_float
198 // DOM element source only formats.
199 RGBX8,
200 BGRX8,
201 BGRA8
204 enum class WebGLTexImageFunc : uint8_t {
205 TexImage,
206 TexSubImage,
207 CopyTexImage,
208 CopyTexSubImage,
209 CompTexImage,
210 CompTexSubImage,
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,
218 EXT_blend_minmax,
219 EXT_color_buffer_float,
220 EXT_color_buffer_half_float,
221 EXT_disjoint_timer_query,
222 EXT_float_blend,
223 EXT_frag_depth,
224 EXT_shader_texture_lod,
225 EXT_sRGB,
226 EXT_texture_compression_bptc,
227 EXT_texture_compression_rgtc,
228 EXT_texture_filter_anisotropic,
229 EXT_texture_norm16,
230 MOZ_debug,
231 OES_element_index_uint,
232 OES_fbo_render_mipmap,
233 OES_standard_derivatives,
234 OES_texture_float,
235 OES_texture_float_linear,
236 OES_texture_half_float,
237 OES_texture_half_float_linear,
238 OES_vertex_array_object,
239 OVR_multiview2,
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,
248 WEBGL_debug_shaders,
249 WEBGL_depth_texture,
250 WEBGL_draw_buffers,
251 WEBGL_explicit_present,
252 WEBGL_lose_context,
256 class UniqueBuffer {
257 // Like UniquePtr<>, but for void* and malloc/calloc/free.
258 void* mBuffer;
260 public:
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) {
277 free(this->mBuffer);
278 this->mBuffer = other.mBuffer;
279 other.mBuffer = nullptr;
280 return *this;
283 UniqueBuffer& operator=(void* newBuffer) {
284 free(this->mBuffer);
285 this->mBuffer = newBuffer;
286 return *this;
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()!
299 namespace webgl {
300 struct FormatUsageInfo;
302 static constexpr GLenum kErrorPerfWarning = 0x10001;
304 struct SampleableInfo final {
305 const char* incompleteReason = nullptr;
306 uint32_t levels = 0;
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
316 Int,
317 Uint,
319 webgl::AttribBaseType ToAttribBaseType(GLenum);
320 const char* ToString(AttribBaseType);
322 enum class UniformBaseType : uint8_t {
323 Float,
324 Int,
325 Uint,
327 const char* ToString(UniformBaseType);
329 typedef uint64_t ObjectId;
331 enum class BufferKind : uint8_t {
332 Undefined,
333 Index,
334 NonIndex,
337 } // namespace webgl
339 // -
341 struct FloatOrInt final // For TexParameter[fi] and friends.
343 const bool isFloat;
344 const GLfloat f;
345 const GLint i;
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));
353 return *this;
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 {
365 bool alpha = true;
366 bool depth = true;
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);
387 // -
389 template <typename _T>
390 struct avec2 {
391 using T = _T;
393 T x = T();
394 T y = 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);
413 avec2() = default;
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); }
419 #define _(OP) \
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}; }
425 _(+)
426 _(-)
427 _(*)
428 _(/)
430 #undef _
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
437 // helper.
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)};
461 // -
463 template <typename _T>
464 struct avec3 {
465 using T = _T;
467 T x = T();
468 T y = T();
469 T z = 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);
485 avec3() = default;
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}; }
501 // -
503 namespace webgl {
505 struct PackingInfo final {
506 GLenum format = 0;
507 GLenum type = 0;
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 {
536 ivec2 srcOffset;
537 uvec2 size;
538 PackingInfo pi = {LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE};
539 PixelPackState packState;
542 // -
544 template <typename E>
545 class EnumMask {
546 public:
547 uint64_t mBits = 0;
549 private:
550 struct BitRef final {
551 EnumMask& bits;
552 const uint64_t mask;
554 explicit operator bool() const { return bits.mBits & mask; }
556 auto& operator=(const bool val) {
557 if (val) {
558 bits.mBits |= mask;
559 } else {
560 bits.mBits &= ~mask;
562 return *this;
566 uint64_t Mask(const E i) const {
567 return uint64_t{1} << static_cast<uint64_t>(i);
570 public:
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> {};
577 // -
579 enum class ContextLossReason : uint8_t {
580 None,
581 Manual,
582 Guilty,
585 inline bool ReadContextLossReason(const uint8_t val,
586 ContextLossReason* const out) {
587 if (val > static_cast<uint8_t>(ContextLossReason::Guilty)) {
588 return false;
590 *out = static_cast<ContextLossReason>(val);
591 return true;
594 // -
596 struct InitContextDesc final {
597 bool isWebgl2 = false;
598 bool resistFingerprinting = false;
599 uvec2 size = {};
600 WebGLContextOptions options;
601 uint32_t principalKey = 0;
604 struct Limits final {
605 ExtensionBits supportedExtensions;
607 // WebGL 1
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}};
616 // WebGL 2
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;
623 // Exts
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 {
632 std::string error;
633 WebGLContextOptions options;
634 webgl::Limits limits;
635 EnumMask<layers::SurfaceDescriptor::Type> uploadableSdTypes;
638 // -
640 struct ErrorInfo final {
641 GLenum type;
642 std::string info;
645 struct ShaderPrecisionFormat final {
646 GLint rangeMin = 0;
647 GLint rangeMax = 0;
648 GLint precision = 0;
651 // -
653 enum class LossStatus {
654 Ready,
656 Lost,
657 LostForever,
658 LostManually,
661 // -
663 struct CompileResult final {
664 bool pending = true;
665 nsCString log;
666 nsCString translatedSource;
667 bool success = false;
670 // -
672 struct OpaqueFramebufferOptions final {
673 bool depthStencil = true;
674 bool antialias = true;
675 uint32_t width = 0;
676 uint32_t height = 0;
679 // -
681 struct ActiveInfo {
682 GLenum elemType = 0; // `type`
683 uint32_t elemCount = 0; // `size`
684 std::string name;
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 {
703 std::string name;
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 {
719 bool pending = true;
720 nsCString log;
721 bool success = false;
722 LinkActiveInfo active;
723 GLenum tfBufferMode = 0;
726 // -
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)] = {};
737 GLenum type = 0;
740 struct FrontBufferSnapshotIpc final {
741 uvec2 surfSize = {};
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;
769 } // namespace webgl
771 // return value for the InitializeCanvasRenderer message
772 struct ICRData {
773 gfx::IntSize size;
774 bool hasAlpha;
775 bool isPremultAlpha;
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;
785 size_t mLen = 0;
786 UniqueBuffer mOwned;
788 public:
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()),
796 mLen(data.length()),
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;
809 mLen = newLen;
812 RawBuffer() = default;
814 RawBuffer(const RawBuffer&) = delete;
815 RawBuffer& operator=(const RawBuffer&) = delete;
817 RawBuffer(RawBuffer&&) = default;
818 RawBuffer& operator=(RawBuffer&&) = default;
821 // -
823 struct CopyableRange final : public Range<const uint8_t> {};
825 // -
827 // clang-format off
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) \
837 X(drawArrays) \
838 X(drawArraysInstanced) \
839 X(drawElements) \
840 X(drawElementsInstanced) \
841 X(drawRangeElements) \
842 X(renderbufferStorage) \
843 X(renderbufferStorageMultisample) \
844 X(texImage2D) \
845 X(texImage3D) \
846 X(TexStorage2D) \
847 X(TexStorage3D) \
848 X(texSubImage2D) \
849 X(texSubImage3D) \
850 X(vertexAttrib1f) \
851 X(vertexAttrib1fv) \
852 X(vertexAttrib2f) \
853 X(vertexAttrib2fv) \
854 X(vertexAttrib3f) \
855 X(vertexAttrib3fv) \
856 X(vertexAttrib4f) \
857 X(vertexAttrib4fv) \
858 X(vertexAttribI4i) \
859 X(vertexAttribI4iv) \
860 X(vertexAttribI4ui) \
861 X(vertexAttribI4uiv) \
862 X(vertexAttribIPointer) \
863 X(vertexAttribPointer)
865 // clang-format on
867 enum class FuncScopeId {
868 #define _(X) X,
869 FOREACH_ID(_)
870 #undef _
873 static constexpr const char* const FUNCSCOPE_NAME_BY_ID[] = {
874 #define _(X) #X,
875 FOREACH_ID(_)
876 #undef _
879 #undef FOREACH_ID
881 inline auto GetFuncScopeName(const FuncScopeId id) {
882 return FUNCSCOPE_NAME_BY_ID[static_cast<size_t>(id)];
885 // -
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;
901 return itr->second;
904 // -
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());
913 // -
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;
924 default:
925 return imageTarget;
929 inline bool IsTexTarget3D(const GLenum texTarget) {
930 switch (texTarget) {
931 case LOCAL_GL_TEXTURE_2D_ARRAY:
932 case LOCAL_GL_TEXTURE_3D:
933 return true;
935 default:
936 return false;
940 // -
942 namespace dom {
943 class Element;
944 class ImageBitmap;
945 class ImageData;
946 } // namespace dom
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;
971 bool mFlipY = false;
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));
978 Unused << expected;
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 {
986 auto ret = *this;
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;
1009 return ret;
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);
1024 auto skipFullRows =
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;
1041 RawBuffer<> data;
1043 const dom::Element* domElem = nullptr;
1044 ErrorResult* out_domElemError = nullptr;
1047 namespace webgl {
1049 struct TexUnpackBlobDesc final {
1050 GLenum imageTarget = LOCAL_GL_TEXTURE_2D;
1051 uvec3 size;
1052 gfxAlphaType srcAlphaType = gfxAlphaType::NonPremult;
1054 Maybe<RawBuffer<>> cpuData;
1055 Maybe<uint64_t> pboOffset;
1057 uvec2 imageSize;
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 // ---------------------------------------
1070 // MakeRange
1072 template <typename T, size_t N>
1073 inline Range<const T> MakeRange(T (&arr)[N]) {
1074 return {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) {
1084 return from.Data();
1087 // abv = ArrayBufferView
1088 template <typename T>
1089 inline auto MakeRangeAbv(const T& abv)
1090 -> Range<const typename T::element_type> {
1091 abv.ComputeState();
1092 return {abv.Data(), abv.Length()};
1095 // -
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,
1114 GLuint elemOffset,
1115 GLuint elemCountOverride);
1117 // -
1119 template <typename T>
1120 RawBuffer<T> RawBufferView(const Range<T>& range) {
1121 return RawBuffer<T>{range};
1124 // -
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);
1156 // -
1158 } // namespace mozilla
1160 #endif