1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <GLcommon/TextureUtils.h>
17 #include <GLcommon/GLESmacros.h>
18 #include <GLcommon/GLDispatch.h>
19 #include <GLcommon/GLESvalidate.h>
20 #include <stdio.h>
21 #include <cmath>
22 #include <memory>
23
24 #include "aemu/base/AlignedBuf.h"
25 #include "compressedTextureFormats/AstcCpuDecompressor.h"
26
27 using android::AlignedBuf;
28 using gfxstream::vk::AstcCpuDecompressor;
29
30 #define GL_R16 0x822A
31 #define GL_RG16 0x822C
32 #define GL_R16_SNORM 0x8F98
33 #define GL_RG16_SNORM 0x8F99
34
35 static constexpr size_t kASTCFormatsCount = 28;
36
37 #define ASTC_FORMATS_LIST(EXPAND_MACRO) \
38 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_4x4_KHR, 4, 4, false) \
39 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_5x4_KHR, 5, 4, false) \
40 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_5x5_KHR, 5, 5, false) \
41 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_6x5_KHR, 6, 5, false) \
42 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_6x6_KHR, 6, 6, false) \
43 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_8x5_KHR, 8, 5, false) \
44 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_8x6_KHR, 8, 6, false) \
45 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_8x8_KHR, 8, 8, false) \
46 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_10x5_KHR, 10, 5, false) \
47 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_10x6_KHR, 10, 6, false) \
48 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_10x8_KHR, 10, 8, false) \
49 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_10x10_KHR, 10, 10, false) \
50 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_12x10_KHR, 12, 10, false) \
51 EXPAND_MACRO(GL_COMPRESSED_RGBA_ASTC_12x12_KHR, 12, 12, false) \
52 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, 4, 4, true) \
53 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, 5, 4, true) \
54 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, 5, 5, true) \
55 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, 6, 5, true) \
56 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, 6, 6, true) \
57 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, 8, 5, true) \
58 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, 8, 6, true) \
59 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, 8, 8, true) \
60 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, 10, 5, true) \
61 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, 10, 6, true) \
62 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, 10, 8, true) \
63 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, 10, 10, true) \
64 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, 12, 10, true) \
65 EXPAND_MACRO(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 12, 12, true) \
66
getCompressedFormats(int majorVersion,int * formats)67 int getCompressedFormats(int majorVersion, int* formats) {
68 static constexpr size_t kCount = MAX_SUPPORTED_PALETTE + MAX_ETC_SUPPORTED + kASTCFormatsCount;
69 int res = kCount;
70
71 if (majorVersion > 1) {
72 res -= MAX_SUPPORTED_PALETTE;
73 }
74
75 if (formats) {
76 size_t i = 0;
77
78 if (1 == majorVersion) {
79 // Palette
80 formats[i++] = GL_PALETTE4_RGBA8_OES;
81 formats[i++] = GL_PALETTE4_RGBA4_OES;
82 formats[i++] = GL_PALETTE8_RGBA8_OES;
83 formats[i++] = GL_PALETTE8_RGBA4_OES;
84 formats[i++] = GL_PALETTE4_RGB8_OES;
85 formats[i++] = GL_PALETTE8_RGB8_OES;
86 formats[i++] = GL_PALETTE4_RGB5_A1_OES;
87 formats[i++] = GL_PALETTE8_RGB5_A1_OES;
88 formats[i++] = GL_PALETTE4_R5_G6_B5_OES;
89 formats[i++] = GL_PALETTE8_R5_G6_B5_OES;
90 }
91
92 // ETC
93 formats[i++] = GL_ETC1_RGB8_OES;
94 formats[i++] = GL_COMPRESSED_RGB8_ETC2;
95 formats[i++] = GL_COMPRESSED_SIGNED_R11_EAC;
96 formats[i++] = GL_COMPRESSED_RG11_EAC;
97 formats[i++] = GL_COMPRESSED_SIGNED_RG11_EAC;
98 formats[i++] = GL_COMPRESSED_RGB8_ETC2;
99 formats[i++] = GL_COMPRESSED_SRGB8_ETC2;
100 formats[i++] = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
101 formats[i++] = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
102 formats[i++] = GL_COMPRESSED_RGBA8_ETC2_EAC;
103 formats[i++] = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
104 formats[i++] = GL_COMPRESSED_R11_EAC;
105
106 // ASTC
107 #define ASTC_FORMAT(typeName, blockWidth, blockHeight, srgbValue) \
108 formats[i++] = typeName;
109
110 ASTC_FORMATS_LIST(ASTC_FORMAT)
111 #undef ASTC_FORMAT
112
113 }
114
115 return res;
116 }
117
getEtcFormat(GLenum internalformat)118 ETC2ImageFormat getEtcFormat(GLenum internalformat) {
119 ETC2ImageFormat etcFormat = EtcRGB8;
120 switch (internalformat) {
121 case GL_COMPRESSED_RGB8_ETC2:
122 case GL_ETC1_RGB8_OES:
123 break;
124 case GL_COMPRESSED_RGBA8_ETC2_EAC:
125 etcFormat = EtcRGBA8;
126 break;
127 case GL_COMPRESSED_SRGB8_ETC2:
128 break;
129 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
130 etcFormat = EtcRGBA8;
131 break;
132 case GL_COMPRESSED_R11_EAC:
133 etcFormat = EtcR11;
134 break;
135 case GL_COMPRESSED_SIGNED_R11_EAC:
136 etcFormat = EtcSignedR11;
137 break;
138 case GL_COMPRESSED_RG11_EAC:
139 etcFormat = EtcRG11;
140 break;
141 case GL_COMPRESSED_SIGNED_RG11_EAC:
142 etcFormat = EtcSignedRG11;
143 break;
144 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
145 etcFormat = EtcRGB8A1;
146 break;
147 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
148 etcFormat = EtcRGB8A1;
149 break;
150 }
151 return etcFormat;
152 }
153
getAstcFormatInfo(GLenum internalformat,uint32_t * width,uint32_t * height,bool * srgb)154 void getAstcFormatInfo(GLenum internalformat, uint32_t* width, uint32_t* height, bool* srgb) {
155 switch (internalformat) {
156 #define ASTC_FORMAT(typeName, blockWidth, blockHeight, srgbValue) \
157 case typeName: \
158 *width = blockWidth; *height = blockHeight; *srgb = srgbValue; break; \
159
160 ASTC_FORMATS_LIST(ASTC_FORMAT)
161 #undef ASTC_FORMAT
162 default:
163 assert(false && "Invalid ASTC format");
164 break;
165 }
166 }
167
168 // Helper function to decompress an ASTC image.
astcDecompress(const uint8_t * astcData,size_t astcDataSize,uint32_t width,uint32_t height,uint32_t blockWidth,uint32_t blockHeight,uint8_t * outBuffer,size_t outBufferSize)169 bool astcDecompress(const uint8_t* astcData, size_t astcDataSize, uint32_t width, uint32_t height,
170 uint32_t blockWidth, uint32_t blockHeight, uint8_t* outBuffer,
171 size_t outBufferSize) {
172 if (outBufferSize < width * height * 4) {
173 WARN("ASTC output buffer too small: %d bytes for %d x %d", outBufferSize, width, height);
174 return false;
175 }
176 int32_t status = AstcCpuDecompressor::get().decompress(width, height, blockWidth, blockHeight,
177 astcData, astcDataSize, outBuffer);
178 if (status != 0) {
179 WARN("astc decompression failed: %s", AstcCpuDecompressor::get().getStatusString(status));
180 return false;
181 }
182 return true;
183 }
184
isAstcFormat(GLenum internalformat)185 bool isAstcFormat(GLenum internalformat) {
186 switch (internalformat) {
187 #define ASTC_FORMAT(typeName, blockWidth, blockHeight, srgbValue) \
188 case typeName:
189
190 ASTC_FORMATS_LIST(ASTC_FORMAT)
191 #undef ASTC_FORMAT
192 return true;
193 default:
194 return false;
195 }
196 }
197
isEtcFormat(GLenum internalformat)198 bool isEtcFormat(GLenum internalformat) {
199 switch (internalformat) {
200 case GL_ETC1_RGB8_OES:
201 case GL_COMPRESSED_RGB8_ETC2:
202 case GL_COMPRESSED_SRGB8_ETC2:
203 case GL_COMPRESSED_RGBA8_ETC2_EAC:
204 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
205 case GL_COMPRESSED_R11_EAC:
206 case GL_COMPRESSED_SIGNED_R11_EAC:
207 case GL_COMPRESSED_RG11_EAC:
208 case GL_COMPRESSED_SIGNED_RG11_EAC:
209 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
210 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
211 return true;
212 }
213 return false;
214 }
215
isEtc2Format(GLenum internalformat)216 bool isEtc2Format(GLenum internalformat) {
217 switch (internalformat) {
218 case GL_COMPRESSED_RGB8_ETC2:
219 case GL_COMPRESSED_SRGB8_ETC2:
220 case GL_COMPRESSED_RGBA8_ETC2_EAC:
221 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
222 case GL_COMPRESSED_R11_EAC:
223 case GL_COMPRESSED_SIGNED_R11_EAC:
224 case GL_COMPRESSED_RG11_EAC:
225 case GL_COMPRESSED_SIGNED_RG11_EAC:
226 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
227 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
228 return true;
229 }
230 return false;
231 }
232
isBptcFormat(GLenum internalformat)233 bool isBptcFormat(GLenum internalformat) {
234 switch (internalformat) {
235 case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
236 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
237 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
238 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
239 return true;
240 }
241 return false;
242 }
243
isS3tcFormat(GLenum internalformat)244 bool isS3tcFormat(GLenum internalformat) {
245 switch (internalformat) {
246 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
247 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
248 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
249 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
250 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
251 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
252 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
253 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
254 return true;
255 }
256 return false;
257 }
258
isPaletteFormat(GLenum internalformat)259 bool isPaletteFormat(GLenum internalformat) {
260 switch (internalformat) {
261 case GL_PALETTE4_RGB8_OES:
262 case GL_PALETTE4_RGBA8_OES:
263 case GL_PALETTE4_R5_G6_B5_OES:
264 case GL_PALETTE4_RGBA4_OES:
265 case GL_PALETTE4_RGB5_A1_OES:
266 case GL_PALETTE8_RGB8_OES:
267 case GL_PALETTE8_RGBA8_OES:
268 case GL_PALETTE8_R5_G6_B5_OES:
269 case GL_PALETTE8_RGBA4_OES:
270 case GL_PALETTE8_RGB5_A1_OES:
271 return true;
272 }
273 return false;
274 }
275
decompressedInternalFormat(GLEScontext * ctx,GLenum compressedFormat)276 GLenum decompressedInternalFormat(GLEScontext* ctx, GLenum compressedFormat) {
277 bool needSizedInternalFormat =
278 isCoreProfile() ||
279 (ctx->getMajorVersion() >= 3);
280
281 GLenum glrgb = needSizedInternalFormat ? GL_RGB8 : GL_RGB;
282 GLenum glrgba = needSizedInternalFormat ? GL_RGBA8 : GL_RGBA;
283
284 switch (compressedFormat) {
285 // ETC2 formats
286 case GL_COMPRESSED_RGB8_ETC2:
287 case GL_ETC1_RGB8_OES:
288 return glrgb;
289 case GL_COMPRESSED_RGBA8_ETC2_EAC:
290 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
291 return glrgba;
292 case GL_COMPRESSED_SRGB8_ETC2:
293 return GL_SRGB8;
294 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
295 return GL_SRGB8_ALPHA8;
296 case GL_COMPRESSED_R11_EAC:
297 case GL_COMPRESSED_SIGNED_R11_EAC:
298 return GL_R32F;
299 case GL_COMPRESSED_RG11_EAC:
300 case GL_COMPRESSED_SIGNED_RG11_EAC:
301 return GL_RG32F;
302 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
303 return GL_SRGB8_ALPHA8;
304 // ASTC formats
305 case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
306 case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
307 case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
308 case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
309 case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
310 case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
311 case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
312 case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
313 case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
314 case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
315 case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
316 case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
317 case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
318 case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
319 return glrgba;
320 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
321 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
322 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
323 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
324 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
325 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
326 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
327 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
328 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
329 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
330 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
331 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
332 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
333 case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
334 return GL_SRGB8_ALPHA8;
335 // palette formats
336 case GL_PALETTE4_RGB8_OES:
337 case GL_PALETTE4_R5_G6_B5_OES:
338 case GL_PALETTE8_RGB8_OES:
339 case GL_PALETTE8_R5_G6_B5_OES:
340 return glrgb;
341 case GL_PALETTE4_RGBA8_OES:
342 case GL_PALETTE4_RGBA4_OES:
343 case GL_PALETTE4_RGB5_A1_OES:
344 case GL_PALETTE8_RGBA8_OES:
345 case GL_PALETTE8_RGBA4_OES:
346 case GL_PALETTE8_RGB5_A1_OES:
347 return glrgba;
348 case GL_COMPRESSED_RED_RGTC1_EXT: // BC4U
349 return GL_R8;
350 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT: // BC4S
351 return GL_R8_SNORM;
352 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: // BC5U
353 return GL_RG8;
354 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: // BC5S
355 return GL_RG8_SNORM;
356 default:
357 return compressedFormat;
358 }
359 }
360
361 class ScopedFetchUnpackData {
362 public:
ScopedFetchUnpackData(GLEScontext * ctx,GLintptr offset,GLsizei dataSize)363 ScopedFetchUnpackData(GLEScontext* ctx, GLintptr offset,
364 GLsizei dataSize) : mCtx(ctx) {
365 mData = ctx->dispatcher().glMapBufferRange(
366 GL_PIXEL_UNPACK_BUFFER,
367 offset, dataSize, GL_MAP_READ_BIT);
368 if (mData) {
369 ctx->dispatcher().glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING,
370 &mUnpackBuffer);
371 ctx->dispatcher().glBindBuffer(GL_PIXEL_UNPACK_BUFFER,
372 0);
373 }
374 }
~ScopedFetchUnpackData()375 ~ScopedFetchUnpackData() {
376 if (mData) {
377 mCtx->dispatcher().glBindBuffer(GL_PIXEL_UNPACK_BUFFER,
378 mUnpackBuffer);
379 mCtx->dispatcher().glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
380 }
381 }
data()382 void* data() {
383 return mData;
384 }
385 private:
386 const GLEScontext* mCtx;
387 void* mData = nullptr;
388 GLint mUnpackBuffer = 0;
389 };
390
doCompressedTexImage2D(GLEScontext * ctx,GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,const GLvoid * data,glTexImage2D_t glTexImage2DPtr)391 void doCompressedTexImage2D(GLEScontext* ctx, GLenum target, GLint level,
392 GLenum internalformat, GLsizei width,
393 GLsizei height, GLint border,
394 GLsizei imageSize, const GLvoid* data,
395 glTexImage2D_t glTexImage2DPtr) {
396 /* XXX: This is just a hack to fix the resolve of glTexImage2D problem
397 It will be removed when we'll no longer link against ligGL */
398 /*typedef void (GLAPIENTRY *glTexImage2DPtr_t ) (
399 GLenum target, GLint level, GLint internalformat,
400 GLsizei width, GLsizei height, GLint border,
401 GLenum format, GLenum type, const GLvoid *pixels);
402
403 glTexImage2DPtr_t glTexImage2DPtr;
404 glTexImage2DPtr = (glTexImage2DPtr_t)funcPtr;*/
405 bool needUnpackBuffer = false;
406 if (ctx->getMajorVersion() >= 3) {
407 GLint unpackBuffer = 0;
408 ctx->dispatcher().glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING,
409 &unpackBuffer);
410 needUnpackBuffer = unpackBuffer;
411 }
412 TextureUnpackReset unpack(ctx);
413 const int32_t unpackAlignment = TextureUnpackReset::kUnpackAlignment;
414 if (isEtcFormat(internalformat)) {
415 GLint format = GL_RGB;
416 GLint type = GL_UNSIGNED_BYTE;
417 GLint convertedInternalFormat = decompressedInternalFormat(ctx, internalformat);
418 ETC2ImageFormat etcFormat = EtcRGB8;
419 switch (internalformat) {
420 case GL_COMPRESSED_RGB8_ETC2:
421 case GL_ETC1_RGB8_OES:
422 break;
423 case GL_COMPRESSED_RGBA8_ETC2_EAC:
424 etcFormat = EtcRGBA8;
425 format = GL_RGBA;
426 break;
427 case GL_COMPRESSED_SRGB8_ETC2:
428 break;
429 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
430 etcFormat = EtcRGBA8;
431 format = GL_RGBA;
432 break;
433 case GL_COMPRESSED_R11_EAC:
434 etcFormat = EtcR11;
435 format = GL_RED;
436 type = GL_FLOAT;
437 break;
438 case GL_COMPRESSED_SIGNED_R11_EAC:
439 etcFormat = EtcSignedR11;
440 format = GL_RED;
441 type = GL_FLOAT;
442 break;
443 case GL_COMPRESSED_RG11_EAC:
444 etcFormat = EtcRG11;
445 format = GL_RG;
446 type = GL_FLOAT;
447 break;
448 case GL_COMPRESSED_SIGNED_RG11_EAC:
449 etcFormat = EtcSignedRG11;
450 format = GL_RG;
451 type = GL_FLOAT;
452 break;
453 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
454 etcFormat = EtcRGB8A1;
455 format = GL_RGBA;
456 break;
457 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
458 etcFormat = EtcRGB8A1;
459 format = GL_RGBA;
460 break;
461 }
462 int pixelSize = etc_get_decoded_pixel_size(etcFormat);
463 GLsizei compressedSize =
464 etc_get_encoded_data_size(etcFormat, width, height);
465 SET_ERROR_IF((compressedSize != imageSize), GL_INVALID_VALUE);
466 std::unique_ptr<ScopedFetchUnpackData> unpackData;
467 std::unique_ptr<char[]> emulatedData;
468 if (needUnpackBuffer) {
469 unpackData.reset(new ScopedFetchUnpackData(ctx,
470 reinterpret_cast<GLintptr>(data), compressedSize));
471 data = unpackData->data();
472 SET_ERROR_IF(!data, GL_INVALID_OPERATION);
473 } else {
474 if (!data) {
475 emulatedData.reset(new char[compressedSize]);
476 data = emulatedData.get();
477 }
478 }
479
480 const int32_t align = unpackAlignment - 1;
481 const int32_t bpr = ((width * pixelSize) + align) & ~align;
482 const size_t size = bpr * height;
483 std::unique_ptr<etc1_byte[]> pOut(new etc1_byte[size]);
484
485 int res =
486 etc2_decode_image(
487 (const etc1_byte*)data, etcFormat, pOut.get(),
488 width, height, bpr);
489 SET_ERROR_IF(res!=0, GL_INVALID_VALUE);
490
491 glTexImage2DPtr(target, level, convertedInternalFormat,
492 width, height, border, format, type, pOut.get());
493 } else if (isAstcFormat(internalformat)) {
494 std::unique_ptr<ScopedFetchUnpackData> unpackData;
495 std::unique_ptr<char[]> emulatedData;
496 if (needUnpackBuffer) {
497 unpackData.reset(
498 new ScopedFetchUnpackData(ctx, reinterpret_cast<GLintptr>(data), imageSize));
499 data = unpackData->data();
500 SET_ERROR_IF(!data, GL_INVALID_OPERATION);
501 } else {
502 if (!data) {
503 emulatedData.reset(new char[imageSize]);
504 data = emulatedData.get();
505 }
506 }
507 uint32_t blockWidth = 0;
508 uint32_t blockHeight = 0;
509 bool srgb;
510 getAstcFormatInfo(internalformat, &blockWidth, &blockHeight, &srgb);
511
512 const int32_t align = unpackAlignment - 1;
513 const int32_t stride = ((width * 4) + align) & ~align;
514 const size_t size = stride * height;
515
516 AlignedBuf<uint8_t, 64> alignedUncompressedData(size);
517
518 const bool result = astcDecompress(
519 reinterpret_cast<const uint8_t*>(data), imageSize, width,
520 height, blockWidth, blockHeight, alignedUncompressedData.data(), size);
521 SET_ERROR_IF(!result, GL_INVALID_VALUE);
522
523 glTexImage2DPtr(target, level, srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8, width,
524 height, border, GL_RGBA, GL_UNSIGNED_BYTE,
525 alignedUncompressedData.data());
526 } else if (isPaletteFormat(internalformat)) {
527 // TODO: fix the case when GL_PIXEL_UNPACK_BUFFER is bound
528 SET_ERROR_IF(
529 level > log2(ctx->getMaxTexSize()) ||
530 border !=0 || level > 0 ||
531 !GLESvalidate::texImgDim(
532 width, height, ctx->getMaxTexSize() + 2),
533 GL_INVALID_VALUE);
534 SET_ERROR_IF(!data,GL_INVALID_OPERATION);
535 //the decoder fully packed the pixels.
536 ctx->dispatcher().glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
537 int nMipmaps = -level + 1;
538 GLsizei tmpWidth = width;
539 GLsizei tmpHeight = height;
540
541 for(int i = 0; i < nMipmaps; i++)
542 {
543 GLenum uncompressedFrmt;
544 unsigned char* uncompressed =
545 uncompressTexture(internalformat, uncompressedFrmt,
546 width, height, imageSize, data, i);
547 glTexImage2DPtr(target, i, uncompressedFrmt,
548 tmpWidth, tmpHeight, border,
549 uncompressedFrmt, GL_UNSIGNED_BYTE, uncompressed);
550 tmpWidth /= 2;
551 tmpHeight /= 2;
552 delete [] uncompressed;
553 }
554 } else if (isRgtcFormat(internalformat)) {
555 GLint format, type;
556 GLint convertedInternalFormat = decompressedInternalFormat(ctx, internalformat);
557 RGTCImageFormat rgtcFormat;
558 switch (internalformat) {
559 case GL_COMPRESSED_RED_RGTC1_EXT: // BC4U
560 format = GL_RED;
561 type = GL_UNSIGNED_BYTE;
562 rgtcFormat = BC4_UNORM;
563 break;
564 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT: // BC4S
565 format = GL_RED;
566 type = GL_BYTE;
567 rgtcFormat = BC4_SNORM;
568 break;
569 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: // BC5U
570 format = GL_RG;
571 type = GL_UNSIGNED_BYTE;
572 rgtcFormat = BC5_UNORM;
573 break;
574 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: // BC5S
575 format = GL_RG;
576 type = GL_BYTE;
577 rgtcFormat = BC5_SNORM;
578 break;
579 }
580 size_t pixelSize = rgtc_get_decoded_pixel_size(rgtcFormat);
581 GLsizei compressedSize = rgtc_get_encoded_image_size(rgtcFormat, width, height);
582 SET_ERROR_IF((compressedSize != imageSize), GL_INVALID_VALUE);
583 std::unique_ptr<ScopedFetchUnpackData> unpackData;
584 std::unique_ptr<char[]> emulatedData;
585 if (needUnpackBuffer) {
586 unpackData.reset(
587 new ScopedFetchUnpackData(ctx, reinterpret_cast<GLintptr>(data), compressedSize));
588 data = unpackData->data();
589 SET_ERROR_IF(!data, GL_INVALID_OPERATION);
590 } else {
591 if (!data) {
592 emulatedData.reset(new char[compressedSize]);
593 data = emulatedData.get();
594 }
595 }
596 const int32_t align = unpackAlignment - 1;
597 const int32_t bpr = ((width * pixelSize) + align) & ~align;
598 const size_t size = bpr * height;
599 std::unique_ptr<uint8_t[]> pOut(new uint8_t[size]);
600
601 int res =
602 rgtc_decode_image((const uint8_t*)data, rgtcFormat, pOut.get(), width, height, bpr);
603 SET_ERROR_IF(res != 0, GL_INVALID_VALUE);
604 glTexImage2DPtr(target, level, convertedInternalFormat, width, height, border, format, type,
605 pOut.get());
606 } else {
607 SET_ERROR_IF(1, GL_INVALID_ENUM);
608 }
609 }
610
deleteRenderbufferGlobal(GLuint rbo)611 void deleteRenderbufferGlobal(GLuint rbo) {
612 if (rbo) {
613 GLEScontext::dispatcher().glDeleteRenderbuffers(1, &rbo);
614 }
615 }
616
isCubeMapFaceTarget(GLenum target)617 bool isCubeMapFaceTarget(GLenum target) {
618 switch (target) {
619 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
620 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
621 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
622 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
623 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
624 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
625 return true;
626 }
627 return false;
628 }
629
isCoreProfileEmulatedFormat(GLenum format)630 bool isCoreProfileEmulatedFormat(GLenum format) {
631 switch (format) {
632 case GL_ALPHA:
633 case GL_LUMINANCE:
634 case GL_LUMINANCE_ALPHA:
635 return true;
636 default:
637 return false;
638 }
639 }
640
getCoreProfileEmulatedFormat(GLenum format)641 GLenum getCoreProfileEmulatedFormat(GLenum format) {
642 switch (format) {
643 case GL_ALPHA:
644 case GL_LUMINANCE:
645 return GL_RED;
646 case GL_LUMINANCE_ALPHA:
647 return GL_RG;
648 }
649 return format;
650 }
651
getCoreProfileEmulatedInternalFormat(GLint internalformat,GLenum type)652 GLint getCoreProfileEmulatedInternalFormat(GLint internalformat, GLenum type) {
653 switch (internalformat) {
654 case GL_ALPHA:
655 case GL_LUMINANCE:
656 switch (type) {
657 case GL_UNSIGNED_BYTE:
658 return GL_R8;
659 case GL_FLOAT:
660 return GL_R32F;
661 case GL_HALF_FLOAT:
662 return GL_R16F;
663 }
664 return GL_R8;
665 case GL_LUMINANCE_ALPHA:
666 switch (type) {
667 case GL_UNSIGNED_BYTE:
668 return GL_RG8;
669 case GL_FLOAT:
670 return GL_RG32F;
671 case GL_HALF_FLOAT:
672 return GL_RG16F;
673 }
674 return GL_RG8;
675 }
676 fprintf(stderr,
677 "%s: warning: unsupported alpha/luminance internal format 0x%x type 0x%x\n",
678 __func__, internalformat, type);
679 return GL_R8;
680 }
681
getSwizzleForEmulatedFormat(GLenum format)682 TextureSwizzle getSwizzleForEmulatedFormat(GLenum format) {
683 TextureSwizzle res;
684 switch (format) {
685 case GL_ALPHA:
686 res.toRed = GL_ZERO;
687 res.toGreen = GL_ZERO;
688 res.toBlue = GL_ZERO;
689 res.toAlpha = GL_RED;
690 break;
691 case GL_LUMINANCE:
692 res.toRed = GL_RED;
693 res.toGreen = GL_RED;
694 res.toBlue = GL_RED;
695 res.toAlpha = GL_ONE;
696 break;
697 case GL_LUMINANCE_ALPHA:
698 res.toRed = GL_RED;
699 res.toGreen = GL_RED;
700 res.toBlue = GL_RED;
701 res.toAlpha = GL_GREEN;
702 break;
703 default:
704 break;
705 }
706 return res;
707 }
708
709 // Inverse swizzle: if we were writing fragments back to this texture,
710 // how should the components be re-arranged?
getInverseSwizzleForEmulatedFormat(GLenum format)711 TextureSwizzle getInverseSwizzleForEmulatedFormat(GLenum format) {
712 TextureSwizzle res;
713 switch (format) {
714 case GL_ALPHA:
715 res.toRed = GL_ALPHA;
716 res.toGreen = GL_ZERO;
717 res.toBlue = GL_ZERO;
718 res.toAlpha = GL_ZERO;
719 break;
720 case GL_LUMINANCE:
721 res.toRed = GL_RED;
722 res.toGreen = GL_ZERO;
723 res.toBlue = GL_ZERO;
724 res.toAlpha = GL_ZERO;
725 break;
726 case GL_LUMINANCE_ALPHA:
727 res.toRed = GL_RED;
728 res.toGreen = GL_ALPHA;
729 res.toBlue = GL_ZERO;
730 res.toAlpha = GL_ZERO;
731 break;
732 default:
733 break;
734 }
735 return res;
736 }
737
swizzleComponentOf(const TextureSwizzle & s,GLenum component)738 GLenum swizzleComponentOf(const TextureSwizzle& s, GLenum component) {
739 switch (component) {
740 case GL_RED: return s.toRed;
741 case GL_GREEN: return s.toGreen;
742 case GL_BLUE: return s.toBlue;
743 case GL_ALPHA: return s.toAlpha;
744 }
745 // Identity map for GL_ZERO / GL_ONE
746 return component;
747 }
748
concatSwizzles(const TextureSwizzle & first,const TextureSwizzle & next)749 TextureSwizzle concatSwizzles(const TextureSwizzle& first,
750 const TextureSwizzle& next) {
751
752 TextureSwizzle result;
753 result.toRed = swizzleComponentOf(first, next.toRed);
754 result.toGreen = swizzleComponentOf(first, next.toGreen);
755 result.toBlue = swizzleComponentOf(first, next.toBlue);
756 result.toAlpha = swizzleComponentOf(first, next.toAlpha);
757 return result;
758 }
759
isSwizzleParam(GLenum pname)760 bool isSwizzleParam(GLenum pname) {
761 switch (pname) {
762 case GL_TEXTURE_SWIZZLE_R:
763 case GL_TEXTURE_SWIZZLE_G:
764 case GL_TEXTURE_SWIZZLE_B:
765 case GL_TEXTURE_SWIZZLE_A:
766 return true;
767 default:
768 return false;
769 }
770 }
771
isIntegerInternalFormat(GLint internalformat)772 bool isIntegerInternalFormat(GLint internalformat) {
773 switch (internalformat) {
774 case GL_R8I:
775 case GL_R8UI:
776 case GL_R16I:
777 case GL_R16UI:
778 case GL_R32I:
779 case GL_R32UI:
780 case GL_RG8I:
781 case GL_RG8UI:
782 case GL_RG16I:
783 case GL_RG16UI:
784 case GL_RG32I:
785 case GL_RG32UI:
786 case GL_RGB8I:
787 case GL_RGB8UI:
788 case GL_RGB16I:
789 case GL_RGB16UI:
790 case GL_RGB32I:
791 case GL_RGB32UI:
792 case GL_RGBA8I:
793 case GL_RGBA8UI:
794 case GL_RGBA16I:
795 case GL_RGBA16UI:
796 case GL_RGBA32I:
797 case GL_RGBA32UI:
798 return true;
799 default:
800 return false;
801 }
802 }
803
doCompressedTexImage2DNative(GLEScontext * ctx,GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,const GLvoid * data)804 void doCompressedTexImage2DNative(GLEScontext* ctx, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
805 // AlignedBuf<uint8_t, 64> alignedData(imageSize);
806 // memcpy(alignedData.data(), data, imageSize);
807 // GLint err = ctx->dispatcher().glGetError();
808 ctx->dispatcher().glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
809 // fprintf(stderr, "%s: tex %u target 0x%x level 0x%x iformat 0x%x w h b %d %d %d imgSize %d\n", __func__, ctx->getBindedTexture(target), target, level, internalformat, width, height, border, imageSize);
810 // err = ctx->dispatcher().glGetError(); if (err) {
811 // fprintf(stderr, "%s:%d err 0x%x\n", __func__, __LINE__, err);
812 // }
813 }
814
doCompressedTexSubImage2DNative(GLEScontext * ctx,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,const GLvoid * data)815 void doCompressedTexSubImage2DNative(GLEScontext* ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
816 // AlignedBuf<uint8_t, 64> alignedData(imageSize);
817 // memcpy(alignedData.data(), data, imageSize);
818 // GLint err = ctx->dispatcher().glGetError();
819 ctx->dispatcher().glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
820 // fprintf(stderr, "%s: tex %u target 0x%x level 0x%x format 0x%x x y w h %d %d %d %d imgSize %d\n", __func__, ctx->getBindedTexture(target), target, level, format, xoffset, yoffset, width, height, imageSize);
821 // err = ctx->dispatcher().glGetError(); if (err) {
822 // fprintf(stderr, "%s:%d err 0x%x\n", __func__, __LINE__, err);
823 // }
824 }
825
forEachEtc2Format(std::function<void (GLint format)> f)826 void forEachEtc2Format(std::function<void(GLint format)> f) {
827 f(GL_COMPRESSED_RGB8_ETC2);
828 f(GL_COMPRESSED_SRGB8_ETC2);
829 f(GL_COMPRESSED_RGBA8_ETC2_EAC);
830 f(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
831 f(GL_COMPRESSED_R11_EAC);
832 f(GL_COMPRESSED_SIGNED_R11_EAC);
833 f(GL_COMPRESSED_RG11_EAC);
834 f(GL_COMPRESSED_SIGNED_RG11_EAC);
835 f(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2);
836 f(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
837 }
838
forEachAstcFormat(std::function<void (GLint format)> f)839 void forEachAstcFormat(std::function<void(GLint format)> f) {
840
841 #define CALL_ON_ASTC_FORMAT(typeName, blockWidth, blockHeight, srgbValue) \
842 f(typeName);
843
844 ASTC_FORMATS_LIST(CALL_ON_ASTC_FORMAT)
845 }
846
forEachBptcFormat(std::function<void (GLint format)> f)847 void forEachBptcFormat(std::function<void(GLint format)> f) {
848 f(GL_COMPRESSED_RGBA_BPTC_UNORM_EXT);
849 f(GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT);
850 f(GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT);
851 f(GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT);
852 }
853
forEachS3tcFormat(std::function<void (GLint format)> f)854 void forEachS3tcFormat(std::function<void(GLint format)> f) {
855 f(GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
856 f(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
857 f(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
858 f(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
859 f(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT);
860 f(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT);
861 f(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT);
862 f(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT);
863 }
864
isRgtcFormat(GLenum format)865 bool isRgtcFormat(GLenum format) {
866 switch (format) {
867 case GL_COMPRESSED_RED_RGTC1_EXT: // BC4U
868 case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT: // BC4S
869 case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: // BC5U
870 case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: // BC5S
871 return true;
872 default:
873 break;
874 }
875 return false;
876 }
877
isEtc2OrAstcFormat(GLenum format)878 bool isEtc2OrAstcFormat(GLenum format) {
879 switch (format) {
880 case GL_COMPRESSED_RGB8_ETC2:
881 case GL_COMPRESSED_SRGB8_ETC2:
882 case GL_COMPRESSED_RGBA8_ETC2_EAC:
883 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
884 case GL_COMPRESSED_R11_EAC:
885 case GL_COMPRESSED_SIGNED_R11_EAC:
886 case GL_COMPRESSED_RG11_EAC:
887 case GL_COMPRESSED_SIGNED_RG11_EAC:
888 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
889 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
890 return true;
891 default:
892 break;
893 }
894 return isAstcFormat(format);
895 }
896
shouldPassthroughCompressedFormat(GLEScontext * ctx,GLenum internalformat)897 bool shouldPassthroughCompressedFormat(GLEScontext* ctx, GLenum internalformat) {
898 if (isEtc2Format(internalformat)) {
899 return ctx->getCaps()->hasEtc2Support;
900 } else if (isAstcFormat(internalformat)) {
901 return ctx->getCaps()->hasAstcSupport;
902 } else if (isBptcFormat(internalformat)) {
903 return ctx->getCaps()->hasBptcSupport;
904 } else if (isS3tcFormat(internalformat)) {
905 return ctx->getCaps()->hasS3tcSupport;
906 } else if (isRgtcFormat(internalformat)) {
907 return ctx->getCaps()->hasRgtcSupport;
908 }
909 return false;
910 }
911
s_texAlign(uint32_t v,uint32_t align)912 static uint32_t s_texAlign(uint32_t v, uint32_t align) {
913 uint32_t rem = v % align;
914 return rem ? (v + (align - rem)) : v;
915 }
916
917 // s_computePixelSize is both in the host and the guest. Consider moving it to
918 // android-emugl/shared
919
s_computePixelSize(GLenum format,GLenum type)920 static int s_computePixelSize(GLenum format, GLenum type) {
921 #define FORMAT_ERROR(format, type) \
922 fprintf(stderr, "%s:%d unknown format/type 0x%x 0x%x\n", __FUNCTION__, \
923 __LINE__, format, type);
924
925 switch (type) {
926 case GL_BYTE:
927 switch (format) {
928 case GL_R8:
929 case GL_R8I:
930 case GL_R8_SNORM:
931 case GL_RED:
932 return 1;
933 case GL_RED_INTEGER:
934 return 1;
935 case GL_RG8:
936 case GL_RG8I:
937 case GL_RG8_SNORM:
938 case GL_RG:
939 return 1 * 2;
940 case GL_RG_INTEGER:
941 return 1 * 2;
942 case GL_RGB8:
943 case GL_RGB8I:
944 case GL_RGB8_SNORM:
945 case GL_RGB:
946 return 1 * 3;
947 case GL_RGB_INTEGER:
948 return 1 * 3;
949 case GL_RGBA8:
950 case GL_RGBA8I:
951 case GL_RGBA8_SNORM:
952 case GL_RGBA:
953 return 1 * 4;
954 case GL_RGBA_INTEGER:
955 return 1 * 4;
956 default:
957 FORMAT_ERROR(format, type);
958 }
959 break;
960 case GL_UNSIGNED_BYTE:
961 switch (format) {
962 case GL_R8:
963 case GL_R8UI:
964 case GL_RED:
965 return 1;
966 case GL_RED_INTEGER:
967 return 1;
968 case GL_ALPHA8_EXT:
969 case GL_ALPHA:
970 return 1;
971 case GL_LUMINANCE8_EXT:
972 case GL_LUMINANCE:
973 return 1;
974 case GL_LUMINANCE8_ALPHA8_EXT:
975 case GL_LUMINANCE_ALPHA:
976 return 1 * 2;
977 case GL_RG8:
978 case GL_RG8UI:
979 case GL_RG:
980 return 1 * 2;
981 case GL_RG_INTEGER:
982 return 1 * 2;
983 case GL_RGB8:
984 case GL_RGB8UI:
985 case GL_SRGB8:
986 case GL_RGB:
987 return 1 * 3;
988 case GL_RGB_INTEGER:
989 return 1 * 3;
990 case GL_RGBA8:
991 case GL_RGBA8UI:
992 case GL_SRGB8_ALPHA8:
993 case GL_RGBA:
994 return 1 * 4;
995 case GL_RGBA_INTEGER:
996 return 1 * 4;
997 case GL_BGRA_EXT:
998 case GL_BGRA8_EXT:
999 return 1 * 4;
1000 default:
1001 FORMAT_ERROR(format, type);
1002 }
1003 break;
1004 case GL_SHORT:
1005 switch (format) {
1006 case GL_R16I:
1007 case GL_RED_INTEGER:
1008 return 2;
1009 case GL_RG16I:
1010 case GL_RG_INTEGER:
1011 return 2 * 2;
1012 case GL_RGB16I:
1013 case GL_RGB_INTEGER:
1014 return 2 * 3;
1015 case GL_RGBA16I:
1016 case GL_RGBA_INTEGER:
1017 return 2 * 4;
1018 default:
1019 FORMAT_ERROR(format, type);
1020 }
1021 break;
1022 case GL_UNSIGNED_SHORT:
1023 switch (format) {
1024 case GL_DEPTH_COMPONENT16:
1025 case GL_DEPTH_COMPONENT:
1026 return 2;
1027 case GL_R16UI:
1028 case GL_RED_INTEGER:
1029 return 2;
1030 case GL_RG16UI:
1031 case GL_RG_INTEGER:
1032 return 2 * 2;
1033 case GL_RGB16UI:
1034 case GL_RGB_INTEGER:
1035 return 2 * 3;
1036 case GL_RGBA16UI:
1037 case GL_RGBA_INTEGER:
1038 return 2 * 4;
1039 default:
1040 FORMAT_ERROR(format, type);
1041 }
1042 break;
1043 case GL_INT:
1044 switch (format) {
1045 case GL_R32I:
1046 case GL_RED_INTEGER:
1047 return 4;
1048 case GL_RG32I:
1049 case GL_RG_INTEGER:
1050 return 4 * 2;
1051 case GL_RGB32I:
1052 case GL_RGB_INTEGER:
1053 return 4 * 3;
1054 case GL_RGBA32I:
1055 case GL_RGBA_INTEGER:
1056 return 4 * 4;
1057 default:
1058 FORMAT_ERROR(format, type);
1059 }
1060 break;
1061 case GL_UNSIGNED_INT:
1062 switch (format) {
1063 case GL_DEPTH_COMPONENT16:
1064 case GL_DEPTH_COMPONENT24:
1065 case GL_DEPTH_COMPONENT32_OES:
1066 case GL_DEPTH_COMPONENT:
1067 return 4;
1068 case GL_R32UI:
1069 case GL_RED_INTEGER:
1070 return 4;
1071 case GL_RG32UI:
1072 case GL_RG_INTEGER:
1073 return 4 * 2;
1074 case GL_RGB32UI:
1075 case GL_RGB_INTEGER:
1076 return 4 * 3;
1077 case GL_RGBA32UI:
1078 case GL_RGBA_INTEGER:
1079 return 4 * 4;
1080 default:
1081 FORMAT_ERROR(format, type);
1082 }
1083 break;
1084 case GL_UNSIGNED_SHORT_4_4_4_4:
1085 case GL_UNSIGNED_SHORT_5_5_5_1:
1086 case GL_UNSIGNED_SHORT_5_6_5:
1087 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1088 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1089 return 2;
1090 case GL_UNSIGNED_INT_10F_11F_11F_REV:
1091 case GL_UNSIGNED_INT_5_9_9_9_REV:
1092 case GL_UNSIGNED_INT_2_10_10_10_REV:
1093 case GL_UNSIGNED_INT_24_8_OES:
1094 return 4;
1095 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
1096 return 4 + 4;
1097 case GL_FLOAT:
1098 switch (format) {
1099 case GL_DEPTH_COMPONENT32F:
1100 case GL_DEPTH_COMPONENT:
1101 return 4;
1102 case GL_ALPHA32F_EXT:
1103 case GL_ALPHA:
1104 return 4;
1105 case GL_LUMINANCE32F_EXT:
1106 case GL_LUMINANCE:
1107 return 4;
1108 case GL_LUMINANCE_ALPHA32F_EXT:
1109 case GL_LUMINANCE_ALPHA:
1110 return 4 * 2;
1111 case GL_RED:
1112 return 4;
1113 case GL_R32F:
1114 return 4;
1115 case GL_RG:
1116 return 4 * 2;
1117 case GL_RG32F:
1118 return 4 * 2;
1119 case GL_RGB:
1120 return 4 * 3;
1121 case GL_RGB32F:
1122 return 4 * 3;
1123 case GL_RGBA:
1124 return 4 * 4;
1125 case GL_RGBA32F:
1126 return 4 * 4;
1127 default:
1128 FORMAT_ERROR(format, type);
1129 }
1130 break;
1131 case GL_HALF_FLOAT:
1132 case GL_HALF_FLOAT_OES:
1133 switch (format) {
1134 case GL_ALPHA16F_EXT:
1135 case GL_ALPHA:
1136 return 2;
1137 case GL_LUMINANCE16F_EXT:
1138 case GL_LUMINANCE:
1139 return 2;
1140 case GL_LUMINANCE_ALPHA16F_EXT:
1141 case GL_LUMINANCE_ALPHA:
1142 return 2 * 2;
1143 case GL_RED:
1144 return 2;
1145 case GL_R16F:
1146 return 2;
1147 case GL_RG:
1148 return 2 * 2;
1149 case GL_RG16F:
1150 return 2 * 2;
1151 case GL_RGB:
1152 return 2 * 3;
1153 case GL_RGB16F:
1154 return 2 * 3;
1155 case GL_RGBA:
1156 return 2 * 4;
1157 case GL_RGBA16F:
1158 return 2 * 4;
1159 default:
1160 FORMAT_ERROR(format, type);
1161 }
1162 break;
1163 default:
1164 FORMAT_ERROR(format, type);
1165 }
1166
1167 return 0;
1168 }
1169
texImageSize(GLenum internalformat,GLenum type,int unpackAlignment,GLsizei width,GLsizei height)1170 uint32_t texImageSize(GLenum internalformat,
1171 GLenum type,
1172 int unpackAlignment,
1173 GLsizei width,
1174 GLsizei height) {
1175
1176 uint32_t alignedWidth = s_texAlign(width, unpackAlignment);
1177 uint32_t pixelSize = s_computePixelSize(internalformat, type);
1178 uint32_t totalSize = pixelSize * alignedWidth * height;
1179
1180 return totalSize;
1181 }
1182
getFormatFromInternalFormat(GLint internalFormat)1183 GLenum getFormatFromInternalFormat(GLint internalFormat) {
1184 switch (internalFormat) {
1185 case GL_R8:
1186 return GL_RED;
1187 case GL_RG8:
1188 return GL_RG;
1189 case GL_RGB8:
1190 case GL_RGB565:
1191 case GL_RGB16F:
1192 return GL_RGB;
1193 case GL_RGBA8:
1194 case GL_RGB5_A1_OES:
1195 case GL_RGBA4_OES:
1196 case GL_UNSIGNED_INT_10_10_10_2_OES:
1197 case GL_RGB10_A2:
1198 case GL_RGBA16F:
1199 return GL_RGBA;
1200 case GL_BGRA8_EXT:
1201 return GL_BGRA_EXT;
1202 default: // already unsized
1203 return internalFormat;
1204 }
1205 }
1206
getTypeFromInternalFormat(GLint internalFormat)1207 GLenum getTypeFromInternalFormat(GLint internalFormat) {
1208 switch (internalFormat) {
1209 case GL_RGB:
1210 case GL_RGB8:
1211 return GL_UNSIGNED_BYTE;
1212 case GL_RGB565_OES:
1213 return GL_UNSIGNED_SHORT_5_6_5;
1214 case GL_RGBA:
1215 case GL_RGBA8:
1216 case GL_RGB5_A1_OES:
1217 case GL_RGBA4_OES:
1218 return GL_UNSIGNED_BYTE;
1219 case GL_UNSIGNED_INT_10_10_10_2_OES:
1220 return GL_UNSIGNED_SHORT;
1221 case GL_RGB10_A2:
1222 return GL_UNSIGNED_INT_2_10_10_10_REV;
1223 case GL_RGB16F:
1224 return GL_HALF_FLOAT;
1225 case GL_RGBA16F:
1226 return GL_HALF_FLOAT;
1227 case GL_LUMINANCE:
1228 return GL_UNSIGNED_SHORT;
1229 case GL_BGRA_EXT:
1230 return GL_UNSIGNED_BYTE;
1231 case GL_R8:
1232 case GL_RED:
1233 return GL_UNSIGNED_BYTE;
1234 case GL_RG8:
1235 case GL_RG:
1236 return GL_UNSIGNED_BYTE;
1237 default:
1238 fprintf(stderr, "%s: Unknown format 0x%x\n", __func__,
1239 internalFormat);
1240 return GL_UNSIGNED_BYTE;
1241 }
1242 }
1243
1244
unpackCheckAndUpdate(GLenum name,GLint newValue)1245 GLint TextureUnpackReset::unpackCheckAndUpdate(GLenum name, GLint newValue) {
1246 GLint curValue;
1247 glesContext->dispatcher().glGetIntegerv(name, &curValue);
1248 if (curValue != newValue) {
1249 glesContext->dispatcher().glPixelStorei(name, newValue);
1250 }
1251 return curValue;
1252 }
1253
TextureUnpackReset(GLEScontext * ctx)1254 TextureUnpackReset::TextureUnpackReset(GLEScontext* ctx) : glesContext(ctx) {
1255 unpackAlignment = unpackCheckAndUpdate(GL_UNPACK_ALIGNMENT, kUnpackAlignment);
1256 if (glesContext->getMajorVersion() >= 3) {
1257 unpackRowLength = unpackCheckAndUpdate(GL_UNPACK_ROW_LENGTH, kUnpackRowLength);
1258 unpackImageHeight = unpackCheckAndUpdate(GL_UNPACK_IMAGE_HEIGHT, kUnpackImageHeight);
1259 unpackSkipRows = unpackCheckAndUpdate(GL_UNPACK_SKIP_ROWS, kUnpackSkipRows);
1260 unpackSkipPixels = unpackCheckAndUpdate(GL_UNPACK_SKIP_PIXELS, kUnpackSkipPixels);
1261 unpackSkipImages = unpackCheckAndUpdate(GL_UNPACK_SKIP_IMAGES, kUnpackSkipImages);
1262 } else {
1263 // avoid clang-tidy warnings on uninitialized values
1264 unpackRowLength = 0;
1265 unpackImageHeight = 0;
1266 unpackSkipRows = 0;
1267 unpackSkipPixels = 0;
1268 unpackSkipImages = 0;
1269 }
1270 }
~TextureUnpackReset()1271 TextureUnpackReset::~TextureUnpackReset() {
1272 unpackCheckAndUpdate(GL_UNPACK_ALIGNMENT, unpackAlignment);
1273 if (glesContext->getMajorVersion() >= 3) {
1274 unpackCheckAndUpdate(GL_UNPACK_ROW_LENGTH, unpackRowLength);
1275 unpackCheckAndUpdate(GL_UNPACK_IMAGE_HEIGHT, unpackImageHeight);
1276 unpackCheckAndUpdate(GL_UNPACK_SKIP_ROWS, unpackSkipRows);
1277 unpackCheckAndUpdate(GL_UNPACK_SKIP_PIXELS, unpackSkipPixels);
1278 unpackCheckAndUpdate(GL_UNPACK_SKIP_IMAGES, unpackSkipImages);
1279 }
1280 }
1281
1282