Bug 1892041 - Part 1: Update test262 features. r=spidermonkey-reviewers,dminor
[gecko.git] / dom / canvas / WebGLTypes.h
blobf5f78e98cb9e57d50fa2828ede0fb73f93bb8e56
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 "GLContextTypes.h"
18 #include "GLDefs.h"
19 #include "ImageContainer.h"
20 #include "mozilla/Casting.h"
21 #include "mozilla/CheckedInt.h"
22 #include "mozilla/EnumTypeTraits.h"
23 #include "mozilla/MathAlgorithms.h"
24 #include "mozilla/Range.h"
25 #include "mozilla/RefCounted.h"
26 #include "mozilla/Result.h"
27 #include "mozilla/ResultVariant.h"
28 #include "mozilla/Span.h"
29 #include "mozilla/TypedEnumBits.h"
30 #include "mozilla/gfx/2D.h"
31 #include "mozilla/gfx/BuildConstants.h"
32 #include "mozilla/gfx/Logging.h"
33 #include "mozilla/gfx/Point.h"
34 #include "mozilla/gfx/Rect.h"
35 #include "mozilla/ipc/Shmem.h"
36 #include "mozilla/layers/LayersSurfaces.h"
37 #include "gfxTypes.h"
39 #include "nsTArray.h"
40 #include "nsString.h"
41 #include "mozilla/dom/WebGLRenderingContextBinding.h"
42 #include "mozilla/ipc/SharedMemoryBasic.h"
43 #include "TiedFields.h"
45 // Manual reflection of WebIDL typedefs that are different from their
46 // OpenGL counterparts.
47 using WebGLsizeiptr = int64_t;
48 using WebGLintptr = int64_t;
49 using WebGLboolean = bool;
51 // -
53 namespace mozilla {
54 namespace gl {
55 class GLContext; // This is going to be needed a lot.
56 } // namespace gl
58 // -
59 // Prevent implicit conversions into calloc and malloc. (mozilla namespace
60 // only!)
62 template <typename DestT>
63 class ForbidNarrowing final {
64 DestT mVal;
66 public:
67 template <typename SrcT>
68 MOZ_IMPLICIT ForbidNarrowing(SrcT val) : mVal(val) {
69 static_assert(
70 std::numeric_limits<SrcT>::min() >= std::numeric_limits<DestT>::min(),
71 "SrcT must be narrower than DestT.");
72 static_assert(
73 std::numeric_limits<SrcT>::max() <= std::numeric_limits<DestT>::max(),
74 "SrcT must be narrower than DestT.");
77 explicit operator DestT() const { return mVal; }
80 inline void* malloc(const ForbidNarrowing<size_t> s) {
81 return ::malloc(size_t(s));
84 inline void* calloc(const ForbidNarrowing<size_t> n,
85 const ForbidNarrowing<size_t> size) {
86 return ::calloc(size_t(n), size_t(size));
89 // -
91 // TODO: Remove this now-mere-alias.
92 template <typename From>
93 inline auto AutoAssertCast(const From val) {
94 return LazyAssertedCast(val);
97 const char* GetEnumName(GLenum val, const char* defaultRet = "<unknown>");
98 std::string EnumString(GLenum val);
100 namespace webgl {
101 template <typename T>
102 struct QueueParamTraits;
103 class TexUnpackBytes;
104 class TexUnpackImage;
105 class TexUnpackSurface;
106 } // namespace webgl
108 class ClientWebGLContext;
109 struct WebGLTexPboOffset;
110 class WebGLTexture;
111 class WebGLBuffer;
112 class WebGLFramebuffer;
113 class WebGLProgram;
114 class WebGLQuery;
115 class WebGLRenderbuffer;
116 class WebGLSampler;
117 class WebGLShader;
118 class WebGLSync;
119 class WebGLTexture;
120 class WebGLTransformFeedback;
121 class WebGLVertexArray;
123 // -
125 class VRefCounted : public RefCounted<VRefCounted> {
126 public:
127 virtual ~VRefCounted() = default;
129 #ifdef MOZ_REFCOUNTED_LEAK_CHECKING
130 virtual const char* typeName() const = 0;
131 virtual size_t typeSize() const = 0;
132 #endif
135 // -
138 * Implementing WebGL (or OpenGL ES 2.0) on top of desktop OpenGL requires
139 * emulating the vertex attrib 0 array when it's not enabled. Indeed,
140 * OpenGL ES 2.0 allows drawing without vertex attrib 0 array enabled, but
141 * desktop OpenGL does not allow that.
143 enum class WebGLVertexAttrib0Status : uint8_t {
144 Default, // default status - no emulation needed
145 EmulatedUninitializedArray, // need an artificial attrib 0 array, but
146 // contents may be left uninitialized
147 EmulatedInitializedArray // need an artificial attrib 0 array, and contents
148 // must be initialized
152 * The formats that may participate, either as source or destination formats,
153 * in WebGL texture conversions. This includes:
154 * - all the formats accepted by WebGL.texImage2D, e.g. RGBA4444
155 * - additional formats provided by extensions, e.g. RGB32F
156 * - additional source formats, depending on browser details, used when
157 * uploading textures from DOM elements. See gfxImageSurface::Format().
159 enum class WebGLTexelFormat : uint8_t {
160 // returned by SurfaceFromElementResultToImageSurface to indicate absence of
161 // image data
162 None,
163 // common value for formats for which format conversions are not supported
164 FormatNotSupportingAnyConversion,
165 // dummy pseudo-format meaning "use the other format".
166 // For example, if SrcFormat=Auto and DstFormat=RGB8, then the source
167 // is implicitly treated as being RGB8 itself.
168 Auto,
169 // 1-channel formats
171 A16F, // OES_texture_half_float
172 A32F, // OES_texture_float
174 R16F, // OES_texture_half_float
175 R32F, // OES_texture_float
176 // 2-channel formats
177 RA8,
178 RA16F, // OES_texture_half_float
179 RA32F, // OES_texture_float
180 RG8,
181 RG16F,
182 RG32F,
183 // 3-channel formats
184 RGB8,
185 RGB565,
186 RGB11F11F10F,
187 RGB16F, // OES_texture_half_float
188 RGB32F, // OES_texture_float
189 // 4-channel formats
190 RGBA8,
191 RGBA5551,
192 RGBA4444,
193 RGBA16F, // OES_texture_half_float
194 RGBA32F, // OES_texture_float
195 // DOM element source only formats.
196 RGBX8,
197 BGRX8,
198 BGRA8
201 enum class WebGLTexImageFunc : uint8_t {
202 TexImage,
203 TexSubImage,
204 CopyTexImage,
205 CopyTexSubImage,
206 CompTexImage,
207 CompTexSubImage,
210 enum class WebGLTexDimensions : uint8_t { Tex2D, Tex3D };
212 // Please keep extensions in alphabetic order.
213 enum class WebGLExtensionID : uint8_t {
214 ANGLE_instanced_arrays,
215 EXT_blend_minmax,
216 EXT_color_buffer_float,
217 EXT_color_buffer_half_float,
218 EXT_disjoint_timer_query,
219 EXT_float_blend,
220 EXT_frag_depth,
221 EXT_shader_texture_lod,
222 EXT_sRGB,
223 EXT_texture_compression_bptc,
224 EXT_texture_compression_rgtc,
225 EXT_texture_filter_anisotropic,
226 EXT_texture_norm16,
227 MOZ_debug,
228 OES_draw_buffers_indexed,
229 OES_element_index_uint,
230 OES_fbo_render_mipmap,
231 OES_standard_derivatives,
232 OES_texture_float,
233 OES_texture_float_linear,
234 OES_texture_half_float,
235 OES_texture_half_float_linear,
236 OES_vertex_array_object,
237 OVR_multiview2,
238 WEBGL_color_buffer_float,
239 WEBGL_compressed_texture_astc,
240 WEBGL_compressed_texture_etc,
241 WEBGL_compressed_texture_etc1,
242 WEBGL_compressed_texture_pvrtc,
243 WEBGL_compressed_texture_s3tc,
244 WEBGL_compressed_texture_s3tc_srgb,
245 WEBGL_debug_renderer_info,
246 WEBGL_debug_shaders,
247 WEBGL_depth_texture,
248 WEBGL_draw_buffers,
249 WEBGL_explicit_present,
250 WEBGL_lose_context,
251 WEBGL_provoking_vertex,
255 class UniqueBuffer final {
256 // Like UniquePtr<>, but for void* and malloc/calloc/free.
257 void* mBuffer = nullptr;
259 public:
260 static inline UniqueBuffer Take(void* buffer) {
261 UniqueBuffer ret;
262 ret.mBuffer = buffer;
263 return ret;
266 UniqueBuffer() = default;
268 ~UniqueBuffer() { reset(); }
270 UniqueBuffer(UniqueBuffer&& rhs) { *this = std::move(rhs); }
272 UniqueBuffer& operator=(UniqueBuffer&& rhs) {
273 reset();
274 this->mBuffer = rhs.mBuffer;
275 rhs.mBuffer = nullptr;
276 return *this;
279 explicit operator bool() const { return bool(mBuffer); }
281 void* get() const { return mBuffer; }
283 void reset() {
284 // Believe it or not, when `free` unconditional, it was showing up
285 // in profiles, nearly 20% of time spent in MethodDispatcther<UniformData>
286 // on Aquarium.
287 if (mBuffer) {
288 free(mBuffer);
289 mBuffer = nullptr;
294 namespace webgl {
295 struct FormatUsageInfo;
297 static constexpr GLenum kErrorPerfWarning = 0x10001;
299 struct SampleableInfo final {
300 const char* incompleteReason = nullptr;
301 uint32_t levels = 0;
302 const webgl::FormatUsageInfo* usage = nullptr;
303 bool isDepthTexCompare = false;
305 bool IsComplete() const { return bool(levels); }
308 enum class AttribBaseType : uint8_t {
309 Boolean, // Can convert from anything.
310 Float, // Also includes NormU?Int
311 Int,
312 Uint,
314 webgl::AttribBaseType ToAttribBaseType(GLenum);
315 const char* ToString(AttribBaseType);
317 enum class UniformBaseType : uint8_t {
318 Float,
319 Int,
320 Uint,
322 const char* ToString(UniformBaseType);
324 using ObjectId = uint64_t;
326 enum class BufferKind : uint8_t {
327 Undefined,
328 Index,
329 NonIndex,
332 } // namespace webgl
334 // -
336 struct FloatOrInt final // For TexParameter[fi] and friends.
338 bool isFloat = false;
339 uint8_t padding[3] = {};
340 GLfloat f = 0;
341 GLint i = 0;
343 explicit FloatOrInt(GLint x = 0) : isFloat(false), f(x), i(x) {}
345 explicit FloatOrInt(GLfloat x) : isFloat(true), f(x), i(roundf(x)) {}
347 auto MutTiedFields() { return std::tie(isFloat, padding, f, i); }
350 // -
352 struct WebGLContextOptions final {
353 bool alpha = true;
354 bool depth = true;
355 bool stencil = false;
356 bool premultipliedAlpha = true;
358 bool antialias = true;
359 bool preserveDrawingBuffer = false;
360 bool failIfMajorPerformanceCaveat = false;
361 bool xrCompatible = false;
363 dom::WebGLPowerPreference powerPreference =
364 dom::WebGLPowerPreference::Default;
365 bool ignoreColorSpace = true;
366 dom::PredefinedColorSpace colorSpace = dom::PredefinedColorSpace::Srgb;
367 bool shouldResistFingerprinting = true;
369 bool enableDebugRendererInfo = false;
371 auto MutTiedFields() {
372 // clang-format off
373 return std::tie(
374 alpha,
375 depth,
376 stencil,
377 premultipliedAlpha,
379 antialias,
380 preserveDrawingBuffer,
381 failIfMajorPerformanceCaveat,
382 xrCompatible,
384 powerPreference,
385 colorSpace,
386 ignoreColorSpace,
387 shouldResistFingerprinting,
389 enableDebugRendererInfo);
390 // clang-format on
393 // -
395 WebGLContextOptions();
396 WebGLContextOptions(const WebGLContextOptions&) = default;
398 using Self = WebGLContextOptions;
399 friend bool operator==(const Self& a, const Self& b) {
400 return TiedFields(a) == TiedFields(b);
402 friend bool operator!=(const Self& a, const Self& b) { return !(a == b); }
405 namespace gfx {
407 inline ColorSpace2 ToColorSpace2(const dom::PredefinedColorSpace cs) {
408 switch (cs) {
409 case dom::PredefinedColorSpace::Srgb:
410 return ColorSpace2::SRGB;
411 case dom::PredefinedColorSpace::Display_p3:
412 return ColorSpace2::DISPLAY_P3;
414 MOZ_CRASH("Exhaustive switch");
417 } // namespace gfx
419 // -
421 template <typename _T>
422 struct avec2 {
423 using T = _T;
425 T x = T();
426 T y = T();
428 auto MutTiedFields() { return std::tie(x, y); }
430 template <typename U, typename V>
431 static Maybe<avec2> From(const U _x, const V _y) {
432 const auto x = CheckedInt<T>(_x);
433 const auto y = CheckedInt<T>(_y);
434 if (!x.isValid() || !y.isValid()) return {};
435 return Some(avec2(x.value(), y.value()));
438 template <typename U>
439 static auto From(const U& val) {
440 return From(val.x, val.y);
442 template <typename U>
443 static auto FromSize(const U& val) {
444 return From(val.width, val.height);
447 avec2() = default;
448 avec2(const T _x, const T _y) : x(_x), y(_y) {}
450 bool operator==(const avec2& rhs) const { return x == rhs.x && y == rhs.y; }
451 bool operator!=(const avec2& rhs) const { return !(*this == rhs); }
453 #define _(OP) \
454 avec2 operator OP(const avec2& rhs) const { \
455 return {x OP rhs.x, y OP rhs.y}; \
457 avec2 operator OP(const T rhs) const { return {x OP rhs, y OP rhs}; }
459 _(+)
460 _(-)
461 _(*)
462 _(/)
464 #undef _
466 avec2 Clamp(const avec2& min, const avec2& max) const {
467 return {mozilla::Clamp(x, min.x, max.x), mozilla::Clamp(y, min.y, max.y)};
470 // mozilla::Clamp doesn't work on floats, so be clear that this is a min+max
471 // helper.
472 avec2 ClampMinMax(const avec2& min, const avec2& max) const {
473 const auto ClampScalar = [](const T v, const T min, const T max) {
474 return std::max(min, std::min(v, max));
476 return {ClampScalar(x, min.x, max.x), ClampScalar(y, min.y, max.y)};
479 template <typename U>
480 U StaticCast() const {
481 return {static_cast<typename U::T>(x), static_cast<typename U::T>(y)};
485 template <typename T>
486 avec2<T> MinExtents(const avec2<T>& a, const avec2<T>& b) {
487 return {std::min(a.x, b.x), std::min(a.y, b.y)};
490 template <typename T>
491 avec2<T> MaxExtents(const avec2<T>& a, const avec2<T>& b) {
492 return {std::max(a.x, b.x), std::max(a.y, b.y)};
495 // -
497 template <typename _T>
498 struct avec3 {
499 using T = _T;
501 T x = T();
502 T y = T();
503 T z = T();
505 auto MutTiedFields() { return std::tie(x, y, z); }
507 template <typename U, typename V>
508 static Maybe<avec3> From(const U _x, const V _y, const V _z) {
509 const auto x = CheckedInt<T>(_x);
510 const auto y = CheckedInt<T>(_y);
511 const auto z = CheckedInt<T>(_z);
512 if (!x.isValid() || !y.isValid() || !z.isValid()) return {};
513 return Some(avec3(x.value(), y.value(), z.value()));
516 template <typename U>
517 static auto From(const U& val) {
518 return From(val.x, val.y, val.z);
521 avec3() = default;
522 avec3(const T _x, const T _y, const T _z) : x(_x), y(_y), z(_z) {}
524 bool operator==(const avec3& rhs) const {
525 return x == rhs.x && y == rhs.y && z == rhs.z;
527 bool operator!=(const avec3& rhs) const { return !(*this == rhs); }
530 using ivec2 = avec2<int32_t>;
531 using ivec3 = avec3<int32_t>;
532 using uvec2 = avec2<uint32_t>;
533 using uvec3 = avec3<uint32_t>;
535 inline ivec2 AsVec(const gfx::IntSize& s) { return {s.width, s.height}; }
537 // -
539 namespace webgl {
541 struct PackingInfo final {
542 GLenum format = 0;
543 GLenum type = 0;
545 auto MutTiedFields() { return std::tie(format, type); }
547 using Self = PackingInfo;
548 friend bool operator<(const Self& a, const Self& b) {
549 return TiedFields(a) < TiedFields(b);
551 friend bool operator==(const Self& a, const Self& b) {
552 return TiedFields(a) == TiedFields(b);
555 template <class T>
556 friend T& operator<<(T& s, const PackingInfo& pi) {
557 s << "PackingInfo{format: " << EnumString(pi.format)
558 << ", type: " << EnumString(pi.type) << "}";
559 return s;
563 struct DriverUnpackInfo final {
564 GLenum internalFormat = 0;
565 GLenum unpackFormat = 0;
566 GLenum unpackType = 0;
568 PackingInfo ToPacking() const { return {unpackFormat, unpackType}; }
571 // -
573 template <typename E>
574 class EnumMask {
575 public:
576 uint64_t mBits = 0;
578 private:
579 struct BitRef final {
580 EnumMask& bits;
581 const uint64_t mask;
583 explicit operator bool() const { return bits.mBits & mask; }
585 auto& operator=(const bool val) {
586 if (val) {
587 bits.mBits |= mask;
588 } else {
589 bits.mBits &= ~mask;
591 return *this;
595 uint64_t Mask(const E i) const {
596 return uint64_t{1} << static_cast<uint64_t>(i);
599 public:
600 BitRef operator[](const E i) { return {*this, Mask(i)}; }
601 bool operator[](const E i) const { return mBits & Mask(i); }
603 // -
605 auto MutTiedFields() { return std::tie(mBits); }
608 using ExtensionBits = EnumMask<WebGLExtensionID>;
610 // -
612 enum class ContextLossReason : uint8_t {
613 None,
614 Manual,
615 Guilty,
618 inline bool ReadContextLossReason(const uint8_t val,
619 ContextLossReason* const out) {
620 if (val > static_cast<uint8_t>(ContextLossReason::Guilty)) {
621 return false;
623 *out = static_cast<ContextLossReason>(val);
624 return true;
627 // -
629 struct InitContextDesc final {
630 bool isWebgl2 = false;
631 bool resistFingerprinting = false;
632 std::array<uint8_t, 2> _padding;
633 uint32_t principalKey = 0;
634 uvec2 size = {};
635 WebGLContextOptions options;
636 std::array<uint8_t, 3> _padding2;
638 auto MutTiedFields() {
639 return std::tie(isWebgl2, resistFingerprinting, _padding, principalKey,
640 size, options, _padding2);
644 constexpr uint32_t kMaxTransformFeedbackSeparateAttribs = 4;
646 struct Limits final {
647 ExtensionBits supportedExtensions;
649 // WebGL 1
650 uint32_t maxTexUnits = 0;
651 uint32_t maxTex2dSize = 0;
652 uint32_t maxTexCubeSize = 0;
653 uint32_t maxVertexAttribs = 0;
654 uint32_t maxViewportDim = 0;
655 std::array<float, 2> pointSizeRange = {{1, 1}};
656 std::array<float, 2> lineWidthRange = {{1, 1}};
658 // WebGL 2
659 uint32_t maxTexArrayLayers = 0;
660 uint32_t maxTex3dSize = 0;
661 uint32_t maxUniformBufferBindings = 0;
662 uint32_t uniformBufferOffsetAlignment = 0;
664 // Exts
665 bool astcHdr = false;
666 std::array<uint8_t, 3> _padding;
667 uint32_t maxColorDrawBuffers = 1;
668 uint32_t maxMultiviewLayers = 0;
669 uint64_t queryCounterBitsTimeElapsed = 0;
670 uint64_t queryCounterBitsTimestamp = 0;
672 auto MutTiedFields() {
673 return std::tie(supportedExtensions,
675 maxTexUnits, maxTex2dSize, maxTexCubeSize, maxVertexAttribs,
676 maxViewportDim, pointSizeRange, lineWidthRange,
678 maxTexArrayLayers, maxTex3dSize, maxUniformBufferBindings,
679 uniformBufferOffsetAlignment,
681 astcHdr, _padding, maxColorDrawBuffers, maxMultiviewLayers,
682 queryCounterBitsTimeElapsed, queryCounterBitsTimestamp);
686 // -
688 template <class T, size_t PaddedSize>
689 struct Padded {
690 private:
691 T val = {};
692 uint8_t padding[PaddedSize - sizeof(T)] = {};
694 public:
695 operator T&() { return val; }
696 operator const T&() const { return val; }
698 auto& operator=(const T& rhs) { return val = rhs; }
699 auto& operator=(T&& rhs) { return val = std::move(rhs); }
701 auto& operator*() { return val; }
702 auto& operator*() const { return val; }
703 auto operator->() { return &val; }
704 auto operator->() const { return &val; }
707 // -
709 enum class OptionalRenderableFormatBits : uint8_t {
710 RGB8 = (1 << 0),
711 SRGB8 = (1 << 1),
713 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(OptionalRenderableFormatBits)
714 inline constexpr bool IsEnumCase(const OptionalRenderableFormatBits raw) {
715 auto rawWithoutValidBits = UnderlyingValue(raw);
716 auto bit = decltype(rawWithoutValidBits){1};
717 while (bit) {
718 switch (OptionalRenderableFormatBits{bit}) {
719 // -Werror=switch ensures exhaustive.
720 case OptionalRenderableFormatBits::RGB8:
721 case OptionalRenderableFormatBits::SRGB8:
722 rawWithoutValidBits &= ~bit;
723 break;
725 bit <<= 1;
727 return rawWithoutValidBits == 0;
730 // -
732 struct InitContextResult final {
733 Padded<std::string, 32> error; // MINGW 32-bit needs this padding.
734 WebGLContextOptions options;
735 gl::GLVendor vendor;
736 OptionalRenderableFormatBits optionalRenderableFormatBits;
737 uint8_t _padding = {};
738 Limits limits;
739 EnumMask<layers::SurfaceDescriptor::Type> uploadableSdTypes;
741 auto MutTiedFields() {
742 return std::tie(error, options, vendor, optionalRenderableFormatBits,
743 _padding, limits, uploadableSdTypes);
747 // -
749 struct ErrorInfo final {
750 GLenum type;
751 std::string info;
754 struct ShaderPrecisionFormat final {
755 GLint rangeMin = 0;
756 GLint rangeMax = 0;
757 GLint precision = 0;
760 // -
762 enum class LossStatus {
763 Ready,
765 Lost,
766 LostForever,
767 LostManually,
770 // -
772 struct CompileResult final {
773 bool pending = true;
774 nsCString log;
775 nsCString translatedSource;
776 bool success = false;
779 // -
781 struct OpaqueFramebufferOptions final {
782 bool depthStencil = true;
783 bool antialias = true;
784 std::array<uint8_t, 2> _padding;
785 uint32_t width = 0;
786 uint32_t height = 0;
788 auto MutTiedFields() {
789 return std::tie(depthStencil, antialias, _padding, width, height);
793 // -
795 struct SwapChainOptions final {
796 layers::RemoteTextureId remoteTextureId;
797 layers::RemoteTextureOwnerId remoteTextureOwnerId;
798 bool bgra = false;
799 bool forceAsyncPresent = false;
800 // Pad to sizeof(u64):
801 uint16_t padding1 = 0;
802 uint32_t padding2 = 0;
804 auto MutTiedFields() {
805 return std::tie(remoteTextureId, remoteTextureOwnerId, bgra,
806 forceAsyncPresent, padding1, padding2);
810 // -
812 struct ActiveInfo {
813 GLenum elemType = 0; // `type`
814 uint32_t elemCount = 0; // `size`
815 std::string name;
818 struct ActiveAttribInfo final : public ActiveInfo {
819 int32_t location = -1;
820 AttribBaseType baseType = AttribBaseType::Float;
823 struct ActiveUniformInfo final : public ActiveInfo {
824 std::unordered_map<uint32_t, uint32_t>
825 locByIndex; // Uniform array locations are sparse.
826 int32_t block_index = -1;
827 int32_t block_offset = -1; // In block, offset.
828 int32_t block_arrayStride = -1;
829 int32_t block_matrixStride = -1;
830 bool block_isRowMajor = false;
833 struct ActiveUniformBlockInfo final {
834 std::string name;
835 // BLOCK_BINDING is dynamic state
836 uint32_t dataSize = 0;
837 std::vector<uint32_t> activeUniformIndices;
838 bool referencedByVertexShader = false;
839 bool referencedByFragmentShader = false;
842 struct LinkActiveInfo final {
843 std::vector<ActiveAttribInfo> activeAttribs;
844 std::vector<ActiveUniformInfo> activeUniforms;
845 std::vector<ActiveUniformBlockInfo> activeUniformBlocks;
846 std::vector<ActiveInfo> activeTfVaryings;
849 struct LinkResult final {
850 bool pending = true;
851 nsCString log;
852 bool success = false;
853 LinkActiveInfo active;
854 GLenum tfBufferMode = 0;
857 // -
859 /// 4x32-bit primitives, with a type tag.
860 struct TypedQuad final {
861 alignas(alignof(float)) std::array<uint8_t, 4 * sizeof(float)> data = {};
862 webgl::AttribBaseType type = webgl::AttribBaseType::Float;
863 uint8_t padding[3] = {};
865 constexpr auto MutTiedFields() { return std::tie(data, type, padding); }
868 /// [1-16]x32-bit primitives, with a type tag.
869 struct GetUniformData final {
870 alignas(alignof(float)) uint8_t data[4 * 4 * sizeof(float)] = {};
871 GLenum type = 0;
874 struct FrontBufferSnapshotIpc final {
875 uvec2 surfSize = {};
876 Maybe<mozilla::ipc::Shmem> shmem = {};
879 struct ReadPixelsResult {
880 gfx::IntRect subrect = {};
881 size_t byteStride = 0;
884 struct ReadPixelsResultIpc final : public ReadPixelsResult {
885 Maybe<mozilla::ipc::Shmem> shmem = {};
888 struct VertAttribPointerDesc final {
889 bool intFunc = false;
890 uint8_t channels = 4;
891 bool normalized = false;
892 uint8_t byteStrideOrZero = 0;
893 GLenum type = LOCAL_GL_FLOAT;
894 uint64_t byteOffset = 0;
896 auto MutTiedFields() {
897 return std::tie(intFunc, channels, normalized, byteStrideOrZero, type,
898 byteOffset);
902 struct VertAttribPointerCalculated final {
903 uint8_t byteSize = 4 * 4;
904 uint8_t byteStride = 4 * 4; // at-most 255
905 webgl::AttribBaseType baseType = webgl::AttribBaseType::Float;
908 } // namespace webgl
910 template <class T>
911 inline Range<T> ShmemRange(const mozilla::ipc::Shmem& shmem) {
912 return {shmem.get<T>(), shmem.Size<T>()};
915 // -
917 template <typename C, typename K>
918 inline auto MaybeFind(C& container, const K& key)
919 -> decltype(&(container.find(key)->second)) {
920 const auto itr = container.find(key);
921 if (itr == container.end()) return nullptr;
922 return &(itr->second);
925 template <typename C, typename K>
926 inline typename C::mapped_type Find(
927 const C& container, const K& key,
928 const typename C::mapped_type notFound = {}) {
929 const auto itr = container.find(key);
930 if (itr == container.end()) return notFound;
931 return itr->second;
934 // -
936 template <typename T, typename U>
937 inline Maybe<T> MaybeAs(const U val) {
938 const auto checked = CheckedInt<T>(val);
939 if (!checked.isValid()) return {};
940 return Some(checked.value());
943 // -
945 inline GLenum IsTexImageTarget(const GLenum imageTarget) {
946 switch (imageTarget) {
947 case LOCAL_GL_TEXTURE_2D:
948 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
949 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
950 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
951 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
952 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
953 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
954 case LOCAL_GL_TEXTURE_3D:
955 case LOCAL_GL_TEXTURE_2D_ARRAY:
956 return true;
958 return false;
961 inline GLenum ImageToTexTarget(const GLenum imageTarget) {
962 switch (imageTarget) {
963 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
964 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
965 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
966 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
967 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
968 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
969 return LOCAL_GL_TEXTURE_CUBE_MAP;
971 if (IsTexImageTarget(imageTarget)) {
972 return imageTarget;
974 return 0;
977 inline bool IsTexTarget3D(const GLenum texTarget) {
978 switch (texTarget) {
979 case LOCAL_GL_TEXTURE_2D_ARRAY:
980 case LOCAL_GL_TEXTURE_3D:
981 return true;
983 default:
984 return false;
988 // -
990 namespace dom {
991 class Element;
992 class ImageBitmap;
993 class ImageData;
994 class OffscreenCanvas;
995 class VideoFrame;
996 } // namespace dom
998 struct TexImageSource {
999 const dom::ArrayBufferView* mView = nullptr;
1000 GLuint mViewElemOffset = 0;
1001 GLuint mViewElemLengthOverride = 0;
1003 const WebGLintptr* mPboOffset = nullptr;
1005 const dom::ImageBitmap* mImageBitmap = nullptr;
1006 const dom::ImageData* mImageData = nullptr;
1008 const dom::OffscreenCanvas* mOffscreenCanvas = nullptr;
1010 const dom::VideoFrame* mVideoFrame = nullptr;
1012 const dom::Element* mDomElem = nullptr;
1013 ErrorResult* mOut_error = nullptr;
1016 namespace webgl {
1018 template <class DerivedT>
1019 struct DeriveNotEq {
1020 bool operator!=(const DerivedT& rhs) const {
1021 const auto self = reinterpret_cast<const DerivedT*>(this);
1022 return !(*self == rhs);
1026 struct PixelPackingState : public DeriveNotEq<PixelPackingState> {
1027 uint32_t alignmentInTypeElems = 4; // ALIGNMENT isn't naive byte alignment!
1028 uint32_t rowLength = 0;
1029 uint32_t imageHeight = 0;
1030 uint32_t skipPixels = 0;
1031 uint32_t skipRows = 0;
1032 uint32_t skipImages = 0;
1034 auto MutTiedFields() {
1035 return std::tie(alignmentInTypeElems, rowLength, imageHeight, skipPixels,
1036 skipRows, skipImages);
1039 using Self = PixelPackingState;
1040 friend bool operator==(const Self& a, const Self& b) {
1041 return TiedFields(a) == TiedFields(b);
1044 static void AssertDefaultUnpack(gl::GLContext& gl, const bool isWebgl2) {
1045 PixelPackingState{}.AssertCurrentUnpack(gl, isWebgl2);
1048 void ApplyUnpack(gl::GLContext&, bool isWebgl2,
1049 const uvec3& uploadSize) const;
1050 bool AssertCurrentUnpack(gl::GLContext&, bool isWebgl2) const;
1053 struct PixelUnpackStateWebgl final : public PixelPackingState {
1054 GLenum colorspaceConversion =
1055 dom::WebGLRenderingContext_Binding::BROWSER_DEFAULT_WEBGL;
1056 bool flipY = false;
1057 bool premultiplyAlpha = false;
1058 bool requireFastPath = false;
1059 uint8_t padding = {};
1061 auto MutTiedFields() {
1062 return std::tuple_cat(PixelPackingState::MutTiedFields(),
1063 std::tie(colorspaceConversion, flipY,
1064 premultiplyAlpha, requireFastPath, padding));
1068 struct ExplicitPixelPackingState final {
1069 struct Metrics final {
1070 uvec3 usedSize = {};
1071 size_t bytesPerPixel = 0;
1073 // (srcStrideAndRowOverride.x, otherwise ROW_LENGTH != 0, otherwise size.x)
1074 // ...aligned to ALIGNMENT.
1075 size_t bytesPerRowStride = 0;
1077 // structuredSrcSize.y, otherwise IMAGE_HEIGHT*(SKIP_IMAGES+size.z)
1078 size_t totalRows = 0;
1080 // This ensures that no one else needs to do CheckedInt math.
1081 size_t totalBytesUsed = 0;
1082 size_t totalBytesStrided = 0;
1085 // It's so important that these aren't modified once evaluated.
1086 const PixelPackingState state;
1087 const Metrics metrics;
1089 static Result<ExplicitPixelPackingState, std::string> ForUseWith(
1090 const PixelPackingState&, GLenum target, const uvec3& subrectSize,
1091 const webgl::PackingInfo&, const Maybe<size_t> bytesPerRowStrideOverride);
1094 struct ReadPixelsDesc final {
1095 ivec2 srcOffset;
1096 uvec2 size;
1097 PackingInfo pi = {LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE};
1098 PixelPackingState packState;
1100 auto MutTiedFields() { return std::tie(srcOffset, size, pi, packState); }
1103 } // namespace webgl
1105 namespace webgl {
1107 struct TexUnpackBlobDesc final {
1108 GLenum imageTarget = LOCAL_GL_TEXTURE_2D;
1109 uvec3 size;
1110 gfxAlphaType srcAlphaType = gfxAlphaType::NonPremult;
1112 Maybe<Span<const uint8_t>> cpuData;
1113 Maybe<uint64_t> pboOffset;
1115 Maybe<uvec2> structuredSrcSize;
1116 RefPtr<layers::Image> image;
1117 Maybe<layers::SurfaceDescriptor> sd;
1118 RefPtr<gfx::DataSourceSurface> dataSurf;
1120 webgl::PixelUnpackStateWebgl unpacking;
1121 bool applyUnpackTransforms = true;
1123 // -
1125 auto ExplicitUnpacking(const webgl::PackingInfo& pi,
1126 const Maybe<size_t> bytesPerRowStrideOverride) const {
1127 return ExplicitPixelPackingState::ForUseWith(this->unpacking,
1128 this->imageTarget, this->size,
1129 pi, bytesPerRowStrideOverride);
1132 void Shrink(const webgl::PackingInfo&);
1135 } // namespace webgl
1137 // ---------------------------------------
1138 // MakeRange
1140 template <typename T, size_t N>
1141 inline Range<const T> MakeRange(T (&arr)[N]) {
1142 return {arr, N};
1145 template <typename T>
1146 inline Range<const T> MakeRange(const dom::Sequence<T>& seq) {
1147 return {seq.Elements(), seq.Length()};
1150 // -
1152 constexpr auto kUniversalAlignment = alignof(std::max_align_t);
1154 template <typename T>
1155 inline size_t AlignmentOffset(const size_t alignment, const T posOrPtr) {
1156 MOZ_ASSERT(alignment);
1157 const auto begin = reinterpret_cast<uintptr_t>(posOrPtr);
1158 const auto wholeMultiples = (begin + (alignment - 1)) / alignment;
1159 const auto aligned = wholeMultiples * alignment;
1160 return aligned - begin;
1163 template <typename T>
1164 inline size_t ByteSize(const Range<T>& range) {
1165 return range.length() * sizeof(T);
1168 // -
1170 Maybe<webgl::ErrorInfo> CheckBindBufferRange(
1171 const GLenum target, const GLuint index, const bool isBuffer,
1172 const uint64_t offset, const uint64_t size, const webgl::Limits& limits);
1174 Maybe<webgl::ErrorInfo> CheckFramebufferAttach(const GLenum bindImageTarget,
1175 const GLenum curTexTarget,
1176 const uint32_t mipLevel,
1177 const uint32_t zLayerBase,
1178 const uint32_t zLayerCount,
1179 const webgl::Limits& limits);
1181 Result<webgl::VertAttribPointerCalculated, webgl::ErrorInfo>
1182 CheckVertexAttribPointer(bool isWebgl2, const webgl::VertAttribPointerDesc&);
1184 uint8_t ElemTypeComponents(GLenum elemType);
1186 inline std::string ToString(const nsACString& text) {
1187 return {text.BeginReading(), text.Length()};
1190 inline void Memcpy(const RangedPtr<uint8_t>& destBytes,
1191 const RangedPtr<const uint8_t>& srcBytes,
1192 const size_t byteSize) {
1193 // Trigger range asserts
1194 (void)(srcBytes + byteSize);
1195 (void)(destBytes + byteSize);
1197 memcpy(destBytes.get(), srcBytes.get(), byteSize);
1200 template <class T, class U>
1201 inline void Memcpy(const Range<T>* const destRange,
1202 const RangedPtr<U>& srcBegin) {
1203 Memcpy(destRange->begin(), srcBegin, destRange->length());
1205 template <class T, class U>
1206 inline void Memcpy(const RangedPtr<T>* const destBegin,
1207 const Range<U>& srcRange) {
1208 Memcpy(destBegin, srcRange->begin(), srcRange->length());
1211 template <typename Dst, typename Src>
1212 inline void Memcpy(const Span<Dst>* const dest, const Span<Src>& src) {
1213 MOZ_RELEASE_ASSERT(src.size_bytes() >= dest->size_bytes());
1214 MOZ_ASSERT(src.size_bytes() == dest->size_bytes());
1215 memcpy(dest->data(), src.data(), dest->size_bytes());
1218 // -
1220 inline bool StartsWith(const std::string_view str,
1221 const std::string_view part) {
1222 return str.find(part) == 0;
1225 // -
1227 template <class T>
1228 Maybe<T> AsValidEnum(const std::underlying_type_t<T> raw_val) {
1229 const auto raw_enum = T{raw_val}; // This is the risk we prevent!
1230 if (!IsEnumCase(raw_enum)) return {};
1231 return Some(raw_enum);
1234 // -
1236 namespace webgl {
1238 // In theory, this number can be unbounded based on the driver. However, no
1239 // driver appears to expose more than 8. We might as well stop there too, for
1240 // now.
1241 // (http://opengl.gpuinfo.org/gl_stats_caps_single.php?listreportsbycap=GL_MAX_COLOR_ATTACHMENTS)
1242 inline constexpr size_t kMaxDrawBuffers = 8;
1244 union UniformDataVal {
1245 float f32;
1246 int32_t i32;
1247 uint32_t u32;
1250 enum class ProvokingVertex : GLenum {
1251 FirstVertex = LOCAL_GL_FIRST_VERTEX_CONVENTION,
1252 LastVertex = LOCAL_GL_LAST_VERTEX_CONVENTION,
1254 inline constexpr bool IsEnumCase(const ProvokingVertex raw) {
1255 switch (raw) {
1256 case ProvokingVertex::FirstVertex:
1257 case ProvokingVertex::LastVertex:
1258 return true;
1260 return false;
1263 template <class E>
1264 inline constexpr std::optional<E> AsEnumCase(
1265 const std::underlying_type_t<E> raw) {
1266 const auto ret = static_cast<E>(raw);
1267 if (!IsEnumCase(ret)) return {};
1268 return ret;
1271 // -
1273 struct BufferAndIndex final {
1274 const WebGLBuffer* buffer = nullptr;
1275 uint32_t id = -1;
1278 } // namespace webgl
1280 struct IndexedBufferBinding final {
1281 RefPtr<WebGLBuffer> mBufferBinding;
1282 uint64_t mRangeStart = 0;
1283 uint64_t mRangeSize = 0;
1285 IndexedBufferBinding();
1286 ~IndexedBufferBinding();
1288 uint64_t ByteCount() const;
1291 // -
1293 template <class... Args>
1294 inline std::string PrintfStdString(const char* const format,
1295 const Args&... args) {
1296 const auto nsStr = nsPrintfCString(format, args...);
1297 return ToString(nsStr);
1300 inline const char* ToChars(const bool val) {
1301 if (val) return "true";
1302 return "false";
1305 template <class To>
1306 struct ReinterpretToSpan {
1307 template <class FromT>
1308 static inline constexpr Span<To> From(const Span<FromT>& from) {
1309 static_assert(sizeof(FromT) == sizeof(To));
1310 return {reinterpret_cast<To*>(from.data()), from.size()};
1314 // -
1316 inline std::string Join(Span<const std::string> ss,
1317 const std::string_view& delim) {
1318 if (!ss.size()) return "";
1319 auto ret = std::string();
1321 auto chars = delim.size() * (ss.size() - 1);
1322 for (const auto& s : ss) {
1323 chars += s.size();
1325 ret.reserve(chars);
1328 ret = ss[0];
1329 ss = ss.subspan(1);
1330 for (const auto& s : ss) {
1331 ret += delim;
1332 ret += s;
1334 return ret;
1337 inline std::string ToStringWithCommas(uint64_t v) {
1338 if (!v) return "0";
1339 std::vector<std::string> chunks;
1340 while (v) {
1341 const auto chunk = v % 1000;
1342 v /= 1000;
1343 chunks.insert(chunks.begin(), std::to_string(chunk));
1345 return Join(chunks, ",");
1348 // -
1350 namespace webgl {
1352 std::unordered_map<GLenum, bool> MakeIsEnabledMap(bool webgl2);
1354 static constexpr uint32_t kMaxClientWaitSyncTimeoutNS =
1355 1000 * 1000 * 1000; // 1000ms in ns.
1357 } // namespace webgl
1358 } // namespace mozilla
1360 #endif