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