1 #include "GLESTextureUtils.h"
2
3 #include <algorithm>
4
5 #include "glUtils.h"
6 #include "etc.h"
7 #include "astc-codec.h"
8
9 #if PLATFORM_SDK_VERSION < 26
10 #include <cutils/log.h>
11 #else
12 #include <log/log.h>
13 #endif
14
15 #define ASTC_FORMATS_LIST(EXPAND_MACRO) \
16 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_4x4_KHR, astc_codec::FootprintType::k4x4, false) \
17 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_5x4_KHR, astc_codec::FootprintType::k5x4, false) \
18 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_5x5_KHR, astc_codec::FootprintType::k5x5, false) \
19 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_6x5_KHR, astc_codec::FootprintType::k6x5, false) \
20 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_6x6_KHR, astc_codec::FootprintType::k6x6, false) \
21 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_8x5_KHR, astc_codec::FootprintType::k8x5, false) \
22 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_8x6_KHR, astc_codec::FootprintType::k8x6, false) \
23 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_8x8_KHR, astc_codec::FootprintType::k8x8, false) \
24 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_10x5_KHR, astc_codec::FootprintType::k10x5, false) \
25 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_10x6_KHR, astc_codec::FootprintType::k10x6, false) \
26 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_10x8_KHR, astc_codec::FootprintType::k10x8, false) \
27 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_10x10_KHR, astc_codec::FootprintType::k10x10, false) \
28 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_12x10_KHR, astc_codec::FootprintType::k12x10, false) \
29 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_12x12_KHR, astc_codec::FootprintType::k12x12, false) \
30 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, astc_codec::FootprintType::k4x4, true) \
31 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, astc_codec::FootprintType::k5x4, true) \
32 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, astc_codec::FootprintType::k5x5, true) \
33 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, astc_codec::FootprintType::k6x5, true) \
34 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, astc_codec::FootprintType::k6x6, true) \
35 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, astc_codec::FootprintType::k8x5, true) \
36 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, astc_codec::FootprintType::k8x6, true) \
37 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, astc_codec::FootprintType::k8x8, true) \
38 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, astc_codec::FootprintType::k10x5, true) \
39 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, astc_codec::FootprintType::k10x6, true) \
40 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, astc_codec::FootprintType::k10x8, true) \
41 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, astc_codec::FootprintType::k10x10, true) \
42 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, astc_codec::FootprintType::k12x10, true) \
43 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, astc_codec::FootprintType::k12x12, true) \
44
45 namespace GLESTextureUtils {
46
47 // Based on computations in
48 // https://swiftshader.googlesource.com/SwiftShader/+/master/src/OpenGL/common/Image.cpp
49 // such as Image::loadImageData,
50 // ComputePitch/ComputePackingOffset
51
52 #define HIGHEST_MULTIPLE_OF(align, x) \
53 (( ( x ) + ( align ) - 1) & ~( ( align ) - 1)) \
54
computePixelSize(GLenum format,GLenum type)55 static int computePixelSize(GLenum format, GLenum type) {
56
57 #define FORMAT_ERROR(format, type) \
58 ALOGE("%s:%d unknown format/type 0x%x 0x%x", __FUNCTION__, __LINE__, format, type) \
59
60 switch(type) {
61 case GL_BYTE:
62 switch(format) {
63 case GL_R8:
64 case GL_R8I:
65 case GL_R8_SNORM:
66 case GL_RED: return sizeof(char);
67 case GL_RED_INTEGER: return sizeof(char);
68 case GL_RG8:
69 case GL_RG8I:
70 case GL_RG8_SNORM:
71 case GL_RG: return sizeof(char) * 2;
72 case GL_RG_INTEGER: return sizeof(char) * 2;
73 case GL_RGB8:
74 case GL_RGB8I:
75 case GL_RGB8_SNORM:
76 case GL_RGB: return sizeof(char) * 3;
77 case GL_RGB_INTEGER: return sizeof(char) * 3;
78 case GL_RGBA8:
79 case GL_RGBA8I:
80 case GL_RGBA8_SNORM:
81 case GL_RGBA: return sizeof(char) * 4;
82 case GL_RGBA_INTEGER: return sizeof(char) * 4;
83 default: FORMAT_ERROR(format, type);
84 }
85 break;
86 case GL_UNSIGNED_BYTE:
87 switch(format) {
88 case GL_R8:
89 case GL_R8UI:
90 case GL_RED: return sizeof(unsigned char);
91 case GL_RED_INTEGER: return sizeof(unsigned char);
92 case GL_ALPHA8_EXT:
93 case GL_ALPHA: return sizeof(unsigned char);
94 case GL_LUMINANCE8_EXT:
95 case GL_LUMINANCE: return sizeof(unsigned char);
96 case GL_LUMINANCE8_ALPHA8_EXT:
97 case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2;
98 case GL_RG8:
99 case GL_RG8UI:
100 case GL_RG: return sizeof(unsigned char) * 2;
101 case GL_RG_INTEGER: return sizeof(unsigned char) * 2;
102 case GL_RGB8:
103 case GL_RGB8UI:
104 case GL_SRGB8:
105 case GL_RGB: return sizeof(unsigned char) * 3;
106 case GL_RGB_INTEGER: return sizeof(unsigned char) * 3;
107 case GL_RGBA8:
108 case GL_RGBA8UI:
109 case GL_SRGB8_ALPHA8:
110 case GL_RGBA: return sizeof(unsigned char) * 4;
111 case GL_RGBA_INTEGER: return sizeof(unsigned char) * 4;
112 case GL_BGRA_EXT:
113 case GL_BGRA8_EXT: return sizeof(unsigned char)* 4;
114 default: FORMAT_ERROR(format, type);
115 }
116 break;
117 case GL_SHORT:
118 switch(format) {
119 case GL_R16I:
120 case GL_RED_INTEGER: return sizeof(short);
121 case GL_RG16I:
122 case GL_RG_INTEGER: return sizeof(short) * 2;
123 case GL_RGB16I:
124 case GL_RGB_INTEGER: return sizeof(short) * 3;
125 case GL_RGBA16I:
126 case GL_RGBA_INTEGER: return sizeof(short) * 4;
127 default: FORMAT_ERROR(format, type);
128 }
129 break;
130 case GL_UNSIGNED_SHORT:
131 switch(format) {
132 case GL_DEPTH_COMPONENT16:
133 case GL_DEPTH_COMPONENT: return sizeof(unsigned short);
134 case GL_R16UI:
135 case GL_RED_INTEGER: return sizeof(unsigned short);
136 case GL_RG16UI:
137 case GL_RG_INTEGER: return sizeof(unsigned short) * 2;
138 case GL_RGB16UI:
139 case GL_RGB_INTEGER: return sizeof(unsigned short) * 3;
140 case GL_RGBA16UI:
141 case GL_RGBA_INTEGER: return sizeof(unsigned short) * 4;
142 default: FORMAT_ERROR(format, type);
143 }
144 break;
145 case GL_INT:
146 switch(format) {
147 case GL_R32I:
148 case GL_RED_INTEGER: return sizeof(int);
149 case GL_RG32I:
150 case GL_RG_INTEGER: return sizeof(int) * 2;
151 case GL_RGB32I:
152 case GL_RGB_INTEGER: return sizeof(int) * 3;
153 case GL_RGBA32I:
154 case GL_RGBA_INTEGER: return sizeof(int) * 4;
155 default: FORMAT_ERROR(format, type);
156 }
157 break;
158 case GL_UNSIGNED_INT:
159 switch(format) {
160 case GL_DEPTH_COMPONENT16:
161 case GL_DEPTH_COMPONENT24:
162 case GL_DEPTH_COMPONENT32_OES:
163 case GL_DEPTH_COMPONENT: return sizeof(unsigned int);
164 case GL_R32UI:
165 case GL_RED_INTEGER: return sizeof(unsigned int);
166 case GL_RG32UI:
167 case GL_RG_INTEGER: return sizeof(unsigned int) * 2;
168 case GL_RGB32UI:
169 case GL_RGB_INTEGER: return sizeof(unsigned int) * 3;
170 case GL_RGBA32UI:
171 case GL_RGBA_INTEGER: return sizeof(unsigned int) * 4;
172 default: FORMAT_ERROR(format, type);
173 }
174 break;
175 case GL_UNSIGNED_SHORT_4_4_4_4:
176 case GL_UNSIGNED_SHORT_5_5_5_1:
177 case GL_UNSIGNED_SHORT_5_6_5:
178 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
179 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
180 return sizeof(unsigned short);
181 case GL_UNSIGNED_INT_10F_11F_11F_REV:
182 case GL_UNSIGNED_INT_5_9_9_9_REV:
183 case GL_UNSIGNED_INT_2_10_10_10_REV:
184 case GL_UNSIGNED_INT_24_8_OES:
185 return sizeof(unsigned int);
186 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
187 return sizeof(float) + sizeof(unsigned int);
188 case GL_FLOAT:
189 switch(format) {
190 case GL_DEPTH_COMPONENT32F:
191 case GL_DEPTH_COMPONENT: return sizeof(float);
192 case GL_ALPHA32F_EXT:
193 case GL_ALPHA: return sizeof(float);
194 case GL_LUMINANCE32F_EXT:
195 case GL_LUMINANCE: return sizeof(float);
196 case GL_LUMINANCE_ALPHA32F_EXT:
197 case GL_LUMINANCE_ALPHA: return sizeof(float) * 2;
198 case GL_RED: return sizeof(float);
199 case GL_R32F: return sizeof(float);
200 case GL_RG: return sizeof(float) * 2;
201 case GL_RG32F: return sizeof(float) * 2;
202 case GL_RGB: return sizeof(float) * 3;
203 case GL_RGB32F: return sizeof(float) * 3;
204 case GL_RGBA: return sizeof(float) * 4;
205 case GL_RGBA32F: return sizeof(float) * 4;
206 default: FORMAT_ERROR(format, type);
207 }
208 break;
209 case GL_HALF_FLOAT:
210 case GL_HALF_FLOAT_OES:
211 switch(format) {
212 case GL_ALPHA16F_EXT:
213 case GL_ALPHA: return sizeof(unsigned short);
214 case GL_LUMINANCE16F_EXT:
215 case GL_LUMINANCE: return sizeof(unsigned short);
216 case GL_LUMINANCE_ALPHA16F_EXT:
217 case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2;
218 case GL_RED: return sizeof(unsigned short);
219 case GL_R16F: return sizeof(unsigned short);
220 case GL_RG: return sizeof(unsigned short) * 2;
221 case GL_RG16F: return sizeof(unsigned short) * 2;
222 case GL_RGB: return sizeof(unsigned short) * 3;
223 case GL_RGB16F: return sizeof(unsigned short) * 3;
224 case GL_RGBA: return sizeof(unsigned short) * 4;
225 case GL_RGBA16F: return sizeof(unsigned short) * 4;
226 default: FORMAT_ERROR(format, type);
227 }
228 break;
229 default: FORMAT_ERROR(format, type);
230 }
231
232 return 0;
233 }
234
computePitch(GLsizei inputWidth,GLenum format,GLenum type,int align)235 static int computePitch(GLsizei inputWidth, GLenum format, GLenum type, int align) {
236 GLsizei unaligned_width = computePixelSize(format, type) * inputWidth;
237 return HIGHEST_MULTIPLE_OF(align, unaligned_width);
238 }
239
computePackingOffset(GLenum format,GLenum type,GLsizei width,GLsizei height,int align,int skipPixels,int skipRows,int skipImages)240 static int computePackingOffset(GLenum format, GLenum type, GLsizei width, GLsizei height, int align, int skipPixels, int skipRows, int skipImages) {
241 GLsizei alignedPitch = computePitch(width, format, type, align);
242 int packingOffsetRows =
243 (skipImages * height + skipRows);
244 int res = packingOffsetRows * alignedPitch + skipPixels * computePixelSize(format, type);
245
246 return res;
247 }
248
computeTextureStartEnd(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int unpackAlignment,int unpackRowLength,int unpackImageHeight,int unpackSkipPixels,int unpackSkipRows,int unpackSkipImages,int * start,int * end,int ignoreTrailing)249 void computeTextureStartEnd(
250 GLsizei width, GLsizei height, GLsizei depth,
251 GLenum format, GLenum type,
252 int unpackAlignment,
253 int unpackRowLength,
254 int unpackImageHeight,
255 int unpackSkipPixels,
256 int unpackSkipRows,
257 int unpackSkipImages,
258 int* start,
259 int* end,
260 int ignoreTrailing) {
261
262 GLsizei inputWidth = (unpackRowLength == 0) ? width : unpackRowLength;
263 GLsizei inputPitch = computePitch(inputWidth, format, type, unpackAlignment);
264 GLsizei inputHeight = (unpackImageHeight == 0) ? height : unpackImageHeight;
265
266 ALOGV("%s: input idim %d %d %d w p h %d %d %d:", __FUNCTION__, width, height, depth, inputWidth, inputPitch, inputHeight);
267
268 int startVal = computePackingOffset(format, type, inputWidth, inputHeight, unpackAlignment, unpackSkipPixels, unpackSkipRows, unpackSkipImages);
269 int endVal;
270 if (ignoreTrailing) {
271 // The last row needs to have just enough data per spec, and could
272 // ignore alignment.
273 // b/223402256
274 endVal = startVal + inputPitch * inputHeight * (depth - 1);
275 endVal += inputPitch * (std::min(height, inputHeight) - 1);
276 endVal += computePitch(std::min(width, inputWidth), format, type, 1);
277 } else {
278 endVal = startVal + inputPitch * inputHeight * depth;
279 }
280
281 if (start) *start = startVal;
282 if (end) *end = endVal;
283
284 ALOGV("%s: start/end: %d %d", __FUNCTION__, *start, *end);
285
286 }
287
computeTotalImageSize(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int unpackAlignment,int unpackRowLength,int unpackImageHeight,int unpackSkipPixels,int unpackSkipRows,int unpackSkipImages)288 int computeTotalImageSize(
289 GLsizei width, GLsizei height, GLsizei depth,
290 GLenum format, GLenum type,
291 int unpackAlignment,
292 int unpackRowLength,
293 int unpackImageHeight,
294 int unpackSkipPixels,
295 int unpackSkipRows,
296 int unpackSkipImages) {
297
298 int start, end;
299 computeTextureStartEnd(
300 width, height, depth,
301 format, type,
302 unpackAlignment,
303 unpackRowLength,
304 unpackImageHeight,
305 unpackSkipPixels,
306 unpackSkipRows,
307 unpackSkipImages,
308 &start,
309 &end,
310 0);
311 return end;
312 }
313
computeNeededBufferSize(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int unpackAlignment,int unpackRowLength,int unpackImageHeight,int unpackSkipPixels,int unpackSkipRows,int unpackSkipImages,int ignoreTrailing)314 int computeNeededBufferSize(
315 GLsizei width, GLsizei height, GLsizei depth,
316 GLenum format, GLenum type,
317 int unpackAlignment,
318 int unpackRowLength,
319 int unpackImageHeight,
320 int unpackSkipPixels,
321 int unpackSkipRows,
322 int unpackSkipImages,
323 int ignoreTrailing) {
324
325 int start, end;
326 computeTextureStartEnd(
327 width, height, depth,
328 format, type,
329 unpackAlignment,
330 unpackRowLength,
331 unpackImageHeight,
332 unpackSkipPixels,
333 unpackSkipRows,
334 unpackSkipImages,
335 &start,
336 &end,
337 ignoreTrailing);
338 return end - start;
339 }
340
computePackingOffsets2D(GLsizei width,GLsizei height,GLenum format,GLenum type,int packAlignment,int packRowLength,int packSkipPixels,int packSkipRows,int * bpp,int * startOffset,int * packingPixelRowSize,int * packingTotalRowSize)341 void computePackingOffsets2D(
342 GLsizei width, GLsizei height,
343 GLenum format, GLenum type,
344 int packAlignment,
345 int packRowLength,
346 int packSkipPixels,
347 int packSkipRows,
348 int* bpp,
349 int* startOffset,
350 int* packingPixelRowSize,
351 int* packingTotalRowSize) {
352
353 int widthTotal = (packRowLength == 0) ? width : packRowLength;
354 int totalRowSize = computePitch(widthTotal, format, type, packAlignment);
355 int pixelsOnlyRowSize = computePitch(width, format, type, packAlignment);
356
357 int packingOffsetStart =
358 computePackingOffset(
359 format, type, widthTotal, height, packAlignment, packSkipPixels, packSkipRows, 0 /* skip images = 0 */);
360
361 if (bpp) *bpp = computePixelSize(format, type);
362 if (startOffset) *startOffset = packingOffsetStart;
363 if (packingPixelRowSize) *packingPixelRowSize = pixelsOnlyRowSize;
364 if (packingTotalRowSize) *packingTotalRowSize = totalRowSize;
365 }
366
computePackingOffsets3D(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int packAlignment,int packRowLength,int packImageHeight,int packSkipPixels,int packSkipRows,int packSkipImages,int * bpp,int * startOffset,int * packingPixelRowSize,int * packingTotalRowSize,int * packingPixelImageSize,int * packingTotalImageSize)367 void computePackingOffsets3D(
368 GLsizei width, GLsizei height, GLsizei depth,
369 GLenum format, GLenum type,
370 int packAlignment,
371 int packRowLength,
372 int packImageHeight,
373 int packSkipPixels,
374 int packSkipRows,
375 int packSkipImages,
376 int* bpp,
377 int* startOffset,
378 int* packingPixelRowSize,
379 int* packingTotalRowSize,
380 int* packingPixelImageSize,
381 int* packingTotalImageSize) {
382
383 (void)depth;
384
385 int widthTotal = (packRowLength == 0) ? width : packRowLength;
386 int totalRowSize = computePitch(widthTotal, format, type, packAlignment);
387 int pixelsOnlyRowSize = computePitch(width, format, type, packAlignment);
388
389 int heightTotal = packImageHeight == 0 ? height : packImageHeight;
390 int totalImageSize = totalRowSize * heightTotal;
391 int pixelsOnlyImageSize = totalRowSize * height;
392
393 int packingOffsetStart =
394 computePackingOffset(
395 format, type, widthTotal, heightTotal, packAlignment, packSkipPixels, packSkipRows, packSkipImages);
396
397 if (bpp) *bpp = computePixelSize(format, type);
398 if (startOffset) *startOffset = packingOffsetStart;
399 if (packingPixelRowSize) *packingPixelRowSize = pixelsOnlyRowSize;
400 if (packingTotalRowSize) *packingTotalRowSize = totalRowSize;
401 if (packingPixelImageSize) *packingPixelImageSize = pixelsOnlyImageSize;
402 if (packingTotalImageSize) *packingTotalImageSize = totalImageSize;
403 }
404
isEtcFormat(GLenum internalformat)405 bool isEtcFormat(GLenum internalformat) {
406 switch (internalformat) {
407 case GL_ETC1_RGB8_OES:
408 case GL_COMPRESSED_RGB8_ETC2:
409 case GL_COMPRESSED_SRGB8_ETC2:
410 case GL_COMPRESSED_RGBA8_ETC2_EAC:
411 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
412 case GL_COMPRESSED_R11_EAC:
413 case GL_COMPRESSED_SIGNED_R11_EAC:
414 case GL_COMPRESSED_RG11_EAC:
415 case GL_COMPRESSED_SIGNED_RG11_EAC:
416 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
417 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
418 return true;
419 }
420 return false;
421 }
422
isEtc2Format(GLenum internalformat)423 bool isEtc2Format(GLenum internalformat) {
424 return internalformat != GL_ETC1_RGB8_OES &&
425 isEtcFormat(internalformat);
426 }
427
getEtcFormat(GLenum internalformat)428 ETC2ImageFormat getEtcFormat(GLenum internalformat) {
429 ETC2ImageFormat etcFormat = EtcRGB8;
430 switch (internalformat) {
431 case GL_COMPRESSED_RGB8_ETC2:
432 case GL_ETC1_RGB8_OES:
433 break;
434 case GL_COMPRESSED_RGBA8_ETC2_EAC:
435 etcFormat = EtcRGBA8;
436 break;
437 case GL_COMPRESSED_SRGB8_ETC2:
438 break;
439 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
440 etcFormat = EtcRGBA8;
441 break;
442 case GL_COMPRESSED_R11_EAC:
443 etcFormat = EtcR11;
444 break;
445 case GL_COMPRESSED_SIGNED_R11_EAC:
446 etcFormat = EtcSignedR11;
447 break;
448 case GL_COMPRESSED_RG11_EAC:
449 etcFormat = EtcRG11;
450 break;
451 case GL_COMPRESSED_SIGNED_RG11_EAC:
452 etcFormat = EtcSignedRG11;
453 break;
454 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
455 etcFormat = EtcRGB8A1;
456 break;
457 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
458 etcFormat = EtcRGB8A1;
459 break;
460 }
461 return etcFormat;
462 }
463
isAstcFormat(GLenum internalformat)464 bool isAstcFormat(GLenum internalformat) {
465 switch (internalformat) {
466 #define ASTC_FORMAT(typeName, footprintType, srgbValue) \
467 case typeName:
468
469 ASTC_FORMATS_LIST(ASTC_FORMAT)
470 #undef ASTC_FORMAT
471 return true;
472 default:
473 return false;
474 }
475 }
476
isBptcFormat(GLenum internalformat)477 bool isBptcFormat(GLenum internalformat) {
478 switch (internalformat) {
479 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
480 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
481 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
482 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
483 return true;
484 default:
485 return false;
486 }
487 }
488
isRgtcFormat(GLenum internalformat)489 bool isRgtcFormat(GLenum internalformat) {
490 switch(internalformat)
491 {
492 case GL_COMPRESSED_RED_RGTC1_EXT:
493 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
494 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
495 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
496 return true;
497 }
498 return false;
499 }
500
isS3tcFormat(GLenum internalformat)501 bool isS3tcFormat(GLenum internalformat) {
502 switch (internalformat) {
503 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
504 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
505 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
506 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
507 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
508 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
509 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
510 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
511 return true;
512 }
513
514 return false;
515 }
516
getAstcFormatInfo(GLenum internalformat,astc_codec::FootprintType * footprint,bool * srgb)517 void getAstcFormatInfo(GLenum internalformat,
518 astc_codec::FootprintType* footprint,
519 bool* srgb) {
520 switch (internalformat) {
521 #define ASTC_FORMAT(typeName, footprintType, srgbValue) \
522 case typeName: \
523 *footprint = footprintType; *srgb = srgbValue; break; \
524
525 ASTC_FORMATS_LIST(ASTC_FORMAT)
526 #undef ASTC_FORMAT
527 default:
528 ALOGE("%s: invalid astc format: 0x%x\n", __func__, internalformat);
529 abort();
530 }
531 }
532
getAstcFootprintWidth(astc_codec::FootprintType footprint)533 int getAstcFootprintWidth(astc_codec::FootprintType footprint) {
534 switch (footprint) {
535 case astc_codec::FootprintType::k4x4: return 4;
536 case astc_codec::FootprintType::k5x4: return 5;
537 case astc_codec::FootprintType::k5x5: return 5;
538 case astc_codec::FootprintType::k6x5: return 6;
539 case astc_codec::FootprintType::k6x6: return 6;
540 case astc_codec::FootprintType::k8x5: return 8;
541 case astc_codec::FootprintType::k8x6: return 8;
542 case astc_codec::FootprintType::k10x5: return 10;
543 case astc_codec::FootprintType::k10x6: return 10;
544 case astc_codec::FootprintType::k8x8: return 8;
545 case astc_codec::FootprintType::k10x8: return 10;
546 case astc_codec::FootprintType::k10x10: return 10;
547 case astc_codec::FootprintType::k12x10: return 12;
548 case astc_codec::FootprintType::k12x12: return 12;
549 default:
550 ALOGE("%s: invalid astc footprint: 0x%x\n", __func__, footprint);
551 abort();
552 }
553 }
554
getAstcFootprintHeight(astc_codec::FootprintType footprint)555 int getAstcFootprintHeight(astc_codec::FootprintType footprint) {
556 switch (footprint) {
557 case astc_codec::FootprintType::k4x4: return 4;
558 case astc_codec::FootprintType::k5x4: return 4;
559 case astc_codec::FootprintType::k5x5: return 5;
560 case astc_codec::FootprintType::k6x5: return 5;
561 case astc_codec::FootprintType::k6x6: return 6;
562 case astc_codec::FootprintType::k8x5: return 5;
563 case astc_codec::FootprintType::k8x6: return 6;
564 case astc_codec::FootprintType::k10x5: return 5;
565 case astc_codec::FootprintType::k10x6: return 6;
566 case astc_codec::FootprintType::k8x8: return 8;
567 case astc_codec::FootprintType::k10x8: return 8;
568 case astc_codec::FootprintType::k10x10: return 10;
569 case astc_codec::FootprintType::k12x10: return 10;
570 case astc_codec::FootprintType::k12x12: return 12;
571 default:
572 ALOGE("%s: invalid astc footprint: 0x%x\n", __func__, footprint);
573 abort();
574 }
575 }
576
getAstcCompressedSize(GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,bool * error)577 GLsizei getAstcCompressedSize(GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool* error) {
578 bool srgb;
579 astc_codec::FootprintType footprintType;
580 getAstcFormatInfo(internalformat, &footprintType, &srgb);
581
582 int fpWidth = getAstcFootprintWidth(footprintType);
583 int fpHeight = getAstcFootprintHeight(footprintType);
584
585 if (width == 0 || height == 0 || depth == 0) {
586 *error = true;
587 return 0;
588 }
589
590 const size_t blocks_wide = (width + fpWidth - 1) / fpWidth;
591 if (blocks_wide == 0) {
592 *error = true;
593 return 0;
594 }
595
596 const size_t expected_block_count =
597 ((width + fpWidth - 1) / fpWidth) *
598 ((height + fpHeight - 1) / fpHeight);
599
600 const size_t kPhysBlockSizeBytes = 16;
601
602 GLsizei res = kPhysBlockSizeBytes * expected_block_count * depth;
603
604 return res;
605 }
606
getCompressedImageBlocksize(GLenum internalformat)607 GLsizei getCompressedImageBlocksize(GLenum internalformat) {
608 if (isBptcFormat(internalformat)) {
609 return 16;
610 }
611
612 switch (internalformat) {
613 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
614 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
615 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
616 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
617 case GL_COMPRESSED_RED_RGTC1_EXT:
618 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
619 return 8;
620 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
621 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
622 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
623 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
624 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
625 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
626 return 16;
627 }
628
629 ALOGE("%s: Unknown blocksize for internal format: 0x%x\n", __func__, internalformat);
630 abort();
631 }
632
get4x4CompressedSize(GLsizei width,GLsizei height,GLsizei depth,GLsizei blocksize,bool * error)633 GLsizei get4x4CompressedSize(GLsizei width, GLsizei height, GLsizei depth, GLsizei blocksize, bool* error) {
634 *error = false;
635 return blocksize * ((width + 3) / 4) * ((height + 3) / 4) * depth;
636 }
637
getCompressedImageSize(GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,bool * error)638 GLsizei getCompressedImageSize(GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool* error) {
639 if (isEtcFormat(internalformat)) {
640 GLsizei total = 0;
641 GLsizei one = etc_get_encoded_data_size(getEtcFormat(internalformat), width, height);
642 for (GLsizei i = 0; i < depth; ++i) {
643 total += one;
644 }
645 return total;
646 }
647
648 if (isAstcFormat(internalformat)) {
649 return getAstcCompressedSize(internalformat, width, height, depth, error);
650 }
651
652 if (isBptcFormat(internalformat) || isS3tcFormat(internalformat) || isRgtcFormat(internalformat)) {
653 GLsizei blocksize = getCompressedImageBlocksize(internalformat);
654 return get4x4CompressedSize(width, height, depth, blocksize, error);
655 }
656
657 ALOGE("%s: Unknown compressed internal format: 0x%x\n", __func__, internalformat);
658 abort();
659 }
660
661 } // namespace GLESTextureUtils
662