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