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