Bug 1941128 - Turn off network.dns.native_https_query on Mac again
[gecko.git] / dom / canvas / WebGLTypes.h
blob0467f61dcf540c75d9c482248683c656f81e1c05
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/IsEnumCase.h"
24 #include "mozilla/MathAlgorithms.h"
25 #include "mozilla/Range.h"
26 #include "mozilla/RefCounted.h"
27 #include "mozilla/Result.h"
28 #include "mozilla/ResultVariant.h"
29 #include "mozilla/Span.h"
30 #include "mozilla/TiedFields.h"
31 #include "mozilla/TypedEnumBits.h"
32 #include "mozilla/gfx/2D.h"
33 #include "mozilla/gfx/BuildConstants.h"
34 #include "mozilla/gfx/Logging.h"
35 #include "mozilla/gfx/Point.h"
36 #include "mozilla/gfx/Rect.h"
37 #include "mozilla/ipc/Shmem.h"
38 #include "mozilla/layers/LayersSurfaces.h"
39 #include "gfxTypes.h"
41 #include "nsTArray.h"
42 #include "nsString.h"
43 #include "mozilla/dom/WebGLRenderingContextBinding.h"
44 #include "mozilla/ipc/SharedMemory.h"
46 // Manual reflection of WebIDL typedefs that are different from their
47 // OpenGL counterparts.
48 using WebGLsizeiptr = int64_t;
49 using WebGLintptr = int64_t;
50 using WebGLboolean = bool;
52 // -
54 namespace mozilla {
55 namespace gl {
56 class GLContext; // This is going to be needed a lot.
57 } // namespace gl
59 // -
60 // Prevent implicit conversions into calloc and malloc. (mozilla namespace
61 // only!)
63 template <typename DestT>
64 class ForbidNarrowing final {
65 DestT mVal;
67 public:
68 template <typename SrcT>
69 MOZ_IMPLICIT ForbidNarrowing(SrcT val) : mVal(val) {
70 static_assert(
71 std::numeric_limits<SrcT>::min() >= std::numeric_limits<DestT>::min(),
72 "SrcT must be narrower than DestT.");
73 static_assert(
74 std::numeric_limits<SrcT>::max() <= std::numeric_limits<DestT>::max(),
75 "SrcT must be narrower than DestT.");
78 explicit operator DestT() const { return mVal; }
81 inline void* malloc(const ForbidNarrowing<size_t> s) {
82 return ::malloc(size_t(s));
85 inline void* calloc(const ForbidNarrowing<size_t> n,
86 const ForbidNarrowing<size_t> size) {
87 return ::calloc(size_t(n), size_t(size));
90 // -
92 // TODO: Remove this now-mere-alias.
93 template <typename From>
94 inline auto AutoAssertCast(const From val) {
95 return LazyAssertedCast(val);
98 const char* GetEnumName(GLenum val, const char* defaultRet = "<unknown>");
99 std::string EnumString(GLenum val);
101 namespace webgl {
102 template <typename T>
103 struct QueueParamTraits;
104 class TexUnpackBytes;
105 class TexUnpackImage;
106 class TexUnpackSurface;
107 } // namespace webgl
109 class ClientWebGLContext;
110 struct WebGLTexPboOffset;
111 class WebGLTexture;
112 class WebGLBuffer;
113 class WebGLFramebuffer;
114 class WebGLProgram;
115 class WebGLQuery;
116 class WebGLRenderbuffer;
117 class WebGLSampler;
118 class WebGLShader;
119 class WebGLSync;
120 class WebGLTexture;
121 class WebGLTransformFeedback;
122 class WebGLVertexArray;
124 // -
126 class VRefCounted : public RefCounted<VRefCounted> {
127 public:
128 virtual ~VRefCounted() = default;
130 #ifdef MOZ_REFCOUNTED_LEAK_CHECKING
131 virtual const char* typeName() const = 0;
132 virtual size_t typeSize() const = 0;
133 #endif
136 // -
139 * Implementing WebGL (or OpenGL ES 2.0) on top of desktop OpenGL requires
140 * emulating the vertex attrib 0 array when it's not enabled. Indeed,
141 * OpenGL ES 2.0 allows drawing without vertex attrib 0 array enabled, but
142 * desktop OpenGL does not allow that.
144 enum class WebGLVertexAttrib0Status : uint8_t {
145 Default, // default status - no emulation needed
146 EmulatedUninitializedArray, // need an artificial attrib 0 array, but
147 // contents may be left uninitialized
148 EmulatedInitializedArray // need an artificial attrib 0 array, and contents
149 // must be initialized
153 * The formats that may participate, either as source or destination formats,
154 * in WebGL texture conversions. This includes:
155 * - all the formats accepted by WebGL.texImage2D, e.g. RGBA4444
156 * - additional formats provided by extensions, e.g. RGB32F
157 * - additional source formats, depending on browser details, used when
158 * uploading textures from DOM elements. See gfxImageSurface::Format().
160 enum class WebGLTexelFormat : uint8_t {
161 // returned by SurfaceFromElementResultToImageSurface to indicate absence of
162 // image data
163 None,
164 // common value for formats for which format conversions are not supported
165 FormatNotSupportingAnyConversion,
166 // dummy pseudo-format meaning "use the other format".
167 // For example, if SrcFormat=Auto and DstFormat=RGB8, then the source
168 // is implicitly treated as being RGB8 itself.
169 Auto,
170 // 1-channel formats
172 A16F, // OES_texture_half_float
173 A32F, // OES_texture_float
175 R16F, // OES_texture_half_float
176 R32F, // OES_texture_float
177 // 2-channel formats
178 RA8,
179 RA16F, // OES_texture_half_float
180 RA32F, // OES_texture_float
181 RG8,
182 RG16F,
183 RG32F,
184 // 3-channel formats
185 RGB8,
186 RGB565,
187 RGB11F11F10F,
188 RGB16F, // OES_texture_half_float
189 RGB32F, // OES_texture_float
190 // 4-channel formats
191 RGBA8,
192 RGBA5551,
193 RGBA4444,
194 RGBA16F, // OES_texture_half_float
195 RGBA32F, // OES_texture_float
196 // DOM element source only formats.
197 RGBX8,
198 BGRX8,
199 BGRA8
202 enum class WebGLTexImageFunc : uint8_t {
203 TexImage,
204 TexSubImage,
205 CopyTexImage,
206 CopyTexSubImage,
207 CompTexImage,
208 CompTexSubImage,
211 enum class WebGLTexDimensions : uint8_t { Tex2D, Tex3D };
213 // Please keep extensions in alphabetic order.
214 enum class WebGLExtensionID : uint8_t {
215 ANGLE_instanced_arrays,
216 EXT_blend_minmax,
217 EXT_color_buffer_float,
218 EXT_color_buffer_half_float,
219 EXT_depth_clamp,
220 EXT_disjoint_timer_query,
221 EXT_float_blend,
222 EXT_frag_depth,
223 EXT_shader_texture_lod,
224 EXT_sRGB,
225 EXT_texture_compression_bptc,
226 EXT_texture_compression_rgtc,
227 EXT_texture_filter_anisotropic,
228 EXT_texture_norm16,
229 MOZ_debug,
230 OES_draw_buffers_indexed,
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,
253 WEBGL_provoking_vertex,
257 class UniqueBuffer final {
258 // Like unique_ptr<>, but for void* and malloc/calloc/free.
259 void* mBuffer = nullptr;
261 public:
262 static inline UniqueBuffer Take(void* buffer) {
263 UniqueBuffer ret;
264 ret.mBuffer = buffer;
265 return ret;
268 UniqueBuffer() = default;
270 ~UniqueBuffer() { reset(); }
272 UniqueBuffer(UniqueBuffer&& rhs) { *this = std::move(rhs); }
274 UniqueBuffer& operator=(UniqueBuffer&& rhs) {
275 reset();
276 this->mBuffer = rhs.mBuffer;
277 rhs.mBuffer = nullptr;
278 return *this;
281 explicit operator bool() const { return bool(mBuffer); }
283 void* get() const { return mBuffer; }
285 void reset() {
286 // Believe it or not, when `free` unconditional, it was showing up
287 // in profiles, nearly 20% of time spent in MethodDispatcther<UniformData>
288 // on Aquarium.
289 if (mBuffer) {
290 free(mBuffer);
291 mBuffer = nullptr;
296 namespace webgl {
297 struct FormatUsageInfo;
299 static constexpr GLenum kErrorPerfWarning = 0x10001;
301 struct SampleableInfo final {
302 const char* incompleteReason = nullptr;
303 uint32_t levels = 0;
304 const webgl::FormatUsageInfo* usage = nullptr;
305 bool isDepthTexCompare = false;
307 bool IsComplete() const { return bool(levels); }
310 enum class AttribBaseType : uint8_t {
311 Boolean, // Can convert from anything.
312 Float, // Also includes NormU?Int
313 Int,
314 Uint,
316 } // namespace webgl
317 template <>
318 inline constexpr bool IsEnumCase<webgl::AttribBaseType>(
319 const webgl::AttribBaseType v) {
320 switch (v) {
321 case webgl::AttribBaseType::Boolean:
322 case webgl::AttribBaseType::Float:
323 case webgl::AttribBaseType::Int:
324 case webgl::AttribBaseType::Uint:
325 return true;
327 return false;
329 namespace webgl {
330 webgl::AttribBaseType ToAttribBaseType(GLenum);
331 const char* ToString(AttribBaseType);
333 enum class UniformBaseType : uint8_t {
334 Float,
335 Int,
336 Uint,
338 const char* ToString(UniformBaseType);
340 using ObjectId = uint64_t;
342 enum class BufferKind : uint8_t {
343 Undefined,
344 Index,
345 NonIndex,
348 } // namespace webgl
350 // -
352 struct FloatOrInt final // For TexParameter[fi] and friends.
354 bool isFloat = false;
355 uint8_t padding[3] = {};
356 GLfloat f = 0;
357 GLint i = 0;
359 explicit FloatOrInt(GLint x = 0) : isFloat(false), f(x), i(x) {}
361 explicit FloatOrInt(GLfloat x) : isFloat(true), f(x), i(roundf(x)) {}
363 auto MutTiedFields() { return std::tie(isFloat, padding, f, i); }
366 // -
368 struct WebGLContextOptions final {
369 bool alpha = true;
370 bool depth = true;
371 bool stencil = false;
372 bool premultipliedAlpha = true;
374 bool antialias = true;
375 bool preserveDrawingBuffer = false;
376 bool failIfMajorPerformanceCaveat = false;
377 bool xrCompatible = false;
379 dom::WebGLPowerPreference powerPreference =
380 dom::WebGLPowerPreference::Default;
381 bool forceSoftwareRendering = false;
382 bool shouldResistFingerprinting = true;
383 bool enableDebugRendererInfo = false;
384 PaddingField<bool, 7> _padding;
386 auto MutTiedFields() {
387 // clang-format off
388 return std::tie(
389 alpha,
390 depth,
391 stencil,
392 premultipliedAlpha,
394 antialias,
395 preserveDrawingBuffer,
396 failIfMajorPerformanceCaveat,
397 xrCompatible,
399 powerPreference,
400 forceSoftwareRendering,
401 shouldResistFingerprinting,
402 enableDebugRendererInfo,
403 _padding);
404 // clang-format on
407 // -
409 WebGLContextOptions();
410 WebGLContextOptions(const WebGLContextOptions&) = default;
412 using Self = WebGLContextOptions;
413 friend bool operator==(const Self& a, const Self& b) {
414 return TiedFields(a) == TiedFields(b);
416 friend bool operator!=(const Self& a, const Self& b) { return !(a == b); }
419 namespace gfx {
421 inline ColorSpace2 ToColorSpace2(const dom::PredefinedColorSpace cs) {
422 switch (cs) {
423 case dom::PredefinedColorSpace::Srgb:
424 return ColorSpace2::SRGB;
425 case dom::PredefinedColorSpace::Display_p3:
426 return ColorSpace2::DISPLAY_P3;
428 MOZ_CRASH("Exhaustive switch");
431 } // namespace gfx
433 // -
435 template <typename _T>
436 struct avec2 {
437 using T = _T;
439 T x = T();
440 T y = T();
442 auto MutTiedFields() { return std::tie(x, y); }
444 template <typename U, typename V>
445 static Maybe<avec2> From(const U _x, const V _y) {
446 const auto x = CheckedInt<T>(_x);
447 const auto y = CheckedInt<T>(_y);
448 if (!x.isValid() || !y.isValid()) return {};
449 return Some(avec2(x.value(), y.value()));
452 template <typename U>
453 static auto From(const U& val) {
454 return From(val.x, val.y);
456 template <typename U>
457 static auto FromSize(const U& val) {
458 return From(val.width, val.height);
461 avec2() = default;
462 avec2(const T _x, const T _y) : x(_x), y(_y) {}
464 bool operator==(const avec2& rhs) const { return x == rhs.x && y == rhs.y; }
465 bool operator!=(const avec2& rhs) const { return !(*this == rhs); }
467 #define _(OP) \
468 avec2 operator OP(const avec2& rhs) const { \
469 return {x OP rhs.x, y OP rhs.y}; \
471 avec2 operator OP(const T rhs) const { return {x OP rhs, y OP rhs}; }
473 _(+)
474 _(-)
475 _(*)
476 _(/)
478 #undef _
480 avec2 Clamp(const avec2& min, const avec2& max) const {
481 return {std::clamp(x, min.x, max.x), std::clamp(y, min.y, max.y)};
484 template <typename U>
485 U StaticCast() const {
486 return {static_cast<typename U::T>(x), static_cast<typename U::T>(y)};
490 template <typename T>
491 avec2<T> MinExtents(const avec2<T>& a, const avec2<T>& b) {
492 return {std::min(a.x, b.x), std::min(a.y, b.y)};
495 template <typename T>
496 avec2<T> MaxExtents(const avec2<T>& a, const avec2<T>& b) {
497 return {std::max(a.x, b.x), std::max(a.y, b.y)};
500 // -
502 template <typename _T>
503 struct avec3 {
504 using T = _T;
506 T x = T();
507 T y = T();
508 T z = T();
510 auto MutTiedFields() { return std::tie(x, y, z); }
512 template <typename U, typename V>
513 static Maybe<avec3> From(const U _x, const V _y, const V _z) {
514 const auto x = CheckedInt<T>(_x);
515 const auto y = CheckedInt<T>(_y);
516 const auto z = CheckedInt<T>(_z);
517 if (!x.isValid() || !y.isValid() || !z.isValid()) return {};
518 return Some(avec3(x.value(), y.value(), z.value()));
521 template <typename U>
522 static auto From(const U& val) {
523 return From(val.x, val.y, val.z);
526 avec3() = default;
527 avec3(const T _x, const T _y, const T _z) : x(_x), y(_y), z(_z) {}
529 bool operator==(const avec3& rhs) const {
530 return x == rhs.x && y == rhs.y && z == rhs.z;
532 bool operator!=(const avec3& rhs) const { return !(*this == rhs); }
535 using ivec2 = avec2<int32_t>;
536 using ivec3 = avec3<int32_t>;
537 using uvec2 = avec2<uint32_t>;
538 using uvec3 = avec3<uint32_t>;
540 inline ivec2 AsVec(const gfx::IntSize& s) { return {s.width, s.height}; }
542 // -
544 namespace webgl {
546 struct PackingInfo final {
547 GLenum format = 0;
548 GLenum type = 0;
550 auto MutTiedFields() { return std::tie(format, type); }
552 using Self = PackingInfo;
553 friend bool operator<(const Self& a, const Self& b) {
554 return TiedFields(a) < TiedFields(b);
556 friend bool operator==(const Self& a, const Self& b) {
557 return TiedFields(a) == TiedFields(b);
560 template <class T>
561 friend T& operator<<(T& s, const PackingInfo& pi) {
562 s << "PackingInfo{format: " << EnumString(pi.format)
563 << ", type: " << EnumString(pi.type) << "}";
564 return s;
568 struct DriverUnpackInfo final {
569 GLenum internalFormat = 0;
570 GLenum unpackFormat = 0;
571 GLenum unpackType = 0;
573 PackingInfo ToPacking() const { return {unpackFormat, unpackType}; }
576 // -
578 template <typename E>
579 class EnumMask {
580 public:
581 uint64_t mBits = 0;
583 private:
584 struct BitRef final {
585 EnumMask& bits;
586 const uint64_t mask;
588 explicit operator bool() const { return bits.mBits & mask; }
590 auto& operator=(const bool val) {
591 if (val) {
592 bits.mBits |= mask;
593 } else {
594 bits.mBits &= ~mask;
596 return *this;
600 uint64_t Mask(const E i) const {
601 return uint64_t{1} << static_cast<uint64_t>(i);
604 public:
605 BitRef operator[](const E i) { return {*this, Mask(i)}; }
606 bool operator[](const E i) const { return mBits & Mask(i); }
608 // -
610 auto MutTiedFields() { return std::tie(mBits); }
613 using ExtensionBits = EnumMask<WebGLExtensionID>;
615 // -
617 enum class ContextLossReason : uint8_t {
618 None,
619 Manual,
620 Guilty,
623 inline bool ReadContextLossReason(const uint8_t val,
624 ContextLossReason* const out) {
625 if (val > static_cast<uint8_t>(ContextLossReason::Guilty)) {
626 return false;
628 *out = static_cast<ContextLossReason>(val);
629 return true;
632 // -
634 struct InitContextDesc final {
635 bool isWebgl2 = false;
636 bool resistFingerprinting = false;
637 std::array<uint8_t, 2> _padding;
638 uint32_t principalKey = 0;
639 uvec2 size = {};
640 WebGLContextOptions options;
641 std::array<uint8_t, 5> _padding2;
643 auto MutTiedFields() {
644 return std::tie(isWebgl2, resistFingerprinting, _padding, principalKey,
645 size, options, _padding2);
649 constexpr uint32_t kMaxTransformFeedbackSeparateAttribs = 4;
651 struct Limits final {
652 ExtensionBits supportedExtensions;
654 // WebGL 1
655 uint32_t maxTexUnits = 0;
656 uint32_t maxTex2dSize = 0;
657 uint32_t maxTexCubeSize = 0;
658 uint32_t maxVertexAttribs = 0;
659 uint32_t maxViewportDim = 0;
660 std::array<float, 2> pointSizeRange = {{1, 1}};
661 std::array<float, 2> lineWidthRange = {{1, 1}};
663 // WebGL 2
664 uint32_t maxTexArrayLayers = 0;
665 uint32_t maxTex3dSize = 0;
666 uint32_t maxUniformBufferBindings = 0;
667 uint32_t uniformBufferOffsetAlignment = 0;
669 // Exts
670 bool astcHdr = false;
671 std::array<uint8_t, 3> _padding;
672 uint32_t maxColorDrawBuffers = 1;
673 uint32_t maxMultiviewLayers = 0;
674 uint64_t queryCounterBitsTimeElapsed = 0;
675 uint64_t queryCounterBitsTimestamp = 0;
677 auto MutTiedFields() {
678 return std::tie(supportedExtensions,
680 maxTexUnits, maxTex2dSize, maxTexCubeSize, maxVertexAttribs,
681 maxViewportDim, pointSizeRange, lineWidthRange,
683 maxTexArrayLayers, maxTex3dSize, maxUniformBufferBindings,
684 uniformBufferOffsetAlignment,
686 astcHdr, _padding, maxColorDrawBuffers, maxMultiviewLayers,
687 queryCounterBitsTimeElapsed, queryCounterBitsTimestamp);
691 // -
692 namespace details {
693 template <class T, size_t Padding>
694 struct PaddedBase {
695 protected:
696 T val = {};
698 private:
699 uint8_t padding[Padding] = {};
702 template <class T>
703 struct PaddedBase<T, 0> {
704 protected:
705 T val = {};
707 } // namespace details
709 template <class T, size_t PaddedSize>
710 struct Padded : details::PaddedBase<T, PaddedSize - sizeof(T)> {
711 operator T&() { return this->val; }
712 operator const T&() const { return this->val; }
714 auto& operator=(const T& rhs) { return this->val = rhs; }
715 auto& operator=(T&& rhs) { return this->val = std::move(rhs); }
717 auto& operator*() { return this->val; }
718 auto& operator*() const { return this->val; }
719 auto operator->() { return &this->val; }
720 auto operator->() const { return &this->val; }
723 // -
725 enum class OptionalRenderableFormatBits : uint8_t {
726 RGB8 = (1 << 0),
727 SRGB8 = (1 << 1),
729 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(OptionalRenderableFormatBits)
731 } // namespace webgl
732 template <>
733 inline constexpr bool IsEnumCase<webgl::OptionalRenderableFormatBits>(
734 const webgl::OptionalRenderableFormatBits raw) {
735 auto rawWithoutValidBits = UnderlyingValue(raw);
736 auto bit = decltype(rawWithoutValidBits){1};
737 while (bit) {
738 switch (webgl::OptionalRenderableFormatBits{bit}) {
739 // -Werror=switch ensures exhaustive.
740 case webgl::OptionalRenderableFormatBits::RGB8:
741 case webgl::OptionalRenderableFormatBits::SRGB8:
742 rawWithoutValidBits &= ~bit;
743 break;
745 bit <<= 1;
747 return rawWithoutValidBits == 0;
749 namespace webgl {
751 // -
753 struct InitContextResult final {
754 Padded<std::string, 32> error; // MINGW 32-bit needs this padding.
755 WebGLContextOptions options;
756 gl::GLVendor vendor;
757 OptionalRenderableFormatBits optionalRenderableFormatBits;
758 std::array<uint8_t, 3> _padding = {};
759 Limits limits;
760 EnumMask<layers::SurfaceDescriptor::Type> uploadableSdTypes;
762 auto MutTiedFields() {
763 return std::tie(error, options, vendor, optionalRenderableFormatBits,
764 _padding, limits, uploadableSdTypes);
768 // -
770 struct ErrorInfo final {
771 GLenum type;
772 std::string info;
775 struct ShaderPrecisionFormat final {
776 GLint rangeMin = 0;
777 GLint rangeMax = 0;
778 GLint precision = 0;
781 // -
783 enum class LossStatus {
784 Ready,
786 Lost,
787 LostForever,
788 LostManually,
791 // -
793 struct CompileResult final {
794 bool pending = true;
795 nsCString log;
796 nsCString translatedSource;
797 bool success = false;
800 // -
802 struct OpaqueFramebufferOptions final {
803 bool depthStencil = true;
804 bool antialias = true;
805 std::array<uint8_t, 2> _padding;
806 uint32_t width = 0;
807 uint32_t height = 0;
809 auto MutTiedFields() {
810 return std::tie(depthStencil, antialias, _padding, width, height);
814 // -
816 struct SwapChainOptions final {
817 layers::RemoteTextureId remoteTextureId;
818 layers::RemoteTextureOwnerId remoteTextureOwnerId;
819 bool bgra = false;
820 bool forceAsyncPresent = false;
821 // Pad to sizeof(u64):
822 uint16_t padding1 = 0;
823 uint32_t padding2 = 0;
825 auto MutTiedFields() {
826 return std::tie(remoteTextureId, remoteTextureOwnerId, bgra,
827 forceAsyncPresent, padding1, padding2);
831 // -
833 struct ActiveInfo {
834 GLenum elemType = 0; // `type`
835 uint32_t elemCount = 0; // `size`
836 std::string name;
839 struct ActiveAttribInfo final : public ActiveInfo {
840 int32_t location = -1;
841 AttribBaseType baseType = AttribBaseType::Float;
844 struct ActiveUniformInfo final : public ActiveInfo {
845 std::unordered_map<uint32_t, uint32_t>
846 locByIndex; // Uniform array locations are sparse.
847 int32_t block_index = -1;
848 int32_t block_offset = -1; // In block, offset.
849 int32_t block_arrayStride = -1;
850 int32_t block_matrixStride = -1;
851 bool block_isRowMajor = false;
854 struct ActiveUniformBlockInfo final {
855 std::string name;
856 // BLOCK_BINDING is dynamic state
857 uint32_t dataSize = 0;
858 std::vector<uint32_t> activeUniformIndices;
859 bool referencedByVertexShader = false;
860 bool referencedByFragmentShader = false;
863 struct LinkActiveInfo final {
864 std::vector<ActiveAttribInfo> activeAttribs;
865 std::vector<ActiveUniformInfo> activeUniforms;
866 std::vector<ActiveUniformBlockInfo> activeUniformBlocks;
867 std::vector<ActiveInfo> activeTfVaryings;
870 struct LinkResult final {
871 bool pending = true;
872 nsCString log;
873 bool success = false;
874 LinkActiveInfo active;
875 GLenum tfBufferMode = 0;
878 // -
880 /// 4x32-bit primitives, with a type tag.
881 struct TypedQuad final {
882 alignas(alignof(float)) std::array<uint8_t, 4 * sizeof(float)> data = {};
883 webgl::AttribBaseType type = webgl::AttribBaseType::Float;
884 uint8_t padding[3] = {};
886 constexpr auto MutTiedFields() { return std::tie(data, type, padding); }
889 /// [1-16]x32-bit primitives, with a type tag.
890 struct GetUniformData final {
891 alignas(alignof(float)) uint8_t data[4 * 4 * sizeof(float)] = {};
892 GLenum type = 0;
895 struct FrontBufferSnapshotIpc final {
896 uvec2 surfSize = {};
897 Maybe<mozilla::ipc::Shmem> shmem = {};
900 struct ReadPixelsResult {
901 gfx::IntRect subrect = {};
902 size_t byteStride = 0;
905 struct ReadPixelsResultIpc final : public ReadPixelsResult {
906 Maybe<mozilla::ipc::Shmem> shmem = {};
909 struct VertAttribPointerDesc final {
910 bool intFunc = false;
911 uint8_t channels = 4;
912 bool normalized = false;
913 uint8_t byteStrideOrZero = 0;
914 GLenum type = LOCAL_GL_FLOAT;
915 uint64_t byteOffset = 0;
917 auto MutTiedFields() {
918 return std::tie(intFunc, channels, normalized, byteStrideOrZero, type,
919 byteOffset);
923 struct VertAttribPointerCalculated final {
924 uint8_t byteSize = 4 * 4;
925 uint8_t byteStride = 4 * 4; // at-most 255
926 webgl::AttribBaseType baseType = webgl::AttribBaseType::Float;
929 } // namespace webgl
931 template <class T>
932 inline Range<T> ShmemRange(const mozilla::ipc::Shmem& shmem) {
933 return {shmem.get<T>(), shmem.Size<T>()};
936 // -
938 template <typename C, typename K>
939 inline auto MaybeFind(C& container, const K& key)
940 -> decltype(&(container.find(key)->second)) {
941 const auto itr = container.find(key);
942 if (itr == container.end()) return nullptr;
943 return &(itr->second);
946 template <typename C, typename K>
947 inline typename C::mapped_type Find(
948 const C& container, const K& key,
949 const typename C::mapped_type notFound = {}) {
950 const auto itr = container.find(key);
951 if (itr == container.end()) return notFound;
952 return itr->second;
955 // -
957 template <typename T, typename U>
958 inline Maybe<T> MaybeAs(const U val) {
959 const auto checked = CheckedInt<T>(val);
960 if (!checked.isValid()) return {};
961 return Some(checked.value());
964 // -
966 inline GLenum IsTexImageTarget(const GLenum imageTarget) {
967 switch (imageTarget) {
968 case LOCAL_GL_TEXTURE_2D:
969 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
970 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
971 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
972 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
973 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
974 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
975 case LOCAL_GL_TEXTURE_3D:
976 case LOCAL_GL_TEXTURE_2D_ARRAY:
977 return true;
979 return false;
982 inline GLenum ImageToTexTarget(const GLenum imageTarget) {
983 switch (imageTarget) {
984 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
985 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
986 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
987 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
988 case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
989 case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
990 return LOCAL_GL_TEXTURE_CUBE_MAP;
992 if (IsTexImageTarget(imageTarget)) {
993 return imageTarget;
995 return 0;
998 inline bool IsTexTarget3D(const GLenum texTarget) {
999 switch (texTarget) {
1000 case LOCAL_GL_TEXTURE_2D_ARRAY:
1001 case LOCAL_GL_TEXTURE_3D:
1002 return true;
1004 default:
1005 return false;
1009 // -
1011 namespace dom {
1012 class Element;
1013 class ImageBitmap;
1014 class ImageData;
1015 class OffscreenCanvas;
1016 class VideoFrame;
1017 } // namespace dom
1019 struct TexImageSource {
1020 const dom::ArrayBufferView* mView = nullptr;
1021 GLuint mViewElemOffset = 0;
1022 GLuint mViewElemLengthOverride = 0;
1024 const WebGLintptr* mPboOffset = nullptr;
1026 const dom::ImageBitmap* mImageBitmap = nullptr;
1027 const dom::ImageData* mImageData = nullptr;
1029 const dom::OffscreenCanvas* mOffscreenCanvas = nullptr;
1031 const dom::VideoFrame* mVideoFrame = nullptr;
1033 const dom::Element* mDomElem = nullptr;
1034 ErrorResult* mOut_error = nullptr;
1037 namespace webgl {
1039 template <class DerivedT>
1040 struct DeriveNotEq {
1041 bool operator!=(const DerivedT& rhs) const {
1042 const auto self = reinterpret_cast<const DerivedT*>(this);
1043 return !(*self == rhs);
1047 struct PixelPackingState : public DeriveNotEq<PixelPackingState> {
1048 uint32_t alignmentInTypeElems = 4; // ALIGNMENT isn't naive byte alignment!
1049 uint32_t rowLength = 0;
1050 uint32_t imageHeight = 0;
1051 uint32_t skipPixels = 0;
1052 uint32_t skipRows = 0;
1053 uint32_t skipImages = 0;
1055 auto MutTiedFields() {
1056 return std::tie(alignmentInTypeElems, rowLength, imageHeight, skipPixels,
1057 skipRows, skipImages);
1060 using Self = PixelPackingState;
1061 friend bool operator==(const Self& a, const Self& b) {
1062 return TiedFields(a) == TiedFields(b);
1065 static void AssertDefaultUnpack(gl::GLContext& gl, const bool isWebgl2) {
1066 PixelPackingState{}.AssertCurrentUnpack(gl, isWebgl2);
1069 void ApplyUnpack(gl::GLContext&, bool isWebgl2,
1070 const uvec3& uploadSize) const;
1071 bool AssertCurrentUnpack(gl::GLContext&, bool isWebgl2) const;
1074 struct PixelUnpackStateWebgl final : public PixelPackingState {
1075 GLenum colorspaceConversion =
1076 dom::WebGLRenderingContext_Binding::BROWSER_DEFAULT_WEBGL;
1077 bool flipY = false;
1078 bool premultiplyAlpha = false;
1079 bool requireFastPath = false;
1080 uint8_t padding = {};
1082 auto MutTiedFields() {
1083 return std::tuple_cat(PixelPackingState::MutTiedFields(),
1084 std::tie(colorspaceConversion, flipY,
1085 premultiplyAlpha, requireFastPath, padding));
1089 struct ExplicitPixelPackingState final {
1090 struct Metrics final {
1091 uvec3 usedSize = {};
1092 size_t bytesPerPixel = 0;
1094 // (srcStrideAndRowOverride.x, otherwise ROW_LENGTH != 0, otherwise size.x)
1095 // ...aligned to ALIGNMENT.
1096 size_t bytesPerRowStride = 0;
1098 // structuredSrcSize.y, otherwise IMAGE_HEIGHT*(SKIP_IMAGES+size.z)
1099 size_t totalRows = 0;
1101 // This ensures that no one else needs to do CheckedInt math.
1102 size_t totalBytesUsed = 0;
1103 size_t totalBytesStrided = 0;
1106 // It's so important that these aren't modified once evaluated.
1107 const PixelPackingState state;
1108 const Metrics metrics;
1110 static Result<ExplicitPixelPackingState, std::string> ForUseWith(
1111 const PixelPackingState&, GLenum target, const uvec3& subrectSize,
1112 const webgl::PackingInfo&, const Maybe<size_t> bytesPerRowStrideOverride);
1115 struct ReadPixelsDesc final {
1116 ivec2 srcOffset;
1117 uvec2 size;
1118 PackingInfo pi = {LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE};
1119 PixelPackingState packState;
1121 auto MutTiedFields() { return std::tie(srcOffset, size, pi, packState); }
1124 } // namespace webgl
1126 namespace webgl {
1128 struct TexUnpackBlobDesc final {
1129 GLenum imageTarget = LOCAL_GL_TEXTURE_2D;
1130 uvec3 size;
1131 gfxAlphaType srcAlphaType = gfxAlphaType::NonPremult;
1133 Maybe<Span<const uint8_t>> cpuData;
1134 Maybe<uint64_t> pboOffset;
1136 Maybe<uvec2> structuredSrcSize;
1137 RefPtr<layers::Image> image;
1138 Maybe<layers::SurfaceDescriptor> sd;
1139 RefPtr<gfx::DataSourceSurface> dataSurf;
1141 webgl::PixelUnpackStateWebgl unpacking;
1142 bool applyUnpackTransforms = true;
1144 // -
1146 auto ExplicitUnpacking(const webgl::PackingInfo& pi,
1147 const Maybe<size_t> bytesPerRowStrideOverride) const {
1148 return ExplicitPixelPackingState::ForUseWith(this->unpacking,
1149 this->imageTarget, this->size,
1150 pi, bytesPerRowStrideOverride);
1153 void Shrink(const webgl::PackingInfo&);
1156 } // namespace webgl
1158 // ---------------------------------------
1159 // MakeRange
1161 template <typename T, size_t N>
1162 inline Range<const T> MakeRange(T (&arr)[N]) {
1163 return {arr, N};
1166 template <typename T>
1167 inline Range<const T> MakeRange(const dom::Sequence<T>& seq) {
1168 return {seq.Elements(), seq.Length()};
1171 // -
1173 constexpr auto kUniversalAlignment = alignof(std::max_align_t);
1175 template <typename T>
1176 inline size_t AlignmentOffset(const size_t alignment, const T posOrPtr) {
1177 MOZ_ASSERT(alignment);
1178 const auto begin = reinterpret_cast<uintptr_t>(posOrPtr);
1179 const auto wholeMultiples = (begin + (alignment - 1)) / alignment;
1180 const auto aligned = wholeMultiples * alignment;
1181 return aligned - begin;
1184 template <typename T>
1185 inline size_t ByteSize(const Range<T>& range) {
1186 return range.length() * sizeof(T);
1189 // -
1191 Maybe<webgl::ErrorInfo> CheckBindBufferRange(
1192 const GLenum target, const GLuint index, const bool isBuffer,
1193 const uint64_t offset, const uint64_t size, const webgl::Limits& limits);
1195 Maybe<webgl::ErrorInfo> CheckFramebufferAttach(const GLenum bindImageTarget,
1196 const GLenum curTexTarget,
1197 const uint32_t mipLevel,
1198 const uint32_t zLayerBase,
1199 const uint32_t zLayerCount,
1200 const webgl::Limits& limits);
1202 Result<webgl::VertAttribPointerCalculated, webgl::ErrorInfo>
1203 CheckVertexAttribPointer(bool isWebgl2, const webgl::VertAttribPointerDesc&);
1205 uint8_t ElemTypeComponents(GLenum elemType);
1207 inline std::string ToString(const nsACString& text) {
1208 return {text.BeginReading(), text.Length()};
1211 inline void Memcpy(const RangedPtr<uint8_t>& destBytes,
1212 const RangedPtr<const uint8_t>& srcBytes,
1213 const size_t byteSize) {
1214 // Trigger range asserts
1215 (void)(srcBytes + byteSize);
1216 (void)(destBytes + byteSize);
1218 memcpy(destBytes.get(), srcBytes.get(), byteSize);
1221 template <class T, class U>
1222 inline void Memcpy(const Range<T>* const destRange,
1223 const RangedPtr<U>& srcBegin) {
1224 Memcpy(destRange->begin(), srcBegin, destRange->length());
1226 template <class T, class U>
1227 inline void Memcpy(const RangedPtr<T>* const destBegin,
1228 const Range<U>& srcRange) {
1229 Memcpy(destBegin, srcRange->begin(), srcRange->length());
1232 template <typename Dst, typename Src>
1233 inline void Memcpy(const Span<Dst>* const dest, const Span<Src>& src) {
1234 MOZ_RELEASE_ASSERT(src.size_bytes() >= dest->size_bytes());
1235 MOZ_ASSERT(src.size_bytes() == dest->size_bytes());
1236 memcpy(dest->data(), src.data(), dest->size_bytes());
1239 // -
1241 inline bool StartsWith(const std::string_view str,
1242 const std::string_view part) {
1243 return str.find(part) == 0;
1246 // -
1248 namespace webgl {
1250 // In theory, this number can be unbounded based on the driver. However, no
1251 // driver appears to expose more than 8. We might as well stop there too, for
1252 // now.
1253 // (http://opengl.gpuinfo.org/gl_stats_caps_single.php?listreportsbycap=GL_MAX_COLOR_ATTACHMENTS)
1254 inline constexpr size_t kMaxDrawBuffers = 8;
1256 union UniformDataVal {
1257 float f32;
1258 int32_t i32;
1259 uint32_t u32;
1262 enum class ProvokingVertex : GLenum {
1263 FirstVertex = LOCAL_GL_FIRST_VERTEX_CONVENTION,
1264 LastVertex = LOCAL_GL_LAST_VERTEX_CONVENTION,
1267 } // namespace webgl
1269 template <>
1270 inline constexpr bool IsEnumCase<webgl::ProvokingVertex>(
1271 const webgl::ProvokingVertex raw) {
1272 switch (raw) {
1273 case webgl::ProvokingVertex::FirstVertex:
1274 case webgl::ProvokingVertex::LastVertex:
1275 return true;
1277 return false;
1280 namespace webgl {
1282 // -
1284 struct BufferAndIndex final {
1285 const WebGLBuffer* buffer = nullptr;
1286 uint32_t id = -1;
1289 } // namespace webgl
1291 struct IndexedBufferBinding final {
1292 RefPtr<WebGLBuffer> mBufferBinding;
1293 uint64_t mRangeStart = 0;
1294 uint64_t mRangeSize = 0;
1296 IndexedBufferBinding();
1297 ~IndexedBufferBinding();
1299 uint64_t ByteCount() const;
1302 // -
1304 template <class... Args>
1305 inline std::string PrintfStdString(const char* const format,
1306 const Args&... args) {
1307 const auto nsStr = nsPrintfCString(format, args...);
1308 return ToString(nsStr);
1311 inline const char* ToChars(const bool val) {
1312 if (val) return "true";
1313 return "false";
1316 template <class To>
1317 struct ReinterpretToSpan {
1318 template <class FromT>
1319 static inline constexpr Span<To> From(const Span<FromT>& from) {
1320 static_assert(sizeof(FromT) == sizeof(To));
1321 return {reinterpret_cast<To*>(from.data()), from.size()};
1325 // -
1327 inline std::string Join(Span<const std::string> ss,
1328 const std::string_view& delim) {
1329 if (!ss.size()) return "";
1330 auto ret = std::string();
1332 auto chars = delim.size() * (ss.size() - 1);
1333 for (const auto& s : ss) {
1334 chars += s.size();
1336 ret.reserve(chars);
1339 ret = ss[0];
1340 ss = ss.subspan(1);
1341 for (const auto& s : ss) {
1342 ret += delim;
1343 ret += s;
1345 return ret;
1348 inline std::string ToStringWithCommas(uint64_t v) {
1349 if (!v) return "0";
1350 std::vector<std::string> chunks;
1351 while (v) {
1352 const auto chunk = v % 1000;
1353 v /= 1000;
1354 chunks.insert(chunks.begin(), std::to_string(chunk));
1356 return Join(chunks, ",");
1359 // -
1361 namespace webgl {
1363 std::unordered_map<GLenum, bool> MakeIsEnabledMap(bool webgl2);
1365 static constexpr uint32_t kMaxClientWaitSyncTimeoutNS =
1366 1000 * 1000 * 1000; // 1000ms in ns.
1368 } // namespace webgl
1369 } // namespace mozilla
1371 #endif