Bug 1769170 [wpt PR 34049] - Update wpt metadata, a=testonly
[gecko.git] / dom / canvas / WebGLFormats.cpp
blobc834043601e9b1c63d5ed656fb02931c54577d3e
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 #include "WebGLFormats.h"
8 #include "GLContext.h"
9 #include "GLDefs.h"
10 #include "mozilla/gfx/Logging.h"
11 #include "mozilla/StaticMutex.h"
13 namespace mozilla::webgl {
15 const char* ToString(const ComponentType type) {
16 switch (type) {
17 case ComponentType::Int:
18 return "Int";
19 case ComponentType::UInt:
20 return "UInt";
21 case ComponentType::NormInt:
22 return "NormInt";
23 case ComponentType::NormUInt:
24 return "NormUInt";
25 case ComponentType::Float:
26 return "Float";
28 MOZ_CRASH("pacify gcc6 warning");
31 static TextureBaseType ToBaseType(const ComponentType type) {
32 switch (type) {
33 case ComponentType::Int:
34 return TextureBaseType::Int;
35 case ComponentType::UInt:
36 return TextureBaseType::UInt;
37 case ComponentType::NormInt:
38 case ComponentType::NormUInt:
39 case ComponentType::Float:
40 // case ComponentType::Depth:
41 return TextureBaseType::Float;
43 MOZ_CRASH("pacify gcc6 warning");
46 const char* ToString(const TextureBaseType x) {
47 switch (x) {
48 case webgl::TextureBaseType::Float:
49 return "FLOAT";
50 case webgl::TextureBaseType::Int:
51 return "INT";
52 case webgl::TextureBaseType::UInt:
53 return "UINT";
55 MOZ_CRASH("pacify gcc6 warning");
58 // -
60 template <typename K, typename V, typename K2, typename V2>
61 static inline void AlwaysInsert(std::map<K, V>& dest, const K2& key,
62 const V2& val) {
63 auto res = dest.insert({key, val});
64 bool didInsert = res.second;
65 MOZ_ALWAYS_TRUE(didInsert);
68 template <typename K, typename V, typename K2>
69 static inline V* FindOrNull(const std::map<K, V*>& dest, const K2& key) {
70 auto itr = dest.find(key);
71 if (itr == dest.end()) return nullptr;
73 return itr->second;
76 // Returns a pointer to the in-place value for `key`.
77 template <typename C, typename K2>
78 static inline auto FindPtrOrNull(C& container, const K2& key) {
79 auto itr = container.find(key);
80 using R = decltype(&(itr->second));
81 if (itr == container.end()) return R{nullptr};
83 return &(itr->second);
86 //////////////////////////////////////////////////////////////////////////////////////////
88 std::map<EffectiveFormat, const CompressedFormatInfo> gCompressedFormatInfoMap;
89 std::map<EffectiveFormat, FormatInfo> gFormatInfoMap;
91 static inline const CompressedFormatInfo* GetCompressedFormatInfo(
92 EffectiveFormat format) {
93 MOZ_ASSERT(!gCompressedFormatInfoMap.empty());
94 return FindPtrOrNull(gCompressedFormatInfoMap, format);
97 static inline FormatInfo* GetFormatInfo_NoLock(EffectiveFormat format) {
98 MOZ_ASSERT(!gFormatInfoMap.empty());
99 return FindPtrOrNull(gFormatInfoMap, format);
102 //////////////////////////////////////////////////////////////////////////////////////////
104 static void AddCompressedFormatInfo(EffectiveFormat format,
105 uint16_t bitsPerBlock, uint8_t blockWidth,
106 uint8_t blockHeight,
107 CompressionFamily family) {
108 MOZ_ASSERT(bitsPerBlock % 8 == 0);
109 uint16_t bytesPerBlock = bitsPerBlock / 8; // The specs always state these in
110 // bits, but it's only ever useful
111 // to us as bytes.
112 MOZ_ASSERT(bytesPerBlock <= 255);
114 const CompressedFormatInfo info = {format, uint8_t(bytesPerBlock), blockWidth,
115 blockHeight, family};
116 AlwaysInsert(gCompressedFormatInfoMap, format, info);
119 static void InitCompressedFormatInfo() {
120 // clang-format off
122 // GLES 3.0.4, p147, table 3.19
123 // GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
124 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB8_ETC2 , 64, 4, 4, CompressionFamily::ES3);
125 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ETC2 , 64, 4, 4, CompressionFamily::ES3);
126 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA8_ETC2_EAC , 128, 4, 4, CompressionFamily::ES3);
127 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC , 128, 4, 4, CompressionFamily::ES3);
128 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_R11_EAC , 64, 4, 4, CompressionFamily::ES3);
129 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RG11_EAC , 128, 4, 4, CompressionFamily::ES3);
130 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SIGNED_R11_EAC , 64, 4, 4, CompressionFamily::ES3);
131 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SIGNED_RG11_EAC , 128, 4, 4, CompressionFamily::ES3);
132 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 , 64, 4, 4, CompressionFamily::ES3);
133 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 64, 4, 4, CompressionFamily::ES3);
135 // EXT_texture_compression_bptc
136 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_BPTC_UNORM , 16*8, 4, 4, CompressionFamily::BPTC);
137 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM , 16*8, 4, 4, CompressionFamily::BPTC);
138 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_BPTC_SIGNED_FLOAT , 16*8, 4, 4, CompressionFamily::BPTC);
139 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, 16*8, 4, 4, CompressionFamily::BPTC);
141 // EXT_texture_compression_rgtc
142 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RED_RGTC1 , 8*8, 4, 4, CompressionFamily::RGTC);
143 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SIGNED_RED_RGTC1, 8*8, 4, 4, CompressionFamily::RGTC);
144 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RG_RGTC2 , 16*8, 4, 4, CompressionFamily::RGTC);
145 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SIGNED_RG_RGTC2 , 16*8, 4, 4, CompressionFamily::RGTC);
147 // EXT_texture_compression_s3tc
148 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_S3TC_DXT1_EXT , 64, 4, 4, CompressionFamily::S3TC);
149 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_S3TC_DXT1_EXT, 64, 4, 4, CompressionFamily::S3TC);
150 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_S3TC_DXT3_EXT, 128, 4, 4, CompressionFamily::S3TC);
151 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_S3TC_DXT5_EXT, 128, 4, 4, CompressionFamily::S3TC);
153 // EXT_texture_compression_s3tc_srgb
154 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT , 64, 4, 4, CompressionFamily::S3TC);
155 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 64, 4, 4, CompressionFamily::S3TC);
156 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 128, 4, 4, CompressionFamily::S3TC);
157 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 128, 4, 4, CompressionFamily::S3TC);
159 // KHR_texture_compression_astc_ldr
160 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_4x4_KHR , 128, 4, 4, CompressionFamily::ASTC);
161 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_5x4_KHR , 128, 5, 4, CompressionFamily::ASTC);
162 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_5x5_KHR , 128, 5, 5, CompressionFamily::ASTC);
163 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_6x5_KHR , 128, 6, 5, CompressionFamily::ASTC);
164 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_6x6_KHR , 128, 6, 6, CompressionFamily::ASTC);
165 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_8x5_KHR , 128, 8, 5, CompressionFamily::ASTC);
166 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_8x6_KHR , 128, 8, 6, CompressionFamily::ASTC);
167 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_8x8_KHR , 128, 8, 8, CompressionFamily::ASTC);
168 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_10x5_KHR , 128, 10, 5, CompressionFamily::ASTC);
169 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_10x6_KHR , 128, 10, 6, CompressionFamily::ASTC);
170 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_10x8_KHR , 128, 10, 8, CompressionFamily::ASTC);
171 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_10x10_KHR , 128, 10, 10, CompressionFamily::ASTC);
172 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_12x10_KHR , 128, 12, 10, CompressionFamily::ASTC);
173 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_12x12_KHR , 128, 12, 12, CompressionFamily::ASTC);
175 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR , 128, 4, 4, CompressionFamily::ASTC);
176 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR , 128, 5, 4, CompressionFamily::ASTC);
177 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR , 128, 5, 5, CompressionFamily::ASTC);
178 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR , 128, 6, 5, CompressionFamily::ASTC);
179 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR , 128, 6, 6, CompressionFamily::ASTC);
180 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR , 128, 8, 5, CompressionFamily::ASTC);
181 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR , 128, 8, 6, CompressionFamily::ASTC);
182 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR , 128, 8, 8, CompressionFamily::ASTC);
183 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR , 128, 10, 5, CompressionFamily::ASTC);
184 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR , 128, 10, 6, CompressionFamily::ASTC);
185 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR , 128, 10, 8, CompressionFamily::ASTC);
186 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, 128, 10, 10, CompressionFamily::ASTC);
187 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, 128, 12, 10, CompressionFamily::ASTC);
188 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 128, 12, 12, CompressionFamily::ASTC);
190 // IMG_texture_compression_pvrtc
191 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_PVRTC_4BPPV1 , 256, 8, 8, CompressionFamily::PVRTC);
192 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_PVRTC_4BPPV1, 256, 8, 8, CompressionFamily::PVRTC);
193 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_PVRTC_2BPPV1 , 256, 16, 8, CompressionFamily::PVRTC);
194 AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_PVRTC_2BPPV1, 256, 16, 8, CompressionFamily::PVRTC);
196 // OES_compressed_ETC1_RGB8_texture
197 AddCompressedFormatInfo(EffectiveFormat::ETC1_RGB8_OES, 64, 4, 4, CompressionFamily::ETC1);
199 // clang-format on
202 //////////////////////////////////////////////////////////////////////////////////////////
204 static void AddFormatInfo(EffectiveFormat format, const char* name,
205 GLenum sizedFormat, uint8_t bytesPerPixel, uint8_t r,
206 uint8_t g, uint8_t b, uint8_t a, uint8_t d, uint8_t s,
207 UnsizedFormat unsizedFormat, bool isSRGB,
208 ComponentType componentType) {
209 switch (unsizedFormat) {
210 case UnsizedFormat::R:
211 MOZ_ASSERT(r && !g && !b && !a && !d && !s);
212 break;
214 case UnsizedFormat::RG:
215 MOZ_ASSERT(r && g && !b && !a && !d && !s);
216 break;
218 case UnsizedFormat::RGB:
219 MOZ_ASSERT(r && g && b && !a && !d && !s);
220 break;
222 case UnsizedFormat::RGBA:
223 MOZ_ASSERT(r && g && b && a && !d && !s);
224 break;
226 case UnsizedFormat::L:
227 MOZ_ASSERT(r && !g && !b && !a && !d && !s);
228 break;
230 case UnsizedFormat::A:
231 MOZ_ASSERT(!r && !g && !b && a && !d && !s);
232 break;
234 case UnsizedFormat::LA:
235 MOZ_ASSERT(r && !g && !b && a && !d && !s);
236 break;
238 case UnsizedFormat::D:
239 MOZ_ASSERT(!r && !g && !b && !a && d && !s);
240 break;
242 case UnsizedFormat::S:
243 MOZ_ASSERT(!r && !g && !b && !a && !d && s);
244 break;
246 case UnsizedFormat::DEPTH_STENCIL:
247 MOZ_ASSERT(!r && !g && !b && !a && d && s);
248 break;
251 const CompressedFormatInfo* compressedFormatInfo =
252 GetCompressedFormatInfo(format);
253 MOZ_ASSERT(!bytesPerPixel == bool(compressedFormatInfo));
255 #ifdef DEBUG
256 uint8_t totalBits = r + g + b + a + d + s;
257 if (format == EffectiveFormat::RGB9_E5) {
258 totalBits = 9 + 9 + 9 + 5;
261 if (compressedFormatInfo) {
262 MOZ_ASSERT(totalBits);
263 MOZ_ASSERT(!bytesPerPixel);
264 } else {
265 MOZ_ASSERT(totalBits == bytesPerPixel * 8);
267 #endif
269 const FormatInfo info = {format,
270 name,
271 sizedFormat,
272 unsizedFormat,
273 componentType,
274 ToBaseType(componentType),
275 isSRGB,
276 compressedFormatInfo,
277 bytesPerPixel,
284 AlwaysInsert(gFormatInfoMap, format, info);
287 static void InitFormatInfo() {
288 // This function is full of expressive formatting, so:
289 // clang-format off
291 #define FOO(x) EffectiveFormat::x, #x, LOCAL_GL_ ## x
293 // GLES 3.0.4, p130-132, table 3.13
294 AddFormatInfo(FOO(R8 ), 1, 8, 0, 0, 0, 0,0, UnsizedFormat::R , false, ComponentType::NormUInt);
295 AddFormatInfo(FOO(R8_SNORM ), 1, 8, 0, 0, 0, 0,0, UnsizedFormat::R , false, ComponentType::NormInt );
296 AddFormatInfo(FOO(RG8 ), 2, 8, 8, 0, 0, 0,0, UnsizedFormat::RG , false, ComponentType::NormUInt);
297 AddFormatInfo(FOO(RG8_SNORM ), 2, 8, 8, 0, 0, 0,0, UnsizedFormat::RG , false, ComponentType::NormInt );
298 AddFormatInfo(FOO(RGB8 ), 3, 8, 8, 8, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
299 AddFormatInfo(FOO(RGB8_SNORM ), 3, 8, 8, 8, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormInt );
300 AddFormatInfo(FOO(RGB565 ), 2, 5, 6, 5, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
301 AddFormatInfo(FOO(RGBA4 ), 2, 4, 4, 4, 4, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
302 AddFormatInfo(FOO(RGB5_A1 ), 2, 5, 5, 5, 1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
303 AddFormatInfo(FOO(RGBA8 ), 4, 8, 8, 8, 8, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
304 AddFormatInfo(FOO(RGBA8_SNORM ), 4, 8, 8, 8, 8, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormInt );
305 AddFormatInfo(FOO(RGB10_A2 ), 4, 10,10,10, 2, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
306 AddFormatInfo(FOO(RGB10_A2UI ), 4, 10,10,10, 2, 0,0, UnsizedFormat::RGBA, false, ComponentType::UInt );
308 AddFormatInfo(FOO(SRGB8 ), 3, 8, 8, 8, 0, 0,0, UnsizedFormat::RGB , true , ComponentType::NormUInt);
309 AddFormatInfo(FOO(SRGB8_ALPHA8 ), 4, 8, 8, 8, 8, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
311 AddFormatInfo(FOO(R16F ), 2, 16, 0, 0, 0, 0,0, UnsizedFormat::R , false, ComponentType::Float );
312 AddFormatInfo(FOO(RG16F ), 4, 16,16, 0, 0, 0,0, UnsizedFormat::RG , false, ComponentType::Float );
313 AddFormatInfo(FOO(RGB16F ), 6, 16,16,16, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::Float );
314 AddFormatInfo(FOO(RGBA16F ), 8, 16,16,16,16, 0,0, UnsizedFormat::RGBA, false, ComponentType::Float );
315 AddFormatInfo(FOO(R32F ), 4, 32, 0, 0, 0, 0,0, UnsizedFormat::R , false, ComponentType::Float );
316 AddFormatInfo(FOO(RG32F ), 8, 32,32, 0, 0, 0,0, UnsizedFormat::RG , false, ComponentType::Float );
317 AddFormatInfo(FOO(RGB32F ), 12, 32,32,32, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::Float );
318 AddFormatInfo(FOO(RGBA32F ), 16, 32,32,32,32, 0,0, UnsizedFormat::RGBA, false, ComponentType::Float );
320 AddFormatInfo(FOO(R11F_G11F_B10F), 4, 11,11,10, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::Float );
321 AddFormatInfo(FOO(RGB9_E5 ), 4, 14,14,14, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::Float );
323 AddFormatInfo(FOO(R8I ), 1, 8, 0, 0, 0, 0,0, UnsizedFormat::R , false, ComponentType::Int );
324 AddFormatInfo(FOO(R8UI ), 1, 8, 0, 0, 0, 0,0, UnsizedFormat::R , false, ComponentType::UInt );
325 AddFormatInfo(FOO(R16I ), 2, 16, 0, 0, 0, 0,0, UnsizedFormat::R , false, ComponentType::Int );
326 AddFormatInfo(FOO(R16UI ), 2, 16, 0, 0, 0, 0,0, UnsizedFormat::R , false, ComponentType::UInt );
327 AddFormatInfo(FOO(R32I ), 4, 32, 0, 0, 0, 0,0, UnsizedFormat::R , false, ComponentType::Int );
328 AddFormatInfo(FOO(R32UI ), 4, 32, 0, 0, 0, 0,0, UnsizedFormat::R , false, ComponentType::UInt );
330 AddFormatInfo(FOO(RG8I ), 2, 8, 8, 0, 0, 0,0, UnsizedFormat::RG , false, ComponentType::Int );
331 AddFormatInfo(FOO(RG8UI ), 2, 8, 8, 0, 0, 0,0, UnsizedFormat::RG , false, ComponentType::UInt );
332 AddFormatInfo(FOO(RG16I ), 4, 16,16, 0, 0, 0,0, UnsizedFormat::RG , false, ComponentType::Int );
333 AddFormatInfo(FOO(RG16UI ), 4, 16,16, 0, 0, 0,0, UnsizedFormat::RG , false, ComponentType::UInt );
334 AddFormatInfo(FOO(RG32I ), 8, 32,32, 0, 0, 0,0, UnsizedFormat::RG , false, ComponentType::Int );
335 AddFormatInfo(FOO(RG32UI ), 8, 32,32, 0, 0, 0,0, UnsizedFormat::RG , false, ComponentType::UInt );
337 AddFormatInfo(FOO(RGB8I ), 3, 8, 8, 8, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::Int );
338 AddFormatInfo(FOO(RGB8UI ), 3, 8, 8, 8, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::UInt );
339 AddFormatInfo(FOO(RGB16I ), 6, 16,16,16, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::Int );
340 AddFormatInfo(FOO(RGB16UI ), 6, 16,16,16, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::UInt );
341 AddFormatInfo(FOO(RGB32I ), 12, 32,32,32, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::Int );
342 AddFormatInfo(FOO(RGB32UI ), 12, 32,32,32, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::UInt );
344 AddFormatInfo(FOO(RGBA8I ), 4, 8, 8, 8, 8, 0,0, UnsizedFormat::RGBA, false, ComponentType::Int );
345 AddFormatInfo(FOO(RGBA8UI ), 4, 8, 8, 8, 8, 0,0, UnsizedFormat::RGBA, false, ComponentType::UInt );
346 AddFormatInfo(FOO(RGBA16I ), 8, 16,16,16,16, 0,0, UnsizedFormat::RGBA, false, ComponentType::Int );
347 AddFormatInfo(FOO(RGBA16UI ), 8, 16,16,16,16, 0,0, UnsizedFormat::RGBA, false, ComponentType::UInt );
348 AddFormatInfo(FOO(RGBA32I ), 16, 32,32,32,32, 0,0, UnsizedFormat::RGBA, false, ComponentType::Int );
349 AddFormatInfo(FOO(RGBA32UI ), 16, 32,32,32,32, 0,0, UnsizedFormat::RGBA, false, ComponentType::UInt );
351 // GLES 3.0.4, p133, table 3.14
352 AddFormatInfo(FOO(DEPTH_COMPONENT16 ), 2, 0,0,0,0, 16,0, UnsizedFormat::D , false, ComponentType::NormUInt);
353 AddFormatInfo(FOO(DEPTH_COMPONENT24 ), 3, 0,0,0,0, 24,0, UnsizedFormat::D , false, ComponentType::NormUInt);
354 AddFormatInfo(FOO(DEPTH_COMPONENT32F), 4, 0,0,0,0, 32,0, UnsizedFormat::D , false, ComponentType::Float);
355 // DEPTH_STENCIL types are sampled as their depth component.
356 AddFormatInfo(FOO(DEPTH24_STENCIL8 ), 4, 0,0,0,0, 24,8, UnsizedFormat::DEPTH_STENCIL, false, ComponentType::NormUInt);
357 AddFormatInfo(FOO(DEPTH32F_STENCIL8 ), 5, 0,0,0,0, 32,8, UnsizedFormat::DEPTH_STENCIL, false, ComponentType::Float);
359 // GLES 3.0.4, p205-206, "Required Renderbuffer Formats"
360 AddFormatInfo(FOO(STENCIL_INDEX8), 1, 0,0,0,0, 0,8, UnsizedFormat::S, false, ComponentType::Int);
362 // GLES 3.0.4, p147, table 3.19
363 // GLES 3.0.4 p286+ $C.1 "ETC Compressed Texture Image Formats"
364 AddFormatInfo(FOO(COMPRESSED_RGB8_ETC2 ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
365 AddFormatInfo(FOO(COMPRESSED_SRGB8_ETC2 ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , true , ComponentType::NormUInt);
366 AddFormatInfo(FOO(COMPRESSED_RGBA8_ETC2_EAC ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
367 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ETC2_EAC ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
368 AddFormatInfo(FOO(COMPRESSED_R11_EAC ), 0, 1,0,0,0, 0,0, UnsizedFormat::R , false, ComponentType::NormUInt);
369 AddFormatInfo(FOO(COMPRESSED_RG11_EAC ), 0, 1,1,0,0, 0,0, UnsizedFormat::RG , false, ComponentType::NormUInt);
370 AddFormatInfo(FOO(COMPRESSED_SIGNED_R11_EAC ), 0, 1,0,0,0, 0,0, UnsizedFormat::R , false, ComponentType::NormInt );
371 AddFormatInfo(FOO(COMPRESSED_SIGNED_RG11_EAC ), 0, 1,1,0,0, 0,0, UnsizedFormat::RG , false, ComponentType::NormInt );
372 AddFormatInfo(FOO(COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
373 AddFormatInfo(FOO(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
375 // EXT_texture_compression_bptc
376 AddFormatInfo(FOO(COMPRESSED_RGBA_BPTC_UNORM ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
377 AddFormatInfo(FOO(COMPRESSED_SRGB_ALPHA_BPTC_UNORM ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
378 AddFormatInfo(FOO(COMPRESSED_RGB_BPTC_SIGNED_FLOAT ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , false, ComponentType::Float );
379 AddFormatInfo(FOO(COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , false, ComponentType::Float );
381 // EXT_texture_compression_rgtc
382 AddFormatInfo(FOO(COMPRESSED_RED_RGTC1 ), 0, 1,0,0,0, 0,0, UnsizedFormat::R , false, ComponentType::NormUInt);
383 AddFormatInfo(FOO(COMPRESSED_SIGNED_RED_RGTC1), 0, 1,0,0,0, 0,0, UnsizedFormat::R , false, ComponentType::NormInt );
384 AddFormatInfo(FOO(COMPRESSED_RG_RGTC2 ), 0, 1,1,0,0, 0,0, UnsizedFormat::RG, false, ComponentType::NormUInt);
385 AddFormatInfo(FOO(COMPRESSED_SIGNED_RG_RGTC2 ), 0, 1,1,0,0, 0,0, UnsizedFormat::RG, false, ComponentType::NormInt );
387 // EXT_texture_compression_s3tc
388 AddFormatInfo(FOO(COMPRESSED_RGB_S3TC_DXT1_EXT ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
389 AddFormatInfo(FOO(COMPRESSED_RGBA_S3TC_DXT1_EXT), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
390 AddFormatInfo(FOO(COMPRESSED_RGBA_S3TC_DXT3_EXT), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
391 AddFormatInfo(FOO(COMPRESSED_RGBA_S3TC_DXT5_EXT), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
393 // EXT_texture_compression_s3tc_srgb
394 AddFormatInfo(FOO(COMPRESSED_SRGB_S3TC_DXT1_EXT ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , true, ComponentType::NormUInt);
395 AddFormatInfo(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true, ComponentType::NormUInt);
396 AddFormatInfo(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true, ComponentType::NormUInt);
397 AddFormatInfo(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true, ComponentType::NormUInt);
399 // KHR_texture_compression_astc_ldr
400 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_4x4_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
401 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_5x4_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
402 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_5x5_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
403 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_6x5_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
404 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_6x6_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
405 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_8x5_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
406 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_8x6_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
407 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_8x8_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
408 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_10x5_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
409 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_10x6_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
410 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_10x8_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
411 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_10x10_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
412 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_12x10_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
413 AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_12x12_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
415 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
416 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
417 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
418 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
419 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
420 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
421 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
422 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
423 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
424 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
425 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
426 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
427 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
428 AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
430 // IMG_texture_compression_pvrtc
431 AddFormatInfo(FOO(COMPRESSED_RGB_PVRTC_4BPPV1 ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
432 AddFormatInfo(FOO(COMPRESSED_RGBA_PVRTC_4BPPV1), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
433 AddFormatInfo(FOO(COMPRESSED_RGB_PVRTC_2BPPV1 ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
434 AddFormatInfo(FOO(COMPRESSED_RGBA_PVRTC_2BPPV1), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
436 // OES_compressed_ETC1_RGB8_texture
437 AddFormatInfo(FOO(ETC1_RGB8_OES), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB, false, ComponentType::NormUInt);
439 // EXT_texture_norm16
440 AddFormatInfo(FOO(R16 ), 2, 16, 0, 0, 0, 0,0, UnsizedFormat::R , false, ComponentType::NormUInt);
441 AddFormatInfo(FOO(RG16 ), 4, 16,16, 0, 0, 0,0, UnsizedFormat::RG , false, ComponentType::NormUInt);
442 AddFormatInfo(FOO(RGB16 ), 6, 16,16,16, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
443 AddFormatInfo(FOO(RGBA16), 8, 16,16,16,16, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
445 AddFormatInfo(FOO(R16_SNORM ), 2, 16, 0, 0, 0, 0,0, UnsizedFormat::R , false, ComponentType::NormInt);
446 AddFormatInfo(FOO(RG16_SNORM ), 4, 16,16, 0, 0, 0,0, UnsizedFormat::RG , false, ComponentType::NormInt);
447 AddFormatInfo(FOO(RGB16_SNORM ), 6, 16,16,16, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormInt);
448 AddFormatInfo(FOO(RGBA16_SNORM), 8, 16,16,16,16, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormInt);
450 #undef FOO
452 // 'Virtual' effective formats have no sizedFormat.
453 #define FOO(x) EffectiveFormat::x, #x, 0
455 // GLES 3.0.4, p128, table 3.12.
456 AddFormatInfo(FOO(Luminance8Alpha8), 2, 8,0,0,8, 0,0, UnsizedFormat::LA, false, ComponentType::NormUInt);
457 AddFormatInfo(FOO(Luminance8 ), 1, 8,0,0,0, 0,0, UnsizedFormat::L , false, ComponentType::NormUInt);
458 AddFormatInfo(FOO(Alpha8 ), 1, 0,0,0,8, 0,0, UnsizedFormat::A , false, ComponentType::NormUInt);
460 // OES_texture_float
461 AddFormatInfo(FOO(Luminance32FAlpha32F), 8, 32,0,0,32, 0,0, UnsizedFormat::LA, false, ComponentType::Float);
462 AddFormatInfo(FOO(Luminance32F ), 4, 32,0,0, 0, 0,0, UnsizedFormat::L , false, ComponentType::Float);
463 AddFormatInfo(FOO(Alpha32F ), 4, 0,0,0,32, 0,0, UnsizedFormat::A , false, ComponentType::Float);
465 // OES_texture_half_float
466 AddFormatInfo(FOO(Luminance16FAlpha16F), 4, 16,0,0,16, 0,0, UnsizedFormat::LA, false, ComponentType::Float);
467 AddFormatInfo(FOO(Luminance16F ), 2, 16,0,0, 0, 0,0, UnsizedFormat::L , false, ComponentType::Float);
468 AddFormatInfo(FOO(Alpha16F ), 2, 0,0,0,16, 0,0, UnsizedFormat::A , false, ComponentType::Float);
470 #undef FOO
472 ////////////////////////////////////////////////////////////////////////////
474 const auto fnSetCopyDecay = [](EffectiveFormat src, EffectiveFormat asR,
475 EffectiveFormat asRG, EffectiveFormat asRGB,
476 EffectiveFormat asRGBA, EffectiveFormat asL,
477 EffectiveFormat asA, EffectiveFormat asLA)
479 auto& map = GetFormatInfo_NoLock(src)->copyDecayFormats;
481 const auto fnSet = [&map](UnsizedFormat uf, EffectiveFormat ef) {
482 if (ef == EffectiveFormat::MAX)
483 return;
485 const auto* format = GetFormatInfo_NoLock(ef);
486 MOZ_ASSERT(format->unsizedFormat == uf);
487 AlwaysInsert(map, uf, format);
490 fnSet(UnsizedFormat::R , asR);
491 fnSet(UnsizedFormat::RG , asRG);
492 fnSet(UnsizedFormat::RGB , asRGB);
493 fnSet(UnsizedFormat::RGBA, asRGBA);
494 fnSet(UnsizedFormat::L , asL);
495 fnSet(UnsizedFormat::A , asA);
496 fnSet(UnsizedFormat::LA , asLA);
499 #define SET_COPY_DECAY(src,asR,asRG,asRGB,asRGBA,asL,asA,asLA) \
500 fnSetCopyDecay(EffectiveFormat::src, EffectiveFormat::asR, EffectiveFormat::asRG, \
501 EffectiveFormat::asRGB, EffectiveFormat::asRGBA, EffectiveFormat::asL, \
502 EffectiveFormat::asA, EffectiveFormat::asLA);
504 //////
506 #define SET_BY_SUFFIX(X) \
507 SET_COPY_DECAY( R##X, R##X, MAX, MAX, MAX, Luminance##X, MAX, MAX) \
508 SET_COPY_DECAY( RG##X, R##X, RG##X, MAX, MAX, Luminance##X, MAX, MAX) \
509 SET_COPY_DECAY( RGB##X, R##X, RG##X, RGB##X, MAX, Luminance##X, MAX, MAX) \
510 SET_COPY_DECAY(RGBA##X, R##X, RG##X, RGB##X, RGBA##X, Luminance##X, Alpha##X, Luminance##X##Alpha##X)
512 SET_BY_SUFFIX(8) // WebGL decided that RGB8 should be guaranteed renderable.
513 SET_BY_SUFFIX(16F) // RGB16F is renderable in EXT_color_buffer_half_float, though not
514 // EXT_color_buffer_float.
515 SET_BY_SUFFIX(32F) // Technically RGB32F is never renderable, but no harm here.
517 #undef SET_BY_SUFFIX
520 //////
522 #define SET_BY_SUFFIX(X) \
523 SET_COPY_DECAY( R##X, R##X, MAX, MAX, MAX, MAX, MAX, MAX) \
524 SET_COPY_DECAY( RG##X, R##X, RG##X, MAX, MAX, MAX, MAX, MAX) \
525 SET_COPY_DECAY(RGBA##X, R##X, RG##X, RGB##X, RGBA##X, MAX, MAX, MAX)
527 SET_BY_SUFFIX(8I)
528 SET_BY_SUFFIX(8UI)
530 SET_BY_SUFFIX(16)
531 SET_BY_SUFFIX(16I)
532 SET_BY_SUFFIX(16UI)
534 SET_BY_SUFFIX(32I)
535 SET_BY_SUFFIX(32UI)
537 #undef SET_BY_SUFFIX
539 //////
541 SET_COPY_DECAY( RGB565, R8, RG8, RGB565, MAX, Luminance8, MAX, MAX)
542 SET_COPY_DECAY( RGBA4, R8, RG8, RGB565, RGBA4, Luminance8, Alpha8, Luminance8Alpha8)
543 SET_COPY_DECAY( RGB5_A1, R8, RG8, RGB565, RGB5_A1, Luminance8, Alpha8, Luminance8Alpha8)
544 SET_COPY_DECAY( RGB10_A2, R8, RG8, RGB8, RGB10_A2, Luminance8, Alpha8, MAX)
546 SET_COPY_DECAY(RGB10_A2UI, R8UI, RG8UI, RGB8UI, RGB10_A2UI, MAX, MAX, MAX)
548 SET_COPY_DECAY(SRGB8_ALPHA8, MAX, MAX, MAX, SRGB8_ALPHA8, MAX, Alpha8, MAX)
550 SET_COPY_DECAY(R11F_G11F_B10F, R16F, RG16F, R11F_G11F_B10F, MAX, Luminance16F, MAX, MAX)
552 #undef SET_COPY_DECAY
554 // clang-format on
557 //////////////////////////////////////////////////////////////////////////////////////////
559 bool gAreFormatTablesInitialized = false;
561 static void EnsureInitFormatTables(
562 const StaticMutexAutoLock&) // Prove that you locked it!
564 if (MOZ_LIKELY(gAreFormatTablesInitialized)) return;
566 gAreFormatTablesInitialized = true;
568 InitCompressedFormatInfo();
569 InitFormatInfo();
572 //////////////////////////////////////////////////////////////////////////////////////////
573 // Public funcs
575 StaticMutex gFormatMapMutex;
577 const FormatInfo* GetFormat(EffectiveFormat format) {
578 StaticMutexAutoLock lock(gFormatMapMutex);
579 EnsureInitFormatTables(lock);
581 return GetFormatInfo_NoLock(format);
584 //////////////////////////////////////////////////////////////////////////////////////////
586 const FormatInfo* FormatInfo::GetCopyDecayFormat(UnsizedFormat uf) const {
587 return FindOrNull(this->copyDecayFormats, uf);
590 Maybe<PackingInfoInfo> PackingInfoInfo::For(const PackingInfo& pi) {
591 PackingInfoInfo ret{};
593 switch (pi.type) {
594 case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
595 case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
596 case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
597 ret = {2, 1, true};
598 break;
600 case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV:
601 case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
602 case LOCAL_GL_UNSIGNED_INT_24_8:
603 case LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV:
604 ret = {4, 1, true};
605 break;
607 case LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
608 ret = {8, 1, true};
609 break;
611 // Alright, that's all the fixed-size unpackTypes.
613 case LOCAL_GL_BYTE:
614 case LOCAL_GL_UNSIGNED_BYTE:
615 ret = {1, 0, false};
616 break;
618 case LOCAL_GL_SHORT:
619 case LOCAL_GL_UNSIGNED_SHORT:
620 case LOCAL_GL_HALF_FLOAT:
621 case LOCAL_GL_HALF_FLOAT_OES:
622 ret = {2, 0, false};
623 break;
625 case LOCAL_GL_INT:
626 case LOCAL_GL_UNSIGNED_INT:
627 case LOCAL_GL_FLOAT:
628 ret = {4, 0, false};
629 break;
631 default:
632 return {};
635 if (!ret.isPacked) {
636 switch (pi.format) {
637 case LOCAL_GL_RED:
638 case LOCAL_GL_RED_INTEGER:
639 case LOCAL_GL_LUMINANCE:
640 case LOCAL_GL_ALPHA:
641 case LOCAL_GL_DEPTH_COMPONENT:
642 ret.elementsPerPixel = 1;
643 break;
645 case LOCAL_GL_RG:
646 case LOCAL_GL_RG_INTEGER:
647 case LOCAL_GL_LUMINANCE_ALPHA:
648 ret.elementsPerPixel = 2;
649 break;
651 case LOCAL_GL_RGB:
652 case LOCAL_GL_RGB_INTEGER:
653 case LOCAL_GL_SRGB:
654 ret.elementsPerPixel = 3;
655 break;
657 case LOCAL_GL_BGRA:
658 case LOCAL_GL_RGBA:
659 case LOCAL_GL_RGBA_INTEGER:
660 case LOCAL_GL_SRGB_ALPHA:
661 ret.elementsPerPixel = 4;
662 break;
664 default:
665 return {};
669 return Some(ret);
672 bool GetBytesPerPixel(const PackingInfo& packing, uint8_t* const out_bytes) {
673 const auto pii = PackingInfoInfo::For(packing);
674 if (!pii) return false;
675 *out_bytes = pii->BytesPerPixel();
676 return true;
679 uint8_t BytesPerPixel(const PackingInfo& packing) {
680 uint8_t ret;
681 if (MOZ_LIKELY(GetBytesPerPixel(packing, &ret))) return ret;
683 gfxCriticalError() << "Bad `packing`: " << gfx::hexa(packing.format) << ", "
684 << gfx::hexa(packing.type);
685 MOZ_CRASH("Bad `packing`.");
688 //////////////////////////////////////////////////////////////////////////////////////////
689 //////////////////////////////////////////////////////////////////////////////////////////
690 //////////////////////////////////////////////////////////////////////////////////////////
691 //////////////////////////////////////////////////////////////////////////////////////////
692 //////////////////////////////////////////////////////////////////////////////////////////
693 //////////////////////////////////////////////////////////////////////////////////////////
694 //////////////////////////////////////////////////////////////////////////////////////////
695 //////////////////////////////////////////////////////////////////////////////////////////
696 // FormatUsageAuthority
698 bool FormatUsageInfo::IsUnpackValid(
699 const PackingInfo& key, const DriverUnpackInfo** const out_value) const {
700 auto itr = validUnpacks.find(key);
701 if (itr == validUnpacks.end()) return false;
703 *out_value = &(itr->second);
704 return true;
707 void FormatUsageInfo::ResolveMaxSamples(gl::GLContext& gl) const {
708 MOZ_ASSERT(gl.IsCurrent());
709 MOZ_ASSERT(!this->maxSamplesKnown);
710 MOZ_ASSERT(!this->maxSamples);
711 this->maxSamplesKnown = true;
713 const GLenum internalFormat = this->format->sizedFormat;
714 if (!internalFormat) return;
715 if (!gl.IsSupported(gl::GLFeature::internalformat_query)) return;
717 // GL_SAMPLES returns a list in descending order, so ask for just one elem to
718 // get the max.
719 gl.fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalFormat,
720 LOCAL_GL_SAMPLES, 1,
721 reinterpret_cast<GLint*>(&this->maxSamples));
724 ////////////////////////////////////////
726 static void AddSimpleUnsized(FormatUsageAuthority* fua, GLenum unpackFormat,
727 GLenum unpackType, EffectiveFormat effFormat) {
728 auto usage = fua->EditUsage(effFormat);
729 usage->isFilterable = true;
731 const PackingInfo pi = {unpackFormat, unpackType};
732 const DriverUnpackInfo dui = {unpackFormat, unpackFormat, unpackType};
733 fua->AddTexUnpack(usage, pi, dui);
735 fua->AllowUnsizedTexFormat(pi, usage);
738 /*static*/ const GLint FormatUsageInfo::kLuminanceSwizzleRGBA[4] = {
739 LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_ONE};
740 /*static*/ const GLint FormatUsageInfo::kAlphaSwizzleRGBA[4] = {
741 LOCAL_GL_ZERO, LOCAL_GL_ZERO, LOCAL_GL_ZERO, LOCAL_GL_RED};
742 /*static*/ const GLint FormatUsageInfo::kLumAlphaSwizzleRGBA[4] = {
743 LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_GREEN};
745 static bool AddLegacyFormats_LA8(FormatUsageAuthority* fua, gl::GLContext* gl) {
746 if (gl->IsCoreProfile()) {
747 if (!gl->IsSupported(gl::GLFeature::texture_swizzle)) return false;
749 PackingInfo pi;
750 DriverUnpackInfo dui;
752 const auto fnAdd = [fua, &pi, &dui](EffectiveFormat effFormat,
753 const GLint* swizzle) {
754 auto usage = fua->EditUsage(effFormat);
755 usage->isFilterable = true;
756 usage->textureSwizzleRGBA = swizzle;
758 fua->AddTexUnpack(usage, pi, dui);
760 fua->AllowUnsizedTexFormat(pi, usage);
763 pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_UNSIGNED_BYTE};
764 dui = {LOCAL_GL_R8, LOCAL_GL_RED, LOCAL_GL_UNSIGNED_BYTE};
765 fnAdd(EffectiveFormat::Luminance8, FormatUsageInfo::kLuminanceSwizzleRGBA);
767 pi = {LOCAL_GL_ALPHA, LOCAL_GL_UNSIGNED_BYTE};
768 dui = {LOCAL_GL_R8, LOCAL_GL_RED, LOCAL_GL_UNSIGNED_BYTE};
769 fnAdd(EffectiveFormat::Alpha8, FormatUsageInfo::kAlphaSwizzleRGBA);
771 pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_UNSIGNED_BYTE};
772 dui = {LOCAL_GL_RG8, LOCAL_GL_RG, LOCAL_GL_UNSIGNED_BYTE};
773 fnAdd(EffectiveFormat::Luminance8Alpha8,
774 FormatUsageInfo::kLumAlphaSwizzleRGBA);
775 } else {
776 // clang-format off
777 AddSimpleUnsized(fua, LOCAL_GL_LUMINANCE , LOCAL_GL_UNSIGNED_BYTE, EffectiveFormat::Luminance8 );
778 AddSimpleUnsized(fua, LOCAL_GL_ALPHA , LOCAL_GL_UNSIGNED_BYTE, EffectiveFormat::Alpha8 );
779 AddSimpleUnsized(fua, LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_UNSIGNED_BYTE, EffectiveFormat::Luminance8Alpha8);
780 // clang-format on
783 return true;
786 static bool AddUnsizedFormats(FormatUsageAuthority* fua, gl::GLContext* gl) {
787 // clang-format off
789 // GLES 2.0.25, p63, Table 3.4
790 AddSimpleUnsized(fua, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE , EffectiveFormat::RGBA8 );
791 AddSimpleUnsized(fua, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_4_4_4_4, EffectiveFormat::RGBA4 );
792 AddSimpleUnsized(fua, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_5_5_5_1, EffectiveFormat::RGB5_A1);
793 AddSimpleUnsized(fua, LOCAL_GL_RGB , LOCAL_GL_UNSIGNED_BYTE , EffectiveFormat::RGB8 );
794 AddSimpleUnsized(fua, LOCAL_GL_RGB , LOCAL_GL_UNSIGNED_SHORT_5_6_5 , EffectiveFormat::RGB565 );
796 // L, A, LA
797 return AddLegacyFormats_LA8(fua, gl);
799 // clang-format on
802 void FormatUsageInfo::SetRenderable(const FormatRenderableState& state) {
803 if (!renderableState.IsExplicit()) {
804 renderableState = state;
807 #ifdef DEBUG
808 const auto format = this->format;
809 if (format->IsColorFormat()) {
810 const auto& map = format->copyDecayFormats;
811 const auto itr = map.find(format->unsizedFormat);
812 MOZ_ASSERT(itr != map.end(),
813 "Renderable formats must be in copyDecayFormats.");
814 MOZ_ASSERT(itr->second == format);
816 #endif
819 UniquePtr<FormatUsageAuthority> FormatUsageAuthority::CreateForWebGL1(
820 gl::GLContext* gl) {
821 UniquePtr<FormatUsageAuthority> ret(new FormatUsageAuthority);
822 const auto ptr = ret.get();
824 ////////////////////////////////////////////////////////////////////////////
825 // Usages
827 const auto fnSet = [ptr](EffectiveFormat effFormat, bool isRenderable,
828 bool isFilterable) {
829 MOZ_ASSERT(!ptr->GetUsage(effFormat));
831 auto usage = ptr->EditUsage(effFormat);
832 usage->isFilterable = isFilterable;
834 if (isRenderable) {
835 usage->SetRenderable();
839 // GLES 2.0.25, p117, Table 4.5
840 // RGBA8 is made renderable in WebGL 1.0, "Framebuffer Object Attachments"
841 // render filter
842 // able able
843 fnSet(EffectiveFormat::RGBA8, true, true);
844 fnSet(EffectiveFormat::RGBA4, true, true);
845 fnSet(EffectiveFormat::RGB5_A1, true, true);
846 fnSet(EffectiveFormat::RGB565, true, true);
848 // RGB8 is not guaranteed to be renderable, but we should allow it for
849 // web-compat. Min-capability mode should mark this as non-renderable.
850 fnSet(EffectiveFormat::RGB8, true, true);
852 fnSet(EffectiveFormat::Luminance8Alpha8, false, true);
853 fnSet(EffectiveFormat::Luminance8, false, true);
854 fnSet(EffectiveFormat::Alpha8, false, true);
856 fnSet(EffectiveFormat::DEPTH_COMPONENT16, true, true);
857 fnSet(EffectiveFormat::DEPTH_COMPONENT24, true,
858 true); // Requires WEBGL_depth_texture.
859 fnSet(EffectiveFormat::STENCIL_INDEX8, true, false);
861 // Added in WebGL 1.0 spec:
862 fnSet(EffectiveFormat::DEPTH24_STENCIL8, true, true);
864 ////////////////////////////////////
865 // RB formats
867 #define FOO(x) \
868 ptr->AllowRBFormat(LOCAL_GL_##x, ptr->GetUsage(EffectiveFormat::x))
870 FOO(RGBA4);
871 FOO(RGB5_A1);
872 FOO(RGB565);
873 FOO(DEPTH_COMPONENT16);
874 FOO(STENCIL_INDEX8);
875 // FOO(DEPTH24_STENCIL8 ); // WebGL 1 uses DEPTH_STENCIL instead of
876 // DEPTH24_STENCIL8.
878 #undef FOO
880 ptr->AllowRBFormat(LOCAL_GL_DEPTH_STENCIL,
881 ptr->GetUsage(EffectiveFormat::DEPTH24_STENCIL8));
883 ////////////////////////////////////////////////////////////////////////////
885 if (!AddUnsizedFormats(ptr, gl)) return nullptr;
887 return ret;
890 UniquePtr<FormatUsageAuthority> FormatUsageAuthority::CreateForWebGL2(
891 gl::GLContext* gl) {
892 UniquePtr<FormatUsageAuthority> ret(new FormatUsageAuthority);
893 const auto ptr = ret.get();
895 ////////////////////////////////////////////////////////////////////////////
896 // GLES 3.0.4 p111-113
898 const auto fnAddSizedUnpack = [ptr](EffectiveFormat effFormat,
899 GLenum internalFormat,
900 GLenum unpackFormat, GLenum unpackType) {
901 auto usage = ptr->EditUsage(effFormat);
903 const PackingInfo pi = {unpackFormat, unpackType};
904 const DriverUnpackInfo dui = {internalFormat, unpackFormat, unpackType};
905 ptr->AddTexUnpack(usage, pi, dui);
908 // clang-format off
909 #define FOO(x) EffectiveFormat::x, LOCAL_GL_ ## x
911 // RGBA
912 fnAddSizedUnpack(FOO(RGBA8 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE );
913 fnAddSizedUnpack(FOO(RGBA4 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 );
914 fnAddSizedUnpack(FOO(RGBA4 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE );
915 fnAddSizedUnpack(FOO(RGB5_A1 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 );
916 fnAddSizedUnpack(FOO(RGB5_A1 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE );
917 fnAddSizedUnpack(FOO(RGB5_A1 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV);
918 fnAddSizedUnpack(FOO(SRGB8_ALPHA8), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE );
919 fnAddSizedUnpack(FOO(RGBA8_SNORM ), LOCAL_GL_RGBA, LOCAL_GL_BYTE );
920 fnAddSizedUnpack(FOO(RGB10_A2 ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV);
921 fnAddSizedUnpack(FOO(RGBA16F ), LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT );
922 fnAddSizedUnpack(FOO(RGBA16F ), LOCAL_GL_RGBA, LOCAL_GL_FLOAT );
923 fnAddSizedUnpack(FOO(RGBA32F ), LOCAL_GL_RGBA, LOCAL_GL_FLOAT );
925 // RGBA_INTEGER
926 fnAddSizedUnpack(FOO(RGBA8UI ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_UNSIGNED_BYTE );
927 fnAddSizedUnpack(FOO(RGBA8I ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_BYTE );
928 fnAddSizedUnpack(FOO(RGBA16UI ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_UNSIGNED_SHORT );
929 fnAddSizedUnpack(FOO(RGBA16I ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_SHORT );
930 fnAddSizedUnpack(FOO(RGBA32UI ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_UNSIGNED_INT );
931 fnAddSizedUnpack(FOO(RGBA32I ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_INT );
932 fnAddSizedUnpack(FOO(RGB10_A2UI), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV);
934 // RGB
935 fnAddSizedUnpack(FOO(RGB8 ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_BYTE );
936 fnAddSizedUnpack(FOO(SRGB8 ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_BYTE );
937 fnAddSizedUnpack(FOO(RGB565 ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_SHORT_5_6_5 );
938 fnAddSizedUnpack(FOO(RGB565 ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_BYTE );
939 fnAddSizedUnpack(FOO(RGB8_SNORM ), LOCAL_GL_RGB, LOCAL_GL_BYTE );
940 fnAddSizedUnpack(FOO(R11F_G11F_B10F), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV);
941 fnAddSizedUnpack(FOO(R11F_G11F_B10F), LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT );
942 fnAddSizedUnpack(FOO(R11F_G11F_B10F), LOCAL_GL_RGB, LOCAL_GL_FLOAT );
943 fnAddSizedUnpack(FOO(RGB16F ), LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT );
944 fnAddSizedUnpack(FOO(RGB16F ), LOCAL_GL_RGB, LOCAL_GL_FLOAT );
945 fnAddSizedUnpack(FOO(RGB9_E5 ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV );
946 fnAddSizedUnpack(FOO(RGB9_E5 ), LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT );
947 fnAddSizedUnpack(FOO(RGB9_E5 ), LOCAL_GL_RGB, LOCAL_GL_FLOAT );
948 fnAddSizedUnpack(FOO(RGB32F ), LOCAL_GL_RGB, LOCAL_GL_FLOAT );
950 // RGB_INTEGER
951 fnAddSizedUnpack(FOO(RGB8UI ), LOCAL_GL_RGB_INTEGER, LOCAL_GL_UNSIGNED_BYTE );
952 fnAddSizedUnpack(FOO(RGB8I ), LOCAL_GL_RGB_INTEGER, LOCAL_GL_BYTE );
953 fnAddSizedUnpack(FOO(RGB16UI), LOCAL_GL_RGB_INTEGER, LOCAL_GL_UNSIGNED_SHORT);
954 fnAddSizedUnpack(FOO(RGB16I ), LOCAL_GL_RGB_INTEGER, LOCAL_GL_SHORT );
955 fnAddSizedUnpack(FOO(RGB32UI), LOCAL_GL_RGB_INTEGER, LOCAL_GL_UNSIGNED_INT );
956 fnAddSizedUnpack(FOO(RGB32I ), LOCAL_GL_RGB_INTEGER, LOCAL_GL_INT );
958 // RG
959 fnAddSizedUnpack(FOO(RG8 ), LOCAL_GL_RG, LOCAL_GL_UNSIGNED_BYTE);
960 fnAddSizedUnpack(FOO(RG8_SNORM), LOCAL_GL_RG, LOCAL_GL_BYTE );
961 fnAddSizedUnpack(FOO(RG16F ), LOCAL_GL_RG, LOCAL_GL_HALF_FLOAT );
962 fnAddSizedUnpack(FOO(RG16F ), LOCAL_GL_RG, LOCAL_GL_FLOAT );
963 fnAddSizedUnpack(FOO(RG32F ), LOCAL_GL_RG, LOCAL_GL_FLOAT );
965 // RG_INTEGER
966 fnAddSizedUnpack(FOO(RG8UI ), LOCAL_GL_RG_INTEGER, LOCAL_GL_UNSIGNED_BYTE );
967 fnAddSizedUnpack(FOO(RG8I ), LOCAL_GL_RG_INTEGER, LOCAL_GL_BYTE );
968 fnAddSizedUnpack(FOO(RG16UI), LOCAL_GL_RG_INTEGER, LOCAL_GL_UNSIGNED_SHORT);
969 fnAddSizedUnpack(FOO(RG16I ), LOCAL_GL_RG_INTEGER, LOCAL_GL_SHORT );
970 fnAddSizedUnpack(FOO(RG32UI), LOCAL_GL_RG_INTEGER, LOCAL_GL_UNSIGNED_INT );
971 fnAddSizedUnpack(FOO(RG32I ), LOCAL_GL_RG_INTEGER, LOCAL_GL_INT );
973 // RED
974 fnAddSizedUnpack(FOO(R8 ), LOCAL_GL_RED, LOCAL_GL_UNSIGNED_BYTE);
975 fnAddSizedUnpack(FOO(R8_SNORM), LOCAL_GL_RED, LOCAL_GL_BYTE );
976 fnAddSizedUnpack(FOO(R16F ), LOCAL_GL_RED, LOCAL_GL_HALF_FLOAT );
977 fnAddSizedUnpack(FOO(R16F ), LOCAL_GL_RED, LOCAL_GL_FLOAT );
978 fnAddSizedUnpack(FOO(R32F ), LOCAL_GL_RED, LOCAL_GL_FLOAT );
980 // RED_INTEGER
981 fnAddSizedUnpack(FOO(R8UI ), LOCAL_GL_RED_INTEGER, LOCAL_GL_UNSIGNED_BYTE );
982 fnAddSizedUnpack(FOO(R8I ), LOCAL_GL_RED_INTEGER, LOCAL_GL_BYTE );
983 fnAddSizedUnpack(FOO(R16UI), LOCAL_GL_RED_INTEGER, LOCAL_GL_UNSIGNED_SHORT);
984 fnAddSizedUnpack(FOO(R16I ), LOCAL_GL_RED_INTEGER, LOCAL_GL_SHORT );
985 fnAddSizedUnpack(FOO(R32UI), LOCAL_GL_RED_INTEGER, LOCAL_GL_UNSIGNED_INT );
986 fnAddSizedUnpack(FOO(R32I ), LOCAL_GL_RED_INTEGER, LOCAL_GL_INT );
988 // DEPTH_COMPONENT
989 fnAddSizedUnpack(FOO(DEPTH_COMPONENT16 ), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_UNSIGNED_SHORT);
990 fnAddSizedUnpack(FOO(DEPTH_COMPONENT16 ), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_UNSIGNED_INT );
991 fnAddSizedUnpack(FOO(DEPTH_COMPONENT24 ), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_UNSIGNED_INT );
992 fnAddSizedUnpack(FOO(DEPTH_COMPONENT32F), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_FLOAT );
994 // DEPTH_STENCIL
995 fnAddSizedUnpack(FOO(DEPTH24_STENCIL8 ), LOCAL_GL_DEPTH_STENCIL, LOCAL_GL_UNSIGNED_INT_24_8 );
996 fnAddSizedUnpack(FOO(DEPTH32F_STENCIL8), LOCAL_GL_DEPTH_STENCIL, LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
998 #undef FOO
999 // clang-format on
1001 ////////////////////////////////////////////////////////////////////////////
1003 // For renderable, see GLES 3.0.4, p212 "Framebuffer Completeness"
1004 // For filterable, see GLES 3.0.4, p161 "...a texture is complete unless..."
1006 const auto fnAllowES3TexFormat = [ptr](GLenum sizedFormat,
1007 EffectiveFormat effFormat,
1008 bool isRenderable, bool isFilterable) {
1009 auto usage = ptr->EditUsage(effFormat);
1010 usage->isFilterable = isFilterable;
1012 if (isRenderable) {
1013 usage->SetRenderable();
1016 ptr->AllowSizedTexFormat(sizedFormat, usage);
1018 if (isRenderable) {
1019 ptr->AllowRBFormat(sizedFormat, usage);
1023 #define FOO(x) LOCAL_GL_##x, EffectiveFormat::x
1025 // GLES 3.0.4, p128-129 "Required Texture Formats"
1026 // GLES 3.0.4, p130-132, table 3.13
1027 // render filter
1028 // able able
1029 fnAllowES3TexFormat(FOO(R8), true, true);
1030 fnAllowES3TexFormat(FOO(R8_SNORM), false, true);
1031 fnAllowES3TexFormat(FOO(RG8), true, true);
1032 fnAllowES3TexFormat(FOO(RG8_SNORM), false, true);
1033 fnAllowES3TexFormat(FOO(RGB8), true, true);
1034 fnAllowES3TexFormat(FOO(RGB8_SNORM), false, true);
1035 fnAllowES3TexFormat(FOO(RGB565), true, true);
1036 fnAllowES3TexFormat(FOO(RGBA4), true, true);
1037 fnAllowES3TexFormat(FOO(RGB5_A1), true, true);
1038 fnAllowES3TexFormat(FOO(RGBA8), true, true);
1039 fnAllowES3TexFormat(FOO(RGBA8_SNORM), false, true);
1040 fnAllowES3TexFormat(FOO(RGB10_A2), true, true);
1041 fnAllowES3TexFormat(FOO(RGB10_A2UI), true, false);
1043 fnAllowES3TexFormat(FOO(SRGB8), false, true);
1044 fnAllowES3TexFormat(FOO(SRGB8_ALPHA8), true, true);
1046 fnAllowES3TexFormat(FOO(R16F), false, true);
1047 fnAllowES3TexFormat(FOO(RG16F), false, true);
1048 fnAllowES3TexFormat(FOO(RGB16F), false, true);
1049 fnAllowES3TexFormat(FOO(RGBA16F), false, true);
1051 fnAllowES3TexFormat(FOO(R32F), false, false);
1052 fnAllowES3TexFormat(FOO(RG32F), false, false);
1053 fnAllowES3TexFormat(FOO(RGB32F), false, false);
1054 fnAllowES3TexFormat(FOO(RGBA32F), false, false);
1056 fnAllowES3TexFormat(FOO(R11F_G11F_B10F), false, true);
1057 fnAllowES3TexFormat(FOO(RGB9_E5), false, true);
1059 fnAllowES3TexFormat(FOO(R8I), true, false);
1060 fnAllowES3TexFormat(FOO(R8UI), true, false);
1061 fnAllowES3TexFormat(FOO(R16I), true, false);
1062 fnAllowES3TexFormat(FOO(R16UI), true, false);
1063 fnAllowES3TexFormat(FOO(R32I), true, false);
1064 fnAllowES3TexFormat(FOO(R32UI), true, false);
1066 fnAllowES3TexFormat(FOO(RG8I), true, false);
1067 fnAllowES3TexFormat(FOO(RG8UI), true, false);
1068 fnAllowES3TexFormat(FOO(RG16I), true, false);
1069 fnAllowES3TexFormat(FOO(RG16UI), true, false);
1070 fnAllowES3TexFormat(FOO(RG32I), true, false);
1071 fnAllowES3TexFormat(FOO(RG32UI), true, false);
1073 fnAllowES3TexFormat(FOO(RGB8I), false, false);
1074 fnAllowES3TexFormat(FOO(RGB8UI), false, false);
1075 fnAllowES3TexFormat(FOO(RGB16I), false, false);
1076 fnAllowES3TexFormat(FOO(RGB16UI), false, false);
1077 fnAllowES3TexFormat(FOO(RGB32I), false, false);
1078 fnAllowES3TexFormat(FOO(RGB32UI), false, false);
1080 fnAllowES3TexFormat(FOO(RGBA8I), true, false);
1081 fnAllowES3TexFormat(FOO(RGBA8UI), true, false);
1082 fnAllowES3TexFormat(FOO(RGBA16I), true, false);
1083 fnAllowES3TexFormat(FOO(RGBA16UI), true, false);
1084 fnAllowES3TexFormat(FOO(RGBA32I), true, false);
1085 fnAllowES3TexFormat(FOO(RGBA32UI), true, false);
1087 // Sized depth or depth-stencil formats are not filterable
1088 // per GLES 3.0.6 p161.
1089 // Specifically, they're texture-incomplete if depth-compare:none and
1090 // not NEAREST.
1091 fnAllowES3TexFormat(FOO(DEPTH_COMPONENT16), true, false);
1092 fnAllowES3TexFormat(FOO(DEPTH_COMPONENT24), true, false);
1093 fnAllowES3TexFormat(FOO(DEPTH_COMPONENT32F), true, false);
1094 fnAllowES3TexFormat(FOO(DEPTH24_STENCIL8), true, false);
1095 fnAllowES3TexFormat(FOO(DEPTH32F_STENCIL8), true, false);
1097 #undef FOO
1099 // GLES 3.0.4, p206, "Required Renderbuffer Formats":
1100 // "Implementations are also required to support STENCIL_INDEX8. Requesting
1101 // this internal format for a renderbuffer will allocate at least 8 stencil
1102 // bit planes."
1104 auto usage = ptr->EditUsage(EffectiveFormat::STENCIL_INDEX8);
1105 usage->SetRenderable();
1106 ptr->AllowRBFormat(LOCAL_GL_STENCIL_INDEX8, usage);
1108 ////////////////
1109 // Legacy formats
1111 if (!AddUnsizedFormats(ptr, gl)) return nullptr;
1113 ptr->AllowRBFormat(LOCAL_GL_DEPTH_STENCIL,
1114 ptr->GetUsage(EffectiveFormat::DEPTH24_STENCIL8));
1116 ////////////////////////////////////
1118 return ret;
1121 //////////////////////////////////////////////////////////////////////////////////////////
1123 void FormatUsageAuthority::AddTexUnpack(FormatUsageInfo* usage,
1124 const PackingInfo& pi,
1125 const DriverUnpackInfo& dui) {
1126 // Don't AlwaysInsert here, since we'll see duplicates from sized and unsized
1127 // formats.
1128 auto res = usage->validUnpacks.insert({pi, dui});
1129 auto itr = res.first;
1131 if (!usage->idealUnpack) {
1132 // First one!
1133 usage->idealUnpack = &(itr->second);
1136 mValidTexUnpackFormats.insert(pi.format);
1137 mValidTexUnpackTypes.insert(pi.type);
1140 static bool Contains(const std::set<GLenum>& set, GLenum key) {
1141 return set.find(key) != set.end();
1144 bool FormatUsageAuthority::IsInternalFormatEnumValid(
1145 GLenum internalFormat) const {
1146 return Contains(mValidTexInternalFormats, internalFormat);
1149 bool FormatUsageAuthority::AreUnpackEnumsValid(GLenum unpackFormat,
1150 GLenum unpackType) const {
1151 return (Contains(mValidTexUnpackFormats, unpackFormat) &&
1152 Contains(mValidTexUnpackTypes, unpackType));
1155 ////////////////////
1157 void FormatUsageAuthority::AllowRBFormat(GLenum sizedFormat,
1158 const FormatUsageInfo* usage,
1159 const bool expectRenderable) {
1160 MOZ_ASSERT(!usage->format->compression);
1161 MOZ_ASSERT(usage->format->sizedFormat);
1162 MOZ_ASSERT(usage->IsRenderable() || !expectRenderable);
1164 const auto& found = mRBFormatMap.find(sizedFormat);
1165 if (found != mRBFormatMap.end()) {
1166 MOZ_ASSERT(found->second == usage);
1167 return;
1169 AlwaysInsert(mRBFormatMap, sizedFormat, usage);
1172 void FormatUsageAuthority::AllowSizedTexFormat(GLenum sizedFormat,
1173 const FormatUsageInfo* usage) {
1174 if (usage->format->compression) {
1175 MOZ_ASSERT(usage->isFilterable, "Compressed formats should be filterable.");
1176 } else {
1177 MOZ_ASSERT(!usage->validUnpacks.empty() && usage->idealUnpack,
1178 "AddTexUnpack() first.");
1181 AlwaysInsert(mSizedTexFormatMap, sizedFormat, usage);
1183 mValidTexInternalFormats.insert(sizedFormat);
1186 void FormatUsageAuthority::AllowUnsizedTexFormat(const PackingInfo& pi,
1187 const FormatUsageInfo* usage) {
1188 MOZ_ASSERT(!usage->format->compression);
1189 MOZ_ASSERT(!usage->validUnpacks.empty() && usage->idealUnpack,
1190 "AddTexUnpack() first.");
1192 AlwaysInsert(mUnsizedTexFormatMap, pi, usage);
1194 mValidTexInternalFormats.insert(pi.format);
1195 mValidTexUnpackFormats.insert(pi.format);
1196 mValidTexUnpackTypes.insert(pi.type);
1199 const FormatUsageInfo* FormatUsageAuthority::GetRBUsage(
1200 GLenum sizedFormat) const {
1201 return FindOrNull(mRBFormatMap, sizedFormat);
1204 const FormatUsageInfo* FormatUsageAuthority::GetSizedTexUsage(
1205 GLenum sizedFormat) const {
1206 return FindOrNull(mSizedTexFormatMap, sizedFormat);
1209 const FormatUsageInfo* FormatUsageAuthority::GetUnsizedTexUsage(
1210 const PackingInfo& pi) const {
1211 return FindOrNull(mUnsizedTexFormatMap, pi);
1214 FormatUsageInfo* FormatUsageAuthority::EditUsage(EffectiveFormat format) {
1215 auto itr = mUsageMap.find(format);
1217 if (itr == mUsageMap.end()) {
1218 const FormatInfo* formatInfo = GetFormat(format);
1219 MOZ_RELEASE_ASSERT(formatInfo, "GFX: no format info set.");
1221 FormatUsageInfo usage(formatInfo);
1223 auto res = mUsageMap.insert({format, usage});
1224 DebugOnly<bool> didInsert = res.second;
1225 MOZ_ASSERT(didInsert);
1227 itr = res.first;
1230 return &(itr->second);
1233 const FormatUsageInfo* FormatUsageAuthority::GetUsage(
1234 EffectiveFormat format) const {
1235 auto itr = mUsageMap.find(format);
1236 if (itr == mUsageMap.end()) return nullptr;
1238 return &(itr->second);
1241 ////////////////////////////////////////////////////////////////////////////////
1243 } // namespace mozilla::webgl