WebGLFormats.h (10747B)
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/. */ 5 6 #ifndef WEBGL_FORMATS_H_ 7 #define WEBGL_FORMATS_H_ 8 9 #include <map> 10 #include <memory> 11 #include <set> 12 13 #include "WebGLTypes.h" 14 15 namespace mozilla::webgl { 16 17 using EffectiveFormatValueT = uint8_t; 18 19 enum class EffectiveFormat : EffectiveFormatValueT { 20 // GLES 3.0.4, p128-129, "Required Texture Formats" 21 // "Texture and renderbuffer color formats" 22 RGBA32I, 23 RGBA32UI, 24 RGBA16I, 25 RGBA16UI, 26 RGBA8, 27 RGBA8I, 28 RGBA8UI, 29 SRGB8_ALPHA8, 30 RGB10_A2, 31 RGB10_A2UI, 32 RGBA4, 33 RGB5_A1, 34 35 RGB8, 36 RGB565, 37 38 RG32I, 39 RG32UI, 40 RG16I, 41 RG16UI, 42 RG8, 43 RG8I, 44 RG8UI, 45 46 R32I, 47 R32UI, 48 R16I, 49 R16UI, 50 R8, 51 R8I, 52 R8UI, 53 54 // "Texture-only color formats" 55 RGBA32F, 56 RGBA16F, 57 RGBA8_SNORM, 58 59 RGB32F, 60 RGB32I, 61 RGB32UI, 62 63 RGB16F, 64 RGB16I, 65 RGB16UI, 66 67 RGB8_SNORM, 68 RGB8I, 69 RGB8UI, 70 SRGB8, 71 72 R11F_G11F_B10F, 73 RGB9_E5, 74 75 RG32F, 76 RG16F, 77 RG8_SNORM, 78 79 R32F, 80 R16F, 81 R8_SNORM, 82 83 // "Depth formats" 84 DEPTH_COMPONENT32F, 85 DEPTH_COMPONENT24, 86 DEPTH_COMPONENT16, 87 88 // "Combined depth+stencil formats" 89 DEPTH32F_STENCIL8, 90 DEPTH24_STENCIL8, 91 92 // GLES 3.0.4, p205-206, "Required Renderbuffer Formats" 93 STENCIL_INDEX8, 94 95 //////////////////////////////////// 96 97 // GLES 3.0.4, p147, table 3.19 98 // GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats" 99 COMPRESSED_R11_EAC, 100 COMPRESSED_SIGNED_R11_EAC, 101 COMPRESSED_RG11_EAC, 102 COMPRESSED_SIGNED_RG11_EAC, 103 COMPRESSED_RGB8_ETC2, 104 COMPRESSED_SRGB8_ETC2, 105 COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 106 COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 107 COMPRESSED_RGBA8_ETC2_EAC, 108 COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 109 110 // EXT_texture_compression_bptc 111 COMPRESSED_RGBA_BPTC_UNORM, 112 COMPRESSED_SRGB_ALPHA_BPTC_UNORM, 113 COMPRESSED_RGB_BPTC_SIGNED_FLOAT, 114 COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, 115 116 // EXT_texture_compression_rgtc 117 COMPRESSED_RED_RGTC1, 118 COMPRESSED_SIGNED_RED_RGTC1, 119 COMPRESSED_RG_RGTC2, 120 COMPRESSED_SIGNED_RG_RGTC2, 121 122 // EXT_texture_compression_s3tc 123 COMPRESSED_RGB_S3TC_DXT1_EXT, 124 COMPRESSED_RGBA_S3TC_DXT1_EXT, 125 COMPRESSED_RGBA_S3TC_DXT3_EXT, 126 COMPRESSED_RGBA_S3TC_DXT5_EXT, 127 128 // EXT_texture_sRGB 129 COMPRESSED_SRGB_S3TC_DXT1_EXT, 130 COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 131 COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 132 COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 133 134 // KHR_texture_compression_astc_ldr 135 COMPRESSED_RGBA_ASTC_4x4_KHR, 136 COMPRESSED_RGBA_ASTC_5x4_KHR, 137 COMPRESSED_RGBA_ASTC_5x5_KHR, 138 COMPRESSED_RGBA_ASTC_6x5_KHR, 139 COMPRESSED_RGBA_ASTC_6x6_KHR, 140 COMPRESSED_RGBA_ASTC_8x5_KHR, 141 COMPRESSED_RGBA_ASTC_8x6_KHR, 142 COMPRESSED_RGBA_ASTC_8x8_KHR, 143 COMPRESSED_RGBA_ASTC_10x5_KHR, 144 COMPRESSED_RGBA_ASTC_10x6_KHR, 145 COMPRESSED_RGBA_ASTC_10x8_KHR, 146 COMPRESSED_RGBA_ASTC_10x10_KHR, 147 COMPRESSED_RGBA_ASTC_12x10_KHR, 148 COMPRESSED_RGBA_ASTC_12x12_KHR, 149 150 COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, 151 COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, 152 COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, 153 COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, 154 COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, 155 COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, 156 COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, 157 COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, 158 COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, 159 COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, 160 COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, 161 COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, 162 COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, 163 COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 164 165 // IMG_texture_compression_pvrtc 166 COMPRESSED_RGB_PVRTC_4BPPV1, 167 COMPRESSED_RGBA_PVRTC_4BPPV1, 168 COMPRESSED_RGB_PVRTC_2BPPV1, 169 COMPRESSED_RGBA_PVRTC_2BPPV1, 170 171 // OES_compressed_ETC1_RGB8_texture 172 ETC1_RGB8_OES, 173 174 //////////////////////////////////// 175 176 // GLES 3.0.4, p128, table 3.12. 177 Luminance8Alpha8, 178 Luminance8, 179 Alpha8, 180 181 // OES_texture_float 182 Luminance32FAlpha32F, 183 Luminance32F, 184 Alpha32F, 185 186 // OES_texture_half_float 187 Luminance16FAlpha16F, 188 Luminance16F, 189 Alpha16F, 190 191 // EXT_texture_norm16 192 R16, 193 RG16, 194 RGB16, 195 RGBA16, 196 R16_SNORM, 197 RG16_SNORM, 198 RGB16_SNORM, 199 RGBA16_SNORM, 200 201 MAX, 202 }; 203 204 enum class UnsizedFormat : uint8_t { 205 R, 206 RG, 207 RGB, 208 RGBA, 209 LA, 210 L, 211 A, 212 D, 213 S, 214 DEPTH_STENCIL, // `DS` is a macro on Solaris. (regset.h) 215 }; 216 217 // GLES 3.0.4 p114 Table 3.4, p240 218 enum class ComponentType : uint8_t { 219 Int, // RGBA32I 220 UInt, // RGBA32UI 221 NormInt, // RGBA8_SNORM 222 NormUInt, // RGBA8 223 Float, // RGBA32F 224 }; 225 const char* ToString(ComponentType); 226 227 enum class TextureBaseType : uint8_t { 228 Int = uint8_t(ComponentType::Int), 229 UInt = uint8_t(ComponentType::UInt), 230 Float = uint8_t(ComponentType::Float), // Also includes NormU?Int and Depth 231 }; 232 233 const char* ToString(TextureBaseType); 234 235 enum class CompressionFamily : uint8_t { 236 ASTC, 237 BPTC, 238 ES3, // ETC2 or EAC 239 ETC1, 240 PVRTC, 241 RGTC, 242 S3TC, 243 }; 244 245 //////////////////////////////////////////////////////////////////////////////// 246 247 struct CompressedFormatInfo { 248 const EffectiveFormat effectiveFormat; 249 const uint8_t bytesPerBlock; 250 const uint8_t blockWidth; 251 const uint8_t blockHeight; 252 const CompressionFamily family; 253 }; 254 255 struct FormatInfo { 256 const EffectiveFormat effectiveFormat; 257 const char* const name; 258 const GLenum sizedFormat; 259 const UnsizedFormat unsizedFormat; 260 const ComponentType componentType; 261 const TextureBaseType baseType; 262 const bool isSRGB; 263 264 const CompressedFormatInfo* const compression; 265 266 const uint8_t estimatedBytesPerPixel; // 0 iff bool(compression). 267 268 // In bits. Iff bool(compression), active channels are 1. 269 const uint8_t r; 270 const uint8_t g; 271 const uint8_t b; 272 const uint8_t a; 273 const uint8_t d; 274 const uint8_t s; 275 276 ////// 277 278 std::map<UnsizedFormat, const FormatInfo*> copyDecayFormats; 279 280 const FormatInfo* GetCopyDecayFormat(UnsizedFormat) const; 281 282 bool IsColorFormat() const { 283 // Alpha is a 'color format' since it's 'color-attachable'. 284 return bool(compression) || bool(r | g | b | a); 285 } 286 }; 287 288 ////////////////////////////////////////////////////////////////////////////////////////// 289 290 struct PackingInfoInfo final { 291 uint8_t bytesPerElement = 0; 292 uint8_t elementsPerPixel = 0; // E.g. 1 for LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 293 bool isPacked = false; 294 295 static Maybe<PackingInfoInfo> For(const PackingInfo&); 296 297 inline uint8_t BytesPerPixel() const { 298 return bytesPerElement * elementsPerPixel; 299 } 300 }; 301 302 const FormatInfo* GetFormat(EffectiveFormat format); 303 304 inline uint8_t BytesPerPixel(const PackingInfo& packing) { 305 const auto pii = PackingInfoInfo::For(packing); 306 if (MOZ_LIKELY(pii)) return pii->BytesPerPixel(); 307 308 gfxCriticalError() << "Bad BytesPerPixel(" << packing << ")"; 309 MOZ_CRASH("Bad `packing`."); 310 } 311 312 /* 313 GLint ComponentSize(const FormatInfo* format, GLenum component); 314 GLenum ComponentType(const FormatInfo* format); 315 */ 316 //////////////////////////////////////// 317 318 struct FormatRenderableState final { 319 private: 320 enum class RenderableState { 321 Disabled, 322 Implicit, 323 Explicit, 324 }; 325 326 public: 327 RenderableState state = RenderableState::Disabled; 328 WebGLExtensionID extid = WebGLExtensionID::Max; 329 330 static FormatRenderableState Explicit() { 331 return {RenderableState::Explicit}; 332 } 333 334 static FormatRenderableState Implicit(WebGLExtensionID extid) { 335 return {RenderableState::Implicit, extid}; 336 } 337 338 bool IsRenderable() const { return state != RenderableState::Disabled; } 339 bool IsExplicit() const { return state == RenderableState::Explicit; } 340 }; 341 342 struct FormatUsageInfo { 343 const FormatInfo* const format; 344 345 private: 346 FormatRenderableState renderableState; 347 348 public: 349 bool isFilterable = false; 350 351 std::map<PackingInfo, DriverUnpackInfo> validUnpacks; 352 const DriverUnpackInfo* idealUnpack = nullptr; 353 354 // LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT/_TYPE: 355 mutable std::optional<PackingInfo> implReadPiCache; 356 357 const GLint* textureSwizzleRGBA = nullptr; 358 359 private: 360 mutable bool maxSamplesKnown = false; 361 mutable uint32_t maxSamples = 0; 362 363 public: 364 static const GLint kLuminanceSwizzleRGBA[4]; 365 static const GLint kAlphaSwizzleRGBA[4]; 366 static const GLint kLumAlphaSwizzleRGBA[4]; 367 368 explicit FormatUsageInfo(const FormatInfo* const _format) : format(_format) { 369 if (format->IsColorFormat() && format->baseType != TextureBaseType::Float) { 370 maxSamplesKnown = true; 371 } 372 } 373 374 bool IsRenderable() const { return renderableState.IsRenderable(); } 375 void SetRenderable( 376 const FormatRenderableState& state = FormatRenderableState::Explicit()); 377 bool IsExplicitlyRenderable() const { return renderableState.IsExplicit(); } 378 WebGLExtensionID GetExtensionID() const { 379 MOZ_ASSERT(renderableState.extid != WebGLExtensionID::Max); 380 return renderableState.extid; 381 } 382 383 bool IsUnpackValid(const PackingInfo& key, 384 const DriverUnpackInfo** const out_value) const; 385 386 private: 387 void ResolveMaxSamples(gl::GLContext& gl) const; 388 389 public: 390 uint32_t MaxSamples(gl::GLContext& gl) const { 391 if (!maxSamplesKnown) { 392 ResolveMaxSamples(gl); 393 } 394 return maxSamples; 395 } 396 }; 397 398 class FormatUsageAuthority { 399 std::map<EffectiveFormat, FormatUsageInfo> mUsageMap; 400 401 std::map<GLenum, const FormatUsageInfo*> mRBFormatMap; 402 std::map<GLenum, const FormatUsageInfo*> mSizedTexFormatMap; 403 std::map<PackingInfo, const FormatUsageInfo*> mUnsizedTexFormatMap; 404 405 std::set<GLenum> mValidTexInternalFormats; 406 std::set<GLenum> mValidTexUnpackFormats; 407 std::set<GLenum> mValidTexUnpackTypes; 408 409 public: 410 static std::unique_ptr<FormatUsageAuthority> CreateForWebGL1( 411 gl::GLContext* gl); 412 static std::unique_ptr<FormatUsageAuthority> CreateForWebGL2( 413 gl::GLContext* gl); 414 415 private: 416 FormatUsageAuthority() = default; 417 418 public: 419 FormatUsageInfo* EditUsage(EffectiveFormat format); 420 const FormatUsageInfo* GetUsage(EffectiveFormat format) const; 421 422 void AddTexUnpack(FormatUsageInfo* usage, const PackingInfo& pi, 423 const DriverUnpackInfo& dui); 424 425 bool IsInternalFormatEnumValid(GLenum internalFormat) const; 426 bool AreUnpackEnumsValid(GLenum unpackFormat, GLenum unpackType) const; 427 428 void AllowRBFormat(GLenum sizedFormat, const FormatUsageInfo* usage, 429 bool expectRenderable = true); 430 void AllowSizedTexFormat(GLenum sizedFormat, const FormatUsageInfo* usage); 431 void AllowUnsizedTexFormat(const PackingInfo& pi, 432 const FormatUsageInfo* usage); 433 434 const FormatUsageInfo* GetRBUsage(GLenum sizedFormat) const; 435 const FormatUsageInfo* GetSizedTexUsage(GLenum sizedFormat) const; 436 const FormatUsageInfo* GetUnsizedTexUsage(const PackingInfo& pi) const; 437 }; 438 439 } // namespace mozilla::webgl 440 441 #endif // WEBGL_FORMATS_H_