1 // Copyright 2014 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4
5 #pragma once
6
7 #include <climits>
8 #include <utility>
9 #include "common/assert.h"
10 #include "common/common_types.h"
11 #include "common/logging/log.h"
12 #include "video_core/gpu.h"
13 #include "video_core/textures/texture.h"
14
15 namespace VideoCore::Surface {
16
17 enum class PixelFormat {
18 A8B8G8R8_UNORM,
19 A8B8G8R8_SNORM,
20 A8B8G8R8_SINT,
21 A8B8G8R8_UINT,
22 R5G6B5_UNORM,
23 B5G6R5_UNORM,
24 A1R5G5B5_UNORM,
25 A2B10G10R10_UNORM,
26 A2B10G10R10_UINT,
27 A1B5G5R5_UNORM,
28 R8_UNORM,
29 R8_SNORM,
30 R8_SINT,
31 R8_UINT,
32 R16G16B16A16_FLOAT,
33 R16G16B16A16_UNORM,
34 R16G16B16A16_SNORM,
35 R16G16B16A16_SINT,
36 R16G16B16A16_UINT,
37 B10G11R11_FLOAT,
38 R32G32B32A32_UINT,
39 BC1_RGBA_UNORM,
40 BC2_UNORM,
41 BC3_UNORM,
42 BC4_UNORM,
43 BC4_SNORM,
44 BC5_UNORM,
45 BC5_SNORM,
46 BC7_UNORM,
47 BC6H_UFLOAT,
48 BC6H_SFLOAT,
49 ASTC_2D_4X4_UNORM,
50 B8G8R8A8_UNORM,
51 R32G32B32A32_FLOAT,
52 R32G32B32A32_SINT,
53 R32G32_FLOAT,
54 R32G32_SINT,
55 R32_FLOAT,
56 R16_FLOAT,
57 R16_UNORM,
58 R16_SNORM,
59 R16_UINT,
60 R16_SINT,
61 R16G16_UNORM,
62 R16G16_FLOAT,
63 R16G16_UINT,
64 R16G16_SINT,
65 R16G16_SNORM,
66 R32G32B32_FLOAT,
67 A8B8G8R8_SRGB,
68 R8G8_UNORM,
69 R8G8_SNORM,
70 R8G8_SINT,
71 R8G8_UINT,
72 R32G32_UINT,
73 R16G16B16X16_FLOAT,
74 R32_UINT,
75 R32_SINT,
76 ASTC_2D_8X8_UNORM,
77 ASTC_2D_8X5_UNORM,
78 ASTC_2D_5X4_UNORM,
79 B8G8R8A8_SRGB,
80 BC1_RGBA_SRGB,
81 BC2_SRGB,
82 BC3_SRGB,
83 BC7_SRGB,
84 A4B4G4R4_UNORM,
85 ASTC_2D_4X4_SRGB,
86 ASTC_2D_8X8_SRGB,
87 ASTC_2D_8X5_SRGB,
88 ASTC_2D_5X4_SRGB,
89 ASTC_2D_5X5_UNORM,
90 ASTC_2D_5X5_SRGB,
91 ASTC_2D_10X8_UNORM,
92 ASTC_2D_10X8_SRGB,
93 ASTC_2D_6X6_UNORM,
94 ASTC_2D_6X6_SRGB,
95 ASTC_2D_10X10_UNORM,
96 ASTC_2D_10X10_SRGB,
97 ASTC_2D_12X12_UNORM,
98 ASTC_2D_12X12_SRGB,
99 ASTC_2D_8X6_UNORM,
100 ASTC_2D_8X6_SRGB,
101 ASTC_2D_6X5_UNORM,
102 ASTC_2D_6X5_SRGB,
103 E5B9G9R9_FLOAT,
104
105 MaxColorFormat,
106
107 // Depth formats
108 D32_FLOAT = MaxColorFormat,
109 D16_UNORM,
110
111 MaxDepthFormat,
112
113 // DepthStencil formats
114 D24_UNORM_S8_UINT = MaxDepthFormat,
115 S8_UINT_D24_UNORM,
116 D32_FLOAT_S8_UINT,
117
118 MaxDepthStencilFormat,
119
120 Max = MaxDepthStencilFormat,
121 Invalid = 255,
122 };
123 static constexpr std::size_t MaxPixelFormat = static_cast<std::size_t>(PixelFormat::Max);
124
125 enum class SurfaceType {
126 ColorTexture = 0,
127 Depth = 1,
128 DepthStencil = 2,
129 Invalid = 3,
130 };
131
132 enum class SurfaceTarget {
133 Texture1D,
134 TextureBuffer,
135 Texture2D,
136 Texture3D,
137 Texture1DArray,
138 Texture2DArray,
139 TextureCubemap,
140 TextureCubeArray,
141 };
142
143 constexpr std::array<u32, MaxPixelFormat> compression_factor_shift_table = {{
144 0, // A8B8G8R8_UNORM
145 0, // A8B8G8R8_SNORM
146 0, // A8B8G8R8_SINT
147 0, // A8B8G8R8_UINT
148 0, // R5G6B5_UNORM
149 0, // B5G6R5_UNORM
150 0, // A1R5G5B5_UNORM
151 0, // A2B10G10R10_UNORM
152 0, // A2B10G10R10_UINT
153 0, // A1B5G5R5_UNORM
154 0, // R8_UNORM
155 0, // R8_SNORM
156 0, // R8_SINT
157 0, // R8_UINT
158 0, // R16G16B16A16_FLOAT
159 0, // R16G16B16A16_UNORM
160 0, // R16G16B16A16_SNORM
161 0, // R16G16B16A16_SINT
162 0, // R16G16B16A16_UINT
163 0, // B10G11R11_FLOAT
164 0, // R32G32B32A32_UINT
165 2, // BC1_RGBA_UNORM
166 2, // BC2_UNORM
167 2, // BC3_UNORM
168 2, // BC4_UNORM
169 2, // BC4_SNORM
170 2, // BC5_UNORM
171 2, // BC5_SNORM
172 2, // BC7_UNORM
173 2, // BC6H_UFLOAT
174 2, // BC6H_SFLOAT
175 2, // ASTC_2D_4X4_UNORM
176 0, // B8G8R8A8_UNORM
177 0, // R32G32B32A32_FLOAT
178 0, // R32G32B32A32_SINT
179 0, // R32G32_FLOAT
180 0, // R32G32_SINT
181 0, // R32_FLOAT
182 0, // R16_FLOAT
183 0, // R16_UNORM
184 0, // R16_SNORM
185 0, // R16_UINT
186 0, // R16_SINT
187 0, // R16G16_UNORM
188 0, // R16G16_FLOAT
189 0, // R16G16_UINT
190 0, // R16G16_SINT
191 0, // R16G16_SNORM
192 0, // R32G32B32_FLOAT
193 0, // A8B8G8R8_SRGB
194 0, // R8G8_UNORM
195 0, // R8G8_SNORM
196 0, // R8G8_SINT
197 0, // R8G8_UINT
198 0, // R32G32_UINT
199 0, // R16G16B16X16_FLOAT
200 0, // R32_UINT
201 0, // R32_SINT
202 2, // ASTC_2D_8X8_UNORM
203 2, // ASTC_2D_8X5_UNORM
204 2, // ASTC_2D_5X4_UNORM
205 0, // B8G8R8A8_SRGB
206 2, // BC1_RGBA_SRGB
207 2, // BC2_SRGB
208 2, // BC3_SRGB
209 2, // BC7_SRGB
210 0, // A4B4G4R4_UNORM
211 2, // ASTC_2D_4X4_SRGB
212 2, // ASTC_2D_8X8_SRGB
213 2, // ASTC_2D_8X5_SRGB
214 2, // ASTC_2D_5X4_SRGB
215 2, // ASTC_2D_5X5_UNORM
216 2, // ASTC_2D_5X5_SRGB
217 2, // ASTC_2D_10X8_UNORM
218 2, // ASTC_2D_10X8_SRGB
219 2, // ASTC_2D_6X6_UNORM
220 2, // ASTC_2D_6X6_SRGB
221 2, // ASTC_2D_10X10_UNORM
222 2, // ASTC_2D_10X10_SRGB
223 2, // ASTC_2D_12X12_UNORM
224 2, // ASTC_2D_12X12_SRGB
225 2, // ASTC_2D_8X6_UNORM
226 2, // ASTC_2D_8X6_SRGB
227 2, // ASTC_2D_6X5_UNORM
228 2, // ASTC_2D_6X5_SRGB
229 0, // E5B9G9R9_FLOAT
230 0, // D32_FLOAT
231 0, // D16_UNORM
232 0, // D24_UNORM_S8_UINT
233 0, // S8_UINT_D24_UNORM
234 0, // D32_FLOAT_S8_UINT
235 }};
236
237 /**
238 * Gets the compression factor for the specified PixelFormat. This applies to just the
239 * "compressed width" and "compressed height", not the overall compression factor of a
240 * compressed image. This is used for maintaining proper surface sizes for compressed
241 * texture formats.
242 */
GetCompressionFactorShift(PixelFormat format)243 inline constexpr u32 GetCompressionFactorShift(PixelFormat format) {
244 DEBUG_ASSERT(format != PixelFormat::Invalid);
245 DEBUG_ASSERT(static_cast<std::size_t>(format) < compression_factor_shift_table.size());
246 return compression_factor_shift_table[static_cast<std::size_t>(format)];
247 }
248
GetCompressionFactor(PixelFormat format)249 inline constexpr u32 GetCompressionFactor(PixelFormat format) {
250 return 1U << GetCompressionFactorShift(format);
251 }
252
253 constexpr std::array<u32, MaxPixelFormat> block_width_table = {{
254 1, // A8B8G8R8_UNORM
255 1, // A8B8G8R8_SNORM
256 1, // A8B8G8R8_SINT
257 1, // A8B8G8R8_UINT
258 1, // R5G6B5_UNORM
259 1, // B5G6R5_UNORM
260 1, // A1R5G5B5_UNORM
261 1, // A2B10G10R10_UNORM
262 1, // A2B10G10R10_UINT
263 1, // A1B5G5R5_UNORM
264 1, // R8_UNORM
265 1, // R8_SNORM
266 1, // R8_SINT
267 1, // R8_UINT
268 1, // R16G16B16A16_FLOAT
269 1, // R16G16B16A16_UNORM
270 1, // R16G16B16A16_SNORM
271 1, // R16G16B16A16_SINT
272 1, // R16G16B16A16_UINT
273 1, // B10G11R11_FLOAT
274 1, // R32G32B32A32_UINT
275 4, // BC1_RGBA_UNORM
276 4, // BC2_UNORM
277 4, // BC3_UNORM
278 4, // BC4_UNORM
279 4, // BC4_SNORM
280 4, // BC5_UNORM
281 4, // BC5_SNORM
282 4, // BC7_UNORM
283 4, // BC6H_UFLOAT
284 4, // BC6H_SFLOAT
285 4, // ASTC_2D_4X4_UNORM
286 1, // B8G8R8A8_UNORM
287 1, // R32G32B32A32_FLOAT
288 1, // R32G32B32A32_SINT
289 1, // R32G32_FLOAT
290 1, // R32G32_SINT
291 1, // R32_FLOAT
292 1, // R16_FLOAT
293 1, // R16_UNORM
294 1, // R16_SNORM
295 1, // R16_UINT
296 1, // R16_SINT
297 1, // R16G16_UNORM
298 1, // R16G16_FLOAT
299 1, // R16G16_UINT
300 1, // R16G16_SINT
301 1, // R16G16_SNORM
302 1, // R32G32B32_FLOAT
303 1, // A8B8G8R8_SRGB
304 1, // R8G8_UNORM
305 1, // R8G8_SNORM
306 1, // R8G8_SINT
307 1, // R8G8_UINT
308 1, // R32G32_UINT
309 1, // R16G16B16X16_FLOAT
310 1, // R32_UINT
311 1, // R32_SINT
312 8, // ASTC_2D_8X8_UNORM
313 8, // ASTC_2D_8X5_UNORM
314 5, // ASTC_2D_5X4_UNORM
315 1, // B8G8R8A8_SRGB
316 4, // BC1_RGBA_SRGB
317 4, // BC2_SRGB
318 4, // BC3_SRGB
319 4, // BC7_SRGB
320 1, // A4B4G4R4_UNORM
321 4, // ASTC_2D_4X4_SRGB
322 8, // ASTC_2D_8X8_SRGB
323 8, // ASTC_2D_8X5_SRGB
324 5, // ASTC_2D_5X4_SRGB
325 5, // ASTC_2D_5X5_UNORM
326 5, // ASTC_2D_5X5_SRGB
327 10, // ASTC_2D_10X8_UNORM
328 10, // ASTC_2D_10X8_SRGB
329 6, // ASTC_2D_6X6_UNORM
330 6, // ASTC_2D_6X6_SRGB
331 10, // ASTC_2D_10X10_UNORM
332 10, // ASTC_2D_10X10_SRGB
333 12, // ASTC_2D_12X12_UNORM
334 12, // ASTC_2D_12X12_SRGB
335 8, // ASTC_2D_8X6_UNORM
336 8, // ASTC_2D_8X6_SRGB
337 6, // ASTC_2D_6X5_UNORM
338 6, // ASTC_2D_6X5_SRGB
339 1, // E5B9G9R9_FLOAT
340 1, // D32_FLOAT
341 1, // D16_UNORM
342 1, // D24_UNORM_S8_UINT
343 1, // S8_UINT_D24_UNORM
344 1, // D32_FLOAT_S8_UINT
345 }};
346
GetDefaultBlockWidth(PixelFormat format)347 static constexpr u32 GetDefaultBlockWidth(PixelFormat format) {
348 if (format == PixelFormat::Invalid)
349 return 0;
350
351 ASSERT(static_cast<std::size_t>(format) < block_width_table.size());
352 return block_width_table[static_cast<std::size_t>(format)];
353 }
354
355 constexpr std::array<u32, MaxPixelFormat> block_height_table = {{
356 1, // A8B8G8R8_UNORM
357 1, // A8B8G8R8_SNORM
358 1, // A8B8G8R8_SINT
359 1, // A8B8G8R8_UINT
360 1, // R5G6B5_UNORM
361 1, // B5G6R5_UNORM
362 1, // A1R5G5B5_UNORM
363 1, // A2B10G10R10_UNORM
364 1, // A2B10G10R10_UINT
365 1, // A1B5G5R5_UNORM
366 1, // R8_UNORM
367 1, // R8_SNORM
368 1, // R8_SINT
369 1, // R8_UINT
370 1, // R16G16B16A16_FLOAT
371 1, // R16G16B16A16_UNORM
372 1, // R16G16B16A16_SNORM
373 1, // R16G16B16A16_SINT
374 1, // R16G16B16A16_UINT
375 1, // B10G11R11_FLOAT
376 1, // R32G32B32A32_UINT
377 4, // BC1_RGBA_UNORM
378 4, // BC2_UNORM
379 4, // BC3_UNORM
380 4, // BC4_UNORM
381 4, // BC4_SNORM
382 4, // BC5_UNORM
383 4, // BC5_SNORM
384 4, // BC7_UNORM
385 4, // BC6H_UFLOAT
386 4, // BC6H_SFLOAT
387 4, // ASTC_2D_4X4_UNORM
388 1, // B8G8R8A8_UNORM
389 1, // R32G32B32A32_FLOAT
390 1, // R32G32B32A32_SINT
391 1, // R32G32_FLOAT
392 1, // R32G32_SINT
393 1, // R32_FLOAT
394 1, // R16_FLOAT
395 1, // R16_UNORM
396 1, // R16_SNORM
397 1, // R16_UINT
398 1, // R16_SINT
399 1, // R16G16_UNORM
400 1, // R16G16_FLOAT
401 1, // R16G16_UINT
402 1, // R16G16_SINT
403 1, // R16G16_SNORM
404 1, // R32G32B32_FLOAT
405 1, // A8B8G8R8_SRGB
406 1, // R8G8_UNORM
407 1, // R8G8_SNORM
408 1, // R8G8_SINT
409 1, // R8G8_UINT
410 1, // R32G32_UINT
411 1, // R16G16B16X16_FLOAT
412 1, // R32_UINT
413 1, // R32_SINT
414 8, // ASTC_2D_8X8_UNORM
415 5, // ASTC_2D_8X5_UNORM
416 4, // ASTC_2D_5X4_UNORM
417 1, // B8G8R8A8_SRGB
418 4, // BC1_RGBA_SRGB
419 4, // BC2_SRGB
420 4, // BC3_SRGB
421 4, // BC7_SRGB
422 1, // A4B4G4R4_UNORM
423 4, // ASTC_2D_4X4_SRGB
424 8, // ASTC_2D_8X8_SRGB
425 5, // ASTC_2D_8X5_SRGB
426 4, // ASTC_2D_5X4_SRGB
427 5, // ASTC_2D_5X5_UNORM
428 5, // ASTC_2D_5X5_SRGB
429 8, // ASTC_2D_10X8_UNORM
430 8, // ASTC_2D_10X8_SRGB
431 6, // ASTC_2D_6X6_UNORM
432 6, // ASTC_2D_6X6_SRGB
433 10, // ASTC_2D_10X10_UNORM
434 10, // ASTC_2D_10X10_SRGB
435 12, // ASTC_2D_12X12_UNORM
436 12, // ASTC_2D_12X12_SRGB
437 6, // ASTC_2D_8X6_UNORM
438 6, // ASTC_2D_8X6_SRGB
439 5, // ASTC_2D_6X5_UNORM
440 5, // ASTC_2D_6X5_SRGB
441 1, // E5B9G9R9_FLOAT
442 1, // D32_FLOAT
443 1, // D16_UNORM
444 1, // D24_UNORM_S8_UINT
445 1, // S8_UINT_D24_UNORM
446 1, // D32_FLOAT_S8_UINT
447 }};
448
GetDefaultBlockHeight(PixelFormat format)449 static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
450 if (format == PixelFormat::Invalid)
451 return 0;
452
453 ASSERT(static_cast<std::size_t>(format) < block_height_table.size());
454 return block_height_table[static_cast<std::size_t>(format)];
455 }
456
457 constexpr std::array<u32, MaxPixelFormat> bpp_table = {{
458 32, // A8B8G8R8_UNORM
459 32, // A8B8G8R8_SNORM
460 32, // A8B8G8R8_SINT
461 32, // A8B8G8R8_UINT
462 16, // R5G6B5_UNORM
463 16, // B5G6R5_UNORM
464 16, // A1R5G5B5_UNORM
465 32, // A2B10G10R10_UNORM
466 32, // A2B10G10R10_UINT
467 16, // A1B5G5R5_UNORM
468 8, // R8_UNORM
469 8, // R8_SNORM
470 8, // R8_SINT
471 8, // R8_UINT
472 64, // R16G16B16A16_FLOAT
473 64, // R16G16B16A16_UNORM
474 64, // R16G16B16A16_SNORM
475 64, // R16G16B16A16_SINT
476 64, // R16G16B16A16_UINT
477 32, // B10G11R11_FLOAT
478 128, // R32G32B32A32_UINT
479 64, // BC1_RGBA_UNORM
480 128, // BC2_UNORM
481 128, // BC3_UNORM
482 64, // BC4_UNORM
483 64, // BC4_SNORM
484 128, // BC5_UNORM
485 128, // BC5_SNORM
486 128, // BC7_UNORM
487 128, // BC6H_UFLOAT
488 128, // BC6H_SFLOAT
489 128, // ASTC_2D_4X4_UNORM
490 32, // B8G8R8A8_UNORM
491 128, // R32G32B32A32_FLOAT
492 128, // R32G32B32A32_SINT
493 64, // R32G32_FLOAT
494 64, // R32G32_SINT
495 32, // R32_FLOAT
496 16, // R16_FLOAT
497 16, // R16_UNORM
498 16, // R16_SNORM
499 16, // R16_UINT
500 16, // R16_SINT
501 32, // R16G16_UNORM
502 32, // R16G16_FLOAT
503 32, // R16G16_UINT
504 32, // R16G16_SINT
505 32, // R16G16_SNORM
506 96, // R32G32B32_FLOAT
507 32, // A8B8G8R8_SRGB
508 16, // R8G8_UNORM
509 16, // R8G8_SNORM
510 16, // R8G8_SINT
511 16, // R8G8_UINT
512 64, // R32G32_UINT
513 64, // R16G16B16X16_FLOAT
514 32, // R32_UINT
515 32, // R32_SINT
516 128, // ASTC_2D_8X8_UNORM
517 128, // ASTC_2D_8X5_UNORM
518 128, // ASTC_2D_5X4_UNORM
519 32, // B8G8R8A8_SRGB
520 64, // BC1_RGBA_SRGB
521 128, // BC2_SRGB
522 128, // BC3_SRGB
523 128, // BC7_UNORM
524 16, // A4B4G4R4_UNORM
525 128, // ASTC_2D_4X4_SRGB
526 128, // ASTC_2D_8X8_SRGB
527 128, // ASTC_2D_8X5_SRGB
528 128, // ASTC_2D_5X4_SRGB
529 128, // ASTC_2D_5X5_UNORM
530 128, // ASTC_2D_5X5_SRGB
531 128, // ASTC_2D_10X8_UNORM
532 128, // ASTC_2D_10X8_SRGB
533 128, // ASTC_2D_6X6_UNORM
534 128, // ASTC_2D_6X6_SRGB
535 128, // ASTC_2D_10X10_UNORM
536 128, // ASTC_2D_10X10_SRGB
537 128, // ASTC_2D_12X12_UNORM
538 128, // ASTC_2D_12X12_SRGB
539 128, // ASTC_2D_8X6_UNORM
540 128, // ASTC_2D_8X6_SRGB
541 128, // ASTC_2D_6X5_UNORM
542 128, // ASTC_2D_6X5_SRGB
543 32, // E5B9G9R9_FLOAT
544 32, // D32_FLOAT
545 16, // D16_UNORM
546 32, // D24_UNORM_S8_UINT
547 32, // S8_UINT_D24_UNORM
548 64, // D32_FLOAT_S8_UINT
549 }};
550
GetFormatBpp(PixelFormat format)551 static constexpr u32 GetFormatBpp(PixelFormat format) {
552 if (format == PixelFormat::Invalid)
553 return 0;
554
555 ASSERT(static_cast<std::size_t>(format) < bpp_table.size());
556 return bpp_table[static_cast<std::size_t>(format)];
557 }
558
559 /// Returns the sizer in bytes of the specified pixel format
GetBytesPerPixel(PixelFormat pixel_format)560 static constexpr u32 GetBytesPerPixel(PixelFormat pixel_format) {
561 if (pixel_format == PixelFormat::Invalid) {
562 return 0;
563 }
564 return GetFormatBpp(pixel_format) / CHAR_BIT;
565 }
566
567 SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type);
568
569 bool SurfaceTargetIsLayered(SurfaceTarget target);
570
571 bool SurfaceTargetIsArray(SurfaceTarget target);
572
573 PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format);
574
575 PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format);
576
577 PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format);
578
579 SurfaceType GetFormatType(PixelFormat pixel_format);
580
581 bool IsPixelFormatASTC(PixelFormat format);
582
583 bool IsPixelFormatSRGB(PixelFormat format);
584
585 std::pair<u32, u32> GetASTCBlockSize(PixelFormat format);
586
587 } // namespace VideoCore::Surface
588