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