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