Bug 1850713: remove duplicated setting of early hint preloader id in `ScriptLoader...
[gecko.git] / dom / canvas / WebGLTypes.h
blobcdf255ab442787ddf760207a2d1eab1d6fb1d9f7
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 <string>
11 #include <string_view>
12 #include <tuple>
13 #include <type_traits>
14 #include <unordered_map>
15 #include <vector>
17 #include "GLDefs.h"
18 #include "GLVendor.h"
19 #include "ImageContainer.h"
20 #include "mozilla/Casting.h"
21 #include "mozilla/CheckedInt.h"
22 #include "mozilla/MathAlgorithms.h"
23 #include "mozilla/Range.h"
24 #include "mozilla/RefCounted.h"
25 #include "mozilla/Result.h"
26 #include "mozilla/ResultVariant.h"
27 #include "mozilla/gfx/2D.h"
28 #include "mozilla/gfx/BuildConstants.h"
29 #include "mozilla/gfx/Logging.h"
30 #include "mozilla/gfx/Point.h"
31 #include "mozilla/gfx/Rect.h"
32 #include "mozilla/ipc/Shmem.h"
33 #include "mozilla/layers/LayersSurfaces.h"
34 #include "gfxTypes.h"
36 #include "nsTArray.h"
37 #include "nsString.h"
38 #include "mozilla/dom/WebGLRenderingContextBinding.h"
39 #include "mozilla/ipc/SharedMemoryBasic.h"
40 #include "TiedFields.h"
42 // Manual reflection of WebIDL typedefs that are different from their
43 // OpenGL counterparts.
44 using WebGLsizeiptr = int64_t;
45 using WebGLintptr = int64_t;
46 using WebGLboolean = bool;
48 // -
50 namespace mozilla {
51 namespace gl {
52 class GLContext; // This is going to be needed a lot.
53 } // namespace gl
55 // -
56 // Prevent implicit conversions into calloc and malloc. (mozilla namespace
57 // only!)
59 template <typename DestT>
60 class ForbidNarrowing final {
61 DestT mVal;
63 public:
64 template <typename SrcT>
65 MOZ_IMPLICIT ForbidNarrowing(SrcT val) : mVal(val) {
66 static_assert(
67 std::numeric_limits<SrcT>::min() >= std::numeric_limits<DestT>::min(),
68 "SrcT must be narrower than DestT.");
69 static_assert(
70 std::numeric_limits<SrcT>::max() <= std::numeric_limits<DestT>::max(),
71 "SrcT must be narrower than DestT.");
74 explicit operator DestT() const { return mVal; }
77 inline void* malloc(const ForbidNarrowing<size_t> s) {
78 return ::malloc(size_t(s));
81 inline void* calloc(const ForbidNarrowing<size_t> n,
82 const ForbidNarrowing<size_t> size) {
83 return ::calloc(size_t(n), size_t(size));
86 // -
88 // TODO: Remove this now-mere-alias.
89 template <typename From>
90 inline auto AutoAssertCast(const From val) {
91 return LazyAssertedCast(val);
94 const char* GetEnumName(GLenum val, const char* defaultRet = "<unknown>");
95 std::string EnumString(GLenum val);
97 namespace webgl {
98 template <typename T>
99 struct QueueParamTraits;
100 class TexUnpackBytes;
101 class TexUnpackImage;
102 class TexUnpackSurface;
103 } // namespace webgl
105 class ClientWebGLContext;
106 struct WebGLTexPboOffset;
107 class WebGLTexture;
108 class WebGLBuffer;
109 class WebGLFramebuffer;
110 class WebGLProgram;
111 class WebGLQuery;
112 class WebGLRenderbuffer;
113 class WebGLSampler;
114 class WebGLShader;
115 class WebGLSync;
116 class WebGLTexture;
117 class WebGLTransformFeedback;
118 class WebGLVertexArray;
120 // -
122 class VRefCounted : public RefCounted<VRefCounted> {
123 public:
124 virtual ~VRefCounted() = default;
126 #ifdef MOZ_REFCOUNTED_LEAK_CHECKING
127 virtual const char* typeName() const = 0;
128 virtual size_t typeSize() const = 0;
129 #endif
132 // -
135 * Implementing WebGL (or OpenGL ES 2.0) on top of desktop OpenGL requires
136 * emulating the vertex attrib 0 array when it's not enabled. Indeed,
137 * OpenGL ES 2.0 allows drawing without vertex attrib 0 array enabled, but
138 * desktop OpenGL does not allow that.
140 enum class WebGLVertexAttrib0Status : uint8_t {
141 Default, // default status - no emulation needed
142 EmulatedUninitializedArray, // need an artificial attrib 0 array, but
143 // contents may be left uninitialized
144 EmulatedInitializedArray // need an artificial attrib 0 array, and contents
145 // must be initialized
149 * The formats that may participate, either as source or destination formats,
150 * in WebGL texture conversions. This includes:
151 * - all the formats accepted by WebGL.texImage2D, e.g. RGBA4444
152 * - additional formats provided by extensions, e.g. RGB32F
153 * - additional source formats, depending on browser details, used when
154 * uploading textures from DOM elements. See gfxImageSurface::Format().
156 enum class WebGLTexelFormat : uint8_t {
157 // returned by SurfaceFromElementResultToImageSurface to indicate absence of
158 // image data
159 None,
160 // common value for formats for which format conversions are not supported
161 FormatNotSupportingAnyConversion,
162 // dummy pseudo-format meaning "use the other format".
163 // For example, if SrcFormat=Auto and DstFormat=RGB8, then the source
164 // is implicitly treated as being RGB8 itself.
165 Auto,
166 // 1-channel formats
168 A16F, // OES_texture_half_float
169 A32F, // OES_texture_float
171 R16F, // OES_texture_half_float
172 R32F, // OES_texture_float
173 // 2-channel formats
174 RA8,
175 RA16F, // OES_texture_half_float
176 RA32F, // OES_texture_float
177 RG8,
178 RG16F,
179 RG32F,
180 // 3-channel formats
181 RGB8,
182 RGB565,
183 RGB11F11F10F,
184 RGB16F, // OES_texture_half_float
185 RGB32F, // OES_texture_float
186 // 4-channel formats
187 RGBA8,
188 RGBA5551,
189 RGBA4444,
190 RGBA16F, // OES_texture_half_float
191 RGBA32F, // OES_texture_float
192 // DOM element source only formats.
193 RGBX8,
194 BGRX8,
195 BGRA8
198 enum class WebGLTexImageFunc : uint8_t {
199 TexImage,
200 TexSubImage,
201 CopyTexImage,
202 CopyTexSubImage,
203 CompTexImage,
204 CompTexSubImage,
207 enum class WebGLTexDimensions : uint8_t { Tex2D, Tex3D };
209 // Please keep extensions in alphabetic order.
210 enum class WebGLExtensionID : uint8_t {
211 ANGLE_instanced_arrays,
212 EXT_blend_minmax,
213 EXT_color_buffer_float,
214 EXT_color_buffer_half_float,
215 EXT_disjoint_timer_query,
216 EXT_float_blend,
217 EXT_frag_depth,
218 EXT_shader_texture_lod,
219 EXT_sRGB,
220 EXT_texture_compression_bptc,
221 EXT_texture_compression_rgtc,
222 EXT_texture_filter_anisotropic,
223 EXT_texture_norm16,
224 MOZ_debug,
225 OES_draw_buffers_indexed,
226 OES_element_index_uint,
227 OES_fbo_render_mipmap,
228 OES_standard_derivatives,
229 OES_texture_float,
230 OES_texture_float_linear,
231 OES_texture_half_float,
232 OES_texture_half_float_linear,
233 OES_vertex_array_object,
234 OVR_multiview2,
235 WEBGL_color_buffer_float,
236 WEBGL_compressed_texture_astc,
237 WEBGL_compressed_texture_etc,
238 WEBGL_compressed_texture_etc1,
239 WEBGL_compressed_texture_pvrtc,
240 WEBGL_compressed_texture_s3tc,
241 WEBGL_compressed_texture_s3tc_srgb,
242 WEBGL_debug_renderer_info,
243 WEBGL_debug_shaders,
244 WEBGL_depth_texture,
245 WEBGL_draw_buffers,
246 WEBGL_explicit_present,
247 WEBGL_lose_context,
248 WEBGL_provoking_vertex,
252 class UniqueBuffer final {
253 // Like UniquePtr<>, but for void* and malloc/calloc/free.
254 void* mBuffer = nullptr;
256 public:
257 static inline UniqueBuffer Take(void* buffer) {
258 UniqueBuffer ret;
259 ret.mBuffer = buffer;
260 return ret;
263 UniqueBuffer() = default;
265 ~UniqueBuffer() { reset(); }
267 UniqueBuffer(UniqueBuffer&& rhs) { *this = std::move(rhs); }
269 UniqueBuffer& operator=(UniqueBuffer&& rhs) {
270 reset();
271 this->mBuffer = rhs.mBuffer;
272 rhs.mBuffer = nullptr;
273 return *this;
276 explicit operator bool() const { return bool(mBuffer); }
278 void* get() const { return mBuffer; }
280 void reset() {
281 // Believe it or not, when `free` unconditional, it was showing up
282 // in profiles, nearly 20% of time spent in MethodDispatcther<UniformData>
283 // on Aquarium.
284 if (mBuffer) {
285 free(mBuffer);
286 mBuffer = nullptr;
291 namespace webgl {
292 struct FormatUsageInfo;
294 static constexpr GLenum kErrorPerfWarning = 0x10001;
296 struct SampleableInfo final {
297 const char* incompleteReason = nullptr;
298 uint32_t levels = 0;
299 const webgl::FormatUsageInfo* usage = nullptr;
300 bool isDepthTexCompare = false;
302 bool IsComplete() const { return bool(levels); }
305 enum class AttribBaseType : uint8_t {
306 Boolean, // Can convert from anything.
307 Float, // Also includes NormU?Int
308 Int,
309 Uint,
311 webgl::AttribBaseType ToAttribBaseType(GLenum);
312 const char* ToString(AttribBaseType);
314 enum class UniformBaseType : uint8_t {
315 Float,
316 Int,
317 Uint,
319 const char* ToString(UniformBaseType);
321 using ObjectId = uint64_t;
323 enum class BufferKind : uint8_t {
324 Undefined,
325 Index,
326 NonIndex,
329 } // namespace webgl
331 // -
333 struct FloatOrInt final // For TexParameter[fi] and friends.
335 bool isFloat = false;
336 uint8_t padding[3] = {};
337 GLfloat f = 0;
338 GLint i = 0;
340 explicit FloatOrInt(GLint x = 0) : isFloat(false), f(x), i(x) {}
342 explicit FloatOrInt(GLfloat x) : isFloat(true), f(x), i(roundf(x)) {}
344 auto MutTiedFields() { return std::tie(isFloat, padding, f, i); }
347 // -
349 struct WebGLContextOptions final {
350 bool alpha = true;
351 bool depth = true;
352 bool stencil = false;
353 bool premultipliedAlpha = true;
355 bool antialias = true;
356 bool preserveDrawingBuffer = false;
357 bool failIfMajorPerformanceCaveat = false;
358 bool xrCompatible = false;
360 dom::WebGLPowerPreference powerPreference =
361 dom::WebGLPowerPreference::Default;
362 bool ignoreColorSpace = true;
363 dom::PredefinedColorSpace colorSpace = dom::PredefinedColorSpace::Srgb;
364 bool shouldResistFingerprinting = true;
366 bool enableDebugRendererInfo = false;
368 auto MutTiedFields() {
369 // clang-format off
370 return std::tie(
371 alpha,
372 depth,
373 stencil,
374 premultipliedAlpha,
376 antialias,
377 preserveDrawingBuffer,
378 failIfMajorPerformanceCaveat,
379 xrCompatible,
381 powerPreference,
382 colorSpace,
383 ignoreColorSpace,
384 shouldResistFingerprinting,
386 enableDebugRendererInfo);
387 // clang-format on
390 // -
392 WebGLContextOptions();
393 WebGLContextOptions(const WebGLContextOptions&) = default;
395 using Self = WebGLContextOptions;
396 friend bool operator==(const Self& a, const Self& b) {
397 return TiedFields(a) == TiedFields(b);
399 friend bool operator!=(const Self& a, const Self& b) { return !(a == b); }
402 namespace gfx {
404 inline ColorSpace2 ToColorSpace2(const dom::PredefinedColorSpace cs) {
405 switch (cs) {
406 case dom::PredefinedColorSpace::Srgb:
407 return ColorSpace2::SRGB;
408 case dom::PredefinedColorSpace::Display_p3:
409 return ColorSpace2::DISPLAY_P3;
410 case dom::PredefinedColorSpace::EndGuard_:
411 break;
413 MOZ_CRASH("Exhaustive switch");
416 } // namespace gfx
418 // -
420 template <typename _T>
421 struct avec2 {
422 using T = _T;
424 T x = T();
425 T y = T();
427 auto MutTiedFields() { return std::tie(x, y); }
429 template <typename U, typename V>
430 static Maybe<avec2> From(const U _x, const V _y) {
431 const auto x = CheckedInt<T>(_x);
432 const auto y = CheckedInt<T>(_y);
433 if (!x.isValid() || !y.isValid()) return {};
434 return Some(avec2(x.value(), y.value()));
437 template <typename U>
438 static auto From(const U& val) {
439 return From(val.x, val.y);
441 template <typename U>
442 static auto FromSize(const U& val) {
443 return From(val.width, val.height);
446 avec2() = default;
447 avec2(const T _x, const T _y) : x(_x), y(_y) {}
449 bool operator==(const avec2& rhs) const { return x == rhs.x && y == rhs.y; }
450 bool operator!=(const avec2& rhs) const { return !(*this == rhs); }
452 #define _(OP) \
453 avec2 operator OP(const avec2& rhs) const { \
454 return {x OP rhs.x, y OP rhs.y}; \
456 avec2 operator OP(const T rhs) const { return {x OP rhs, y OP rhs}; }
458 _(+)
459 _(-)
460 _(*)
461 _(/)
463 #undef _
465 avec2 Clamp(const avec2& min, const avec2& max) const {
466 return {mozilla::Clamp(x, min.x, max.x), mozilla::Clamp(y, min.y, max.y)};
469 // mozilla::Clamp doesn't work on floats, so be clear that this is a min+max
470 // helper.
471 avec2 ClampMinMax(const avec2& min, const avec2& max) const {
472 const auto ClampScalar = [](const T v, const T min, const T max) {
473 return std::max(min, std::min(v, max));
475 return {ClampScalar(x, min.x, max.x), ClampScalar(y, min.y, max.y)};
478 template <typename U>
479 U StaticCast() const {
480 return {static_cast<typename U::T>(x), static_cast<typename U::T>(y)};
484 template <typename T>
485 avec2<T> MinExtents(const avec2<T>& a, const avec2<T>& b) {
486 return {std::min(a.x, b.x), std::min(a.y, b.y)};
489 template <typename T>
490 avec2<T> MaxExtents(const avec2<T>& a, const avec2<T>& b) {
491 return {std::max(a.x, b.x), std::max(a.y, b.y)};
494 // -
496 template <typename _T>
497 struct avec3 {
498 using T = _T;
500 T x = T();
501 T y = T();
502 T z = T();
504 auto MutTiedFields() { return std::tie(x, y, z); }
506 template <typename U, typename V>
507 static Maybe<avec3> From(const U _x, const V _y, const V _z) {
508 const auto x = CheckedInt<T>(_x);
509 const auto y = CheckedInt<T>(_y);
510 const auto z = CheckedInt<T>(_z);
511 if (!x.isValid() || !y.isValid() || !z.isValid()) return {};
512 return Some(avec3(x.value(), y.value(), z.value()));
515 template <typename U>
516 static auto From(const U& val) {
517 return From(val.x, val.y, val.z);
520 avec3() = default;
521 avec3(const T _x, const T _y, const T _z) : x(_x), y(_y), z(_z) {}
523 bool operator==(const avec3& rhs) const {
524 return x == rhs.x && y == rhs.y && z == rhs.z;
526 bool operator!=(const avec3& rhs) const { return !(*this == rhs); }
529 using ivec2 = avec2<int32_t>;
530 using ivec3 = avec3<int32_t>;
531 using uvec2 = avec2<uint32_t>;
532 using uvec3 = avec3<uint32_t>;
534 inline ivec2 AsVec(const gfx::IntSize& s) { return {s.width, s.height}; }
536 // -
538 namespace webgl {
540 struct PackingInfo final {
541 GLenum format = 0;
542 GLenum type = 0;
544 auto MutTiedFields() { return std::tie(format, type); }
546 using Self = PackingInfo;
547 friend bool operator<(const Self& a, const Self& b) {
548 return TiedFields(a) < TiedFields(b);
550 friend bool operator==(const Self& a, const Self& b) {
551 return TiedFields(a) == TiedFields(b);
554 template <class T>
555 friend T& operator<<(T& s, const PackingInfo& pi) {
556 s << "PackingInfo{format: " << EnumString(pi.format)
557 << ", type: " << EnumString(pi.type) << "}";
558 return s;
562 struct DriverUnpackInfo final {
563 GLenum internalFormat = 0;
564 GLenum unpackFormat = 0;
565 GLenum unpackType = 0;
567 PackingInfo ToPacking() const { return {unpackFormat, unpackType}; }
570 // -
572 template <typename E>
573 class EnumMask {
574 public:
575 uint64_t mBits = 0;
577 private:
578 struct BitRef final {
579 EnumMask& bits;
580 const uint64_t mask;
582 explicit operator bool() const { return bits.mBits & mask; }
584 auto& operator=(const bool val) {
585 if (val) {
586 bits.mBits |= mask;
587 } else {
588 bits.mBits &= ~mask;
590 return *this;
594 uint64_t Mask(const E i) const {
595 return uint64_t{1} << static_cast<uint64_t>(i);
598 public:
599 BitRef operator[](const E i) { return {*this, Mask(i)}; }
600 bool operator[](const E i) const { return mBits & Mask(i); }
603 class ExtensionBits : public EnumMask<WebGLExtensionID> {};
605 // -
607 enum class ContextLossReason : uint8_t {
608 None,
609 Manual,
610 Guilty,
613 inline bool ReadContextLossReason(const uint8_t val,
614 ContextLossReason* const out) {
615 if (val > static_cast<uint8_t>(ContextLossReason::Guilty)) {
616 return false;
618 *out = static_cast<ContextLossReason>(val);
619 return true;
622 // -
624 struct InitContextDesc final {
625 bool isWebgl2 = false;
626 bool resistFingerprinting = false;
627 uvec2 size = {};
628 WebGLContextOptions options;
629 uint32_t principalKey = 0;
632 constexpr uint32_t kMaxTransformFeedbackSeparateAttribs = 4;
634 struct Limits final {
635 ExtensionBits supportedExtensions;
637 // WebGL 1
638 uint32_t maxTexUnits = 0;
639 uint32_t maxTex2dSize = 0;
640 uint32_t maxTexCubeSize = 0;
641 uint32_t maxVertexAttribs = 0;
642 uint32_t maxViewportDim = 0;
643 std::array<float, 2> pointSizeRange = {{1, 1}};
644 std::array<float, 2> lineWidthRange = {{1, 1}};
646 // WebGL 2
647 uint32_t maxTexArrayLayers = 0;
648 uint32_t maxTex3dSize = 0;
649 uint32_t maxUniformBufferBindings = 0;
650 uint32_t uniformBufferOffsetAlignment = 0;
652 // Exts
653 bool astcHdr = false;
654 uint32_t maxColorDrawBuffers = 1;
655 uint64_t queryCounterBitsTimeElapsed = 0;
656 uint64_t queryCounterBitsTimestamp = 0;
657 uint32_t maxMultiviewLayers = 0;
660 struct InitContextResult final {
661 std::string error;
662 WebGLContextOptions options;
663 webgl::Limits limits;
664 EnumMask<layers::SurfaceDescriptor::Type> uploadableSdTypes;
665 gl::GLVendor vendor;
668 // -
670 struct ErrorInfo final {
671 GLenum type;
672 std::string info;
675 struct ShaderPrecisionFormat final {
676 GLint rangeMin = 0;
677 GLint rangeMax = 0;
678 GLint precision = 0;
681 // -
683 enum class LossStatus {
684 Ready,
686 Lost,
687 LostForever,
688 LostManually,
691 // -
693 struct CompileResult final {
694 bool pending = true;
695 nsCString log;
696 nsCString translatedSource;
697 bool success = false;
700 // -
702 struct OpaqueFramebufferOptions final {
703 bool depthStencil = true;
704 bool antialias = true;
705 uint32_t width = 0;
706 uint32_t height = 0;
709 // -
711 struct SwapChainOptions final {
712 layers::RemoteTextureId remoteTextureId;
713 layers::RemoteTextureOwnerId remoteTextureOwnerId;
714 bool bgra = false;
715 bool forceAsyncPresent = false;
716 // Pad to sizeof(u64):
717 uint16_t padding1 = 0;
718 uint32_t padding2 = 0;
720 auto MutTiedFields() {
721 return std::tie(remoteTextureId, remoteTextureOwnerId, bgra,
722 forceAsyncPresent, padding1, padding2);
726 // -
728 struct ActiveInfo {
729 GLenum elemType = 0; // `type`
730 uint32_t elemCount = 0; // `size`
731 std::string name;
734 struct ActiveAttribInfo final : public ActiveInfo {
735 int32_t location = -1;
736 AttribBaseType baseType = AttribBaseType::Float;
739 struct ActiveUniformInfo final : public ActiveInfo {
740 std::unordered_map<uint32_t, uint32_t>
741 locByIndex; // Uniform array locations are sparse.
742 int32_t block_index = -1;
743 int32_t block_offset = -1; // In block, offset.
744 int32_t block_arrayStride = -1;
745 int32_t block_matrixStride = -1;
746 bool block_isRowMajor = false;
749 struct ActiveUniformBlockInfo final {
750 std::string name;
751 // BLOCK_BINDING is dynamic state
752 uint32_t dataSize = 0;
753 std::vector<uint32_t> activeUniformIndices;
754 bool referencedByVertexShader = false;
755 bool referencedByFragmentShader = false;
758 struct LinkActiveInfo final {
759 std::vector<ActiveAttribInfo> activeAttribs;
760 std::vector<ActiveUniformInfo> activeUniforms;
761 std::vector<ActiveUniformBlockInfo> activeUniformBlocks;
762 std::vector<ActiveInfo> activeTfVaryings;
765 struct LinkResult final {
766 bool pending = true;
767 nsCString log;
768 bool success = false;
769 LinkActiveInfo active;
770 GLenum tfBufferMode = 0;
773 // -
775 /// 4x32-bit primitives, with a type tag.
776 struct TypedQuad final {
777 alignas(alignof(float)) std::array<uint8_t, 4 * sizeof(float)> data = {};
778 webgl::AttribBaseType type = webgl::AttribBaseType::Float;
779 uint8_t padding[3] = {};
781 constexpr auto MutTiedFields() { return std::tie(data, type, padding); }
784 /// [1-16]x32-bit primitives, with a type tag.
785 struct GetUniformData final {
786 alignas(alignof(float)) uint8_t data[4 * 4 * sizeof(float)] = {};
787 GLenum type = 0;
790 struct FrontBufferSnapshotIpc final {
791 uvec2 surfSize = {};
792 Maybe<mozilla::ipc::Shmem> shmem = {};
795 struct ReadPixelsResult {
796 gfx::IntRect subrect = {};
797 size_t byteStride = 0;
800 struct ReadPixelsResultIpc final : public ReadPixelsResult {
801 Maybe<mozilla::ipc::Shmem> shmem = {};
804 struct VertAttribPointerDesc final {
805 bool intFunc = false;
806 uint8_t channels = 4;
807 bool normalized = false;
808 uint8_t byteStrideOrZero = 0;
809 GLenum type = LOCAL_GL_FLOAT;
810 uint64_t byteOffset = 0;
812 auto MutTiedFields() {
813 return std::tie(intFunc, channels, normalized, byteStrideOrZero, type,
814 byteOffset);
818 struct VertAttribPointerCalculated final {
819 uint8_t byteSize = 4 * 4;
820 uint8_t byteStride = 4 * 4; // at-most 255
821 webgl::AttribBaseType baseType = webgl::AttribBaseType::Float;
824 } // namespace webgl
827 * Represents a block of memory that it may or may not own. The
828 * inner data type must be trivially copyable by memcpy.
830 template <typename T = uint8_t>
831 class RawBuffer final {
832 const T* mBegin = nullptr;
833 size_t mLen = 0;
834 UniqueBuffer mOwned;
836 public:
837 using ElementType = T;
840 * If aTakeData is true, RawBuffer will delete[] the memory when destroyed.
842 explicit RawBuffer(const Range<const T>& data, UniqueBuffer&& owned = {})
843 : mBegin(data.begin().get()),
844 mLen(data.length()),
845 mOwned(std::move(owned)) {}
847 explicit RawBuffer(const size_t len) : mLen(len) {}
849 ~RawBuffer() = default;
851 Range<const T> Data() const { return {mBegin, mLen}; }
852 const auto& begin() const { return mBegin; }
853 const auto& size() const { return mLen; }
855 void Shrink(const size_t newLen) {
856 if (mLen <= newLen) return;
857 mLen = newLen;
860 RawBuffer() = default;
862 RawBuffer(const RawBuffer&) = delete;
863 RawBuffer& operator=(const RawBuffer&) = delete;
865 RawBuffer(RawBuffer&&) = default;
866 RawBuffer& operator=(RawBuffer&&) = default;
869 template <class T>
870 inline Range<T> ShmemRange(const mozilla::ipc::Shmem& shmem) {
871 return {shmem.get<T>(), shmem.Size<T>()};
874 // -
876 template <typename C, typename K>
877 inline auto MaybeFind(C& container, const K& key)
878 -> decltype(&(container.find(key)->second)) {
879 const auto itr = container.find(key);
880 if (itr == container.end()) return nullptr;
881 return &(itr->second);
884 template <typename C, typename K>
885 inline typename C::mapped_type Find(
886 const C& container, const K& key,
887 const typename C::mapped_type notFound = {}) {
888 const auto itr = container.find(key);
889 if (itr == container.end()) return notFound;
890 return itr->second;
893 // -
895 template <typename T, typename U>
896 inline Maybe<T> MaybeAs(const U val) {
897 const auto checked = CheckedInt<T>(val);
898 if (!checked.isValid()) return {};
899 return Some(checked.value());
902 // -
904 inline GLenum IsTexImageTarget(const GLenum imageTarget) {
905 switch (imageTarget) {
906 case LOCAL_GL_TEXTURE_2D:
907 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
908 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
909 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
910 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
911 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
912 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
913 case LOCAL_GL_TEXTURE_3D:
914 case LOCAL_GL_TEXTURE_2D_ARRAY:
915 return true;
917 return false;
920 inline GLenum ImageToTexTarget(const GLenum imageTarget) {
921 switch (imageTarget) {
922 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
923 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
924 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
925 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
926 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
927 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
928 return LOCAL_GL_TEXTURE_CUBE_MAP;
930 if (IsTexImageTarget(imageTarget)) {
931 return imageTarget;
933 return 0;
936 inline bool IsTexTarget3D(const GLenum texTarget) {
937 switch (texTarget) {
938 case LOCAL_GL_TEXTURE_2D_ARRAY:
939 case LOCAL_GL_TEXTURE_3D:
940 return true;
942 default:
943 return false;
947 // -
949 namespace dom {
950 class Element;
951 class ImageBitmap;
952 class ImageData;
953 class OffscreenCanvas;
954 } // namespace dom
956 struct TexImageSource {
957 const dom::ArrayBufferView* mView = nullptr;
958 GLuint mViewElemOffset = 0;
959 GLuint mViewElemLengthOverride = 0;
961 const WebGLintptr* mPboOffset = nullptr;
963 const dom::ImageBitmap* mImageBitmap = nullptr;
964 const dom::ImageData* mImageData = nullptr;
966 const dom::OffscreenCanvas* mOffscreenCanvas = nullptr;
968 const dom::Element* mDomElem = nullptr;
969 ErrorResult* mOut_error = nullptr;
972 namespace webgl {
974 template <class DerivedT>
975 struct DeriveNotEq {
976 bool operator!=(const DerivedT& rhs) const {
977 const auto self = reinterpret_cast<const DerivedT*>(this);
978 return !(*self == rhs);
982 struct PixelPackingState : public DeriveNotEq<PixelPackingState> {
983 uint32_t alignmentInTypeElems = 4; // ALIGNMENT isn't naive byte alignment!
984 uint32_t rowLength = 0;
985 uint32_t imageHeight = 0;
986 uint32_t skipPixels = 0;
987 uint32_t skipRows = 0;
988 uint32_t skipImages = 0;
990 auto MutTiedFields() {
991 return std::tie(alignmentInTypeElems, rowLength, imageHeight, skipPixels,
992 skipRows, skipImages);
995 using Self = PixelPackingState;
996 friend bool operator==(const Self& a, const Self& b) {
997 return TiedFields(a) == TiedFields(b);
1000 static void AssertDefaultUnpack(gl::GLContext& gl, const bool isWebgl2) {
1001 PixelPackingState{}.AssertCurrentUnpack(gl, isWebgl2);
1004 void ApplyUnpack(gl::GLContext&, bool isWebgl2,
1005 const uvec3& uploadSize) const;
1006 bool AssertCurrentUnpack(gl::GLContext&, bool isWebgl2) const;
1009 struct PixelUnpackStateWebgl final : public PixelPackingState {
1010 GLenum colorspaceConversion =
1011 dom::WebGLRenderingContext_Binding::BROWSER_DEFAULT_WEBGL;
1012 bool flipY = false;
1013 bool premultiplyAlpha = false;
1014 bool requireFastPath = false;
1015 uint8_t padding = {};
1017 auto MutTiedFields() {
1018 return std::tuple_cat(PixelPackingState::MutTiedFields(),
1019 std::tie(colorspaceConversion, flipY,
1020 premultiplyAlpha, requireFastPath, padding));
1024 struct ExplicitPixelPackingState final {
1025 struct Metrics final {
1026 uvec3 usedSize = {};
1027 size_t bytesPerPixel = 0;
1029 // (srcStrideAndRowOverride.x, otherwise ROW_LENGTH != 0, otherwise size.x)
1030 // ...aligned to ALIGNMENT.
1031 size_t bytesPerRowStride = 0;
1033 // structuredSrcSize.y, otherwise IMAGE_HEIGHT*(SKIP_IMAGES+size.z)
1034 size_t totalRows = 0;
1036 // This ensures that no one else needs to do CheckedInt math.
1037 size_t totalBytesUsed = 0;
1038 size_t totalBytesStrided = 0;
1041 // It's so important that these aren't modified once evaluated.
1042 const PixelPackingState state;
1043 const Metrics metrics;
1045 static Result<ExplicitPixelPackingState, std::string> ForUseWith(
1046 const PixelPackingState&, GLenum target, const uvec3& subrectSize,
1047 const webgl::PackingInfo&, const Maybe<size_t> bytesPerRowStrideOverride);
1050 struct ReadPixelsDesc final {
1051 ivec2 srcOffset;
1052 uvec2 size;
1053 PackingInfo pi = {LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE};
1054 PixelPackingState packState;
1056 auto MutTiedFields() { return std::tie(srcOffset, size, pi, packState); }
1059 } // namespace webgl
1061 namespace webgl {
1063 struct TexUnpackBlobDesc final {
1064 GLenum imageTarget = LOCAL_GL_TEXTURE_2D;
1065 uvec3 size;
1066 gfxAlphaType srcAlphaType = gfxAlphaType::NonPremult;
1068 Maybe<RawBuffer<>> cpuData;
1069 Maybe<uint64_t> pboOffset;
1071 Maybe<uvec2> structuredSrcSize;
1072 RefPtr<layers::Image> image;
1073 Maybe<layers::SurfaceDescriptor> sd;
1074 RefPtr<gfx::DataSourceSurface> dataSurf;
1076 webgl::PixelUnpackStateWebgl unpacking;
1077 bool applyUnpackTransforms = true;
1079 // -
1081 auto ExplicitUnpacking(const webgl::PackingInfo& pi,
1082 const Maybe<size_t> bytesPerRowStrideOverride) const {
1083 return ExplicitPixelPackingState::ForUseWith(this->unpacking,
1084 this->imageTarget, this->size,
1085 pi, bytesPerRowStrideOverride);
1088 void Shrink(const webgl::PackingInfo&);
1091 } // namespace webgl
1093 // ---------------------------------------
1094 // MakeRange
1096 template <typename T, size_t N>
1097 inline Range<const T> MakeRange(T (&arr)[N]) {
1098 return {arr, N};
1101 template <typename T>
1102 inline Range<const T> MakeRange(const dom::Sequence<T>& seq) {
1103 return {seq.Elements(), seq.Length()};
1106 template <typename T>
1107 inline Range<const T> MakeRange(const RawBuffer<T>& from) {
1108 return from.Data();
1111 // abv = ArrayBufferView
1112 template <typename T>
1113 inline auto MakeRangeAbv(const T& abv)
1114 -> Range<const typename T::element_type> {
1115 abv.ComputeState();
1116 return {abv.Data(), abv.Length()};
1119 // -
1121 constexpr auto kUniversalAlignment = alignof(std::max_align_t);
1123 template <typename T>
1124 inline size_t AlignmentOffset(const size_t alignment, const T posOrPtr) {
1125 MOZ_ASSERT(alignment);
1126 const auto begin = reinterpret_cast<uintptr_t>(posOrPtr);
1127 const auto wholeMultiples = (begin + (alignment - 1)) / alignment;
1128 const auto aligned = wholeMultiples * alignment;
1129 return aligned - begin;
1132 template <typename T>
1133 inline size_t ByteSize(const Range<T>& range) {
1134 return range.length() * sizeof(T);
1137 Maybe<Range<const uint8_t>> GetRangeFromView(const dom::ArrayBufferView& view,
1138 GLuint elemOffset,
1139 GLuint elemCountOverride);
1141 // -
1143 template <typename T>
1144 RawBuffer<T> RawBufferView(const Range<T>& range) {
1145 return RawBuffer<T>{range};
1148 // -
1150 Maybe<webgl::ErrorInfo> CheckBindBufferRange(
1151 const GLenum target, const GLuint index, const bool isBuffer,
1152 const uint64_t offset, const uint64_t size, const webgl::Limits& limits);
1154 Maybe<webgl::ErrorInfo> CheckFramebufferAttach(const GLenum bindImageTarget,
1155 const GLenum curTexTarget,
1156 const uint32_t mipLevel,
1157 const uint32_t zLayerBase,
1158 const uint32_t zLayerCount,
1159 const webgl::Limits& limits);
1161 Result<webgl::VertAttribPointerCalculated, webgl::ErrorInfo>
1162 CheckVertexAttribPointer(bool isWebgl2, const webgl::VertAttribPointerDesc&);
1164 uint8_t ElemTypeComponents(GLenum elemType);
1166 inline std::string ToString(const nsACString& text) {
1167 return {text.BeginReading(), text.Length()};
1170 inline void Memcpy(const RangedPtr<uint8_t>& destBytes,
1171 const RangedPtr<const uint8_t>& srcBytes,
1172 const size_t byteSize) {
1173 // Trigger range asserts
1174 (void)(srcBytes + byteSize);
1175 (void)(destBytes + byteSize);
1177 memcpy(destBytes.get(), srcBytes.get(), byteSize);
1180 template <class T, class U>
1181 inline void Memcpy(const Range<T>* const destRange,
1182 const RangedPtr<U>& srcBegin) {
1183 Memcpy(destRange->begin(), srcBegin, destRange->length());
1185 template <class T, class U>
1186 inline void Memcpy(const RangedPtr<T>* const destBegin,
1187 const Range<U>& srcRange) {
1188 Memcpy(destBegin, srcRange->begin(), srcRange->length());
1191 // -
1193 inline bool StartsWith(const std::string_view str,
1194 const std::string_view part) {
1195 return str.find(part) == 0;
1198 // -
1200 namespace webgl {
1202 // In theory, this number can be unbounded based on the driver. However, no
1203 // driver appears to expose more than 8. We might as well stop there too, for
1204 // now.
1205 // (http://opengl.gpuinfo.org/gl_stats_caps_single.php?listreportsbycap=GL_MAX_COLOR_ATTACHMENTS)
1206 inline constexpr size_t kMaxDrawBuffers = 8;
1208 union UniformDataVal {
1209 float f32;
1210 int32_t i32;
1211 uint32_t u32;
1214 enum class ProvokingVertex : GLenum {
1215 FirstVertex = LOCAL_GL_FIRST_VERTEX_CONVENTION,
1216 LastVertex = LOCAL_GL_LAST_VERTEX_CONVENTION,
1218 inline constexpr bool IsEnumCase(const ProvokingVertex raw) {
1219 switch (raw) {
1220 case ProvokingVertex::FirstVertex:
1221 case ProvokingVertex::LastVertex:
1222 return true;
1224 return false;
1227 template <class E>
1228 inline constexpr std::optional<E> AsEnumCase(
1229 const std::underlying_type_t<E> raw) {
1230 const auto ret = static_cast<E>(raw);
1231 if (!IsEnumCase(ret)) return {};
1232 return ret;
1235 } // namespace webgl
1237 } // namespace mozilla
1239 #endif