• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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