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