/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef WEBGL_FORMATS_H_ #define WEBGL_FORMATS_H_ #include <map> #include <set> #include "mozilla/UniquePtr.h" #include "WebGLTypes.h" namespace mozilla { namespace webgl { typedef uint8_t EffectiveFormatValueT; enum class EffectiveFormat : EffectiveFormatValueT { // GLES 3.0.4, p128-129, "Required Texture Formats" // "Texture and renderbuffer color formats" RGBA32I, RGBA32UI, RGBA16I, RGBA16UI, RGBA8, RGBA8I, RGBA8UI, SRGB8_ALPHA8, RGB10_A2, RGB10_A2UI, RGBA4, RGB5_A1, RGB8, RGB565, RG32I, RG32UI, RG16I, RG16UI, RG8, RG8I, RG8UI, R32I, R32UI, R16I, R16UI, R8, R8I, R8UI, // "Texture-only color formats" RGBA32F, RGBA16F, RGBA8_SNORM, RGB32F, RGB32I, RGB32UI, RGB16F, RGB16I, RGB16UI, RGB8_SNORM, RGB8I, RGB8UI, SRGB8, R11F_G11F_B10F, RGB9_E5, RG32F, RG16F, RG8_SNORM, R32F, R16F, R8_SNORM, // "Depth formats" DEPTH_COMPONENT32F, DEPTH_COMPONENT24, DEPTH_COMPONENT16, // "Combined depth+stencil formats" DEPTH32F_STENCIL8, DEPTH24_STENCIL8, // GLES 3.0.4, p205-206, "Required Renderbuffer Formats" STENCIL_INDEX8, //////////////////////////////////// // GLES 3.0.4, p147, table 3.19 // GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats" COMPRESSED_R11_EAC, COMPRESSED_SIGNED_R11_EAC, COMPRESSED_RG11_EAC, COMPRESSED_SIGNED_RG11_EAC, COMPRESSED_RGB8_ETC2, COMPRESSED_SRGB8_ETC2, COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, COMPRESSED_RGBA8_ETC2_EAC, COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, // AMD_compressed_ATC_texture ATC_RGB_AMD, ATC_RGBA_EXPLICIT_ALPHA_AMD, ATC_RGBA_INTERPOLATED_ALPHA_AMD, // EXT_texture_compression_s3tc COMPRESSED_RGB_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT3_EXT, COMPRESSED_RGBA_S3TC_DXT5_EXT, // IMG_texture_compression_pvrtc COMPRESSED_RGB_PVRTC_4BPPV1, COMPRESSED_RGBA_PVRTC_4BPPV1, COMPRESSED_RGB_PVRTC_2BPPV1, COMPRESSED_RGBA_PVRTC_2BPPV1, // OES_compressed_ETC1_RGB8_texture ETC1_RGB8_OES, //////////////////////////////////// // GLES 3.0.4, p128, table 3.12. Luminance8Alpha8, Luminance8, Alpha8, // OES_texture_float Luminance32FAlpha32F, Luminance32F, Alpha32F, // OES_texture_half_float Luminance16FAlpha16F, Luminance16F, Alpha16F, MAX, }; enum class UnsizedFormat : uint8_t { R, RG, RGB, RGBA, LA, L, A, D, S, DEPTH_STENCIL, // `DS` is a macro on Solaris. (regset.h) }; // GLES 3.0.4 p114 Table 3.4, p240 enum class ComponentType : uint8_t { None, Int, // RGBA32I UInt, // RGBA32UI, STENCIL_INDEX8 NormInt, // RGBA8_SNORM NormUInt, // RGBA8, DEPTH_COMPONENT16 Float, // RGBA32F Special, // DEPTH24_STENCIL8 }; enum class CompressionFamily : uint8_t { ETC1, ES3, // ETC2 or EAC ATC, S3TC, PVRTC, }; //////////////////////////////////////////////////////////////////////////////// struct CompressedFormatInfo { const EffectiveFormat effectiveFormat; const uint8_t bytesPerBlock; const uint8_t blockWidth; const uint8_t blockHeight; const CompressionFamily family; }; struct FormatInfo { const EffectiveFormat effectiveFormat; const char* const name; const GLenum sizedFormat; const UnsizedFormat unsizedFormat; const ComponentType componentType; const bool isSRGB; const CompressedFormatInfo* const compression; const uint8_t estimatedBytesPerPixel; // 0 iff bool(compression). // In bits. Iff bool(compression), active channels are 1. const uint8_t r; const uint8_t g; const uint8_t b; const uint8_t a; const uint8_t d; const uint8_t s; ////// std::map<UnsizedFormat, const FormatInfo*> copyDecayFormats; const FormatInfo* GetCopyDecayFormat(UnsizedFormat) const; bool IsColorFormat() const { // Alpha is a 'color format' since it's 'color-attachable'. return bool(compression) || bool(r | g | b | a); } }; struct PackingInfo { GLenum format; GLenum type; bool operator <(const PackingInfo& x) const { if (format != x.format) return format < x.format; return type < x.type; } bool operator ==(const PackingInfo& x) const { return (format == x.format && type == x.type); } }; struct DriverUnpackInfo { GLenum internalFormat; GLenum unpackFormat; GLenum unpackType; PackingInfo ToPacking() const { return {unpackFormat, unpackType}; } }; ////////////////////////////////////////////////////////////////////////////////////////// const FormatInfo* GetFormat(EffectiveFormat format); uint8_t BytesPerPixel(const PackingInfo& packing); bool GetBytesPerPixel(const PackingInfo& packing, uint8_t* const out_bytes); /* GLint ComponentSize(const FormatInfo* format, GLenum component); GLenum ComponentType(const FormatInfo* format); */ //////////////////////////////////////// struct FormatUsageInfo { const FormatInfo* const format; private: bool isRenderable; public: bool isFilterable; std::map<PackingInfo, DriverUnpackInfo> validUnpacks; const DriverUnpackInfo* idealUnpack; const GLint* textureSwizzleRGBA; bool maxSamplesKnown; uint32_t maxSamples; static const GLint kLuminanceSwizzleRGBA[4]; static const GLint kAlphaSwizzleRGBA[4]; static const GLint kLumAlphaSwizzleRGBA[4]; explicit FormatUsageInfo(const FormatInfo* _format) : format(_format) , isRenderable(false) , isFilterable(false) , idealUnpack(nullptr) , textureSwizzleRGBA(nullptr) , maxSamplesKnown(false) , maxSamples(0) { } bool IsRenderable() const { return isRenderable; } void SetRenderable(); bool IsUnpackValid(const PackingInfo& key, const DriverUnpackInfo** const out_value) const; void ResolveMaxSamples(gl::GLContext* gl); }; class FormatUsageAuthority { std::map<EffectiveFormat, FormatUsageInfo> mUsageMap; std::map<GLenum, const FormatUsageInfo*> mRBFormatMap; std::map<GLenum, const FormatUsageInfo*> mSizedTexFormatMap; std::map<PackingInfo, const FormatUsageInfo*> mUnsizedTexFormatMap; std::set<GLenum> mValidTexInternalFormats; std::set<GLenum> mValidTexUnpackFormats; std::set<GLenum> mValidTexUnpackTypes; public: static UniquePtr<FormatUsageAuthority> CreateForWebGL1(gl::GLContext* gl); static UniquePtr<FormatUsageAuthority> CreateForWebGL2(gl::GLContext* gl); private: FormatUsageAuthority() { } public: FormatUsageInfo* EditUsage(EffectiveFormat format); const FormatUsageInfo* GetUsage(EffectiveFormat format) const; void AddTexUnpack(FormatUsageInfo* usage, const PackingInfo& pi, const DriverUnpackInfo& dui); bool IsInternalFormatEnumValid(GLenum internalFormat) const; bool AreUnpackEnumsValid(GLenum unpackFormat, GLenum unpackType) const; void AllowRBFormat(GLenum sizedFormat, const FormatUsageInfo* usage); void AllowSizedTexFormat(GLenum sizedFormat, const FormatUsageInfo* usage); void AllowUnsizedTexFormat(const PackingInfo& pi, const FormatUsageInfo* usage); const FormatUsageInfo* GetRBUsage(GLenum sizedFormat) const; const FormatUsageInfo* GetSizedTexUsage(GLenum sizedFormat) const; const FormatUsageInfo* GetUnsizedTexUsage(const PackingInfo& pi) const; }; } // namespace webgl } // namespace mozilla #endif // WEBGL_FORMATS_H_