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
347 default:
348 return compressedFormat;
349 }
350 }
351
352 class ScopedFetchUnpackData {
353 public:
ScopedFetchUnpackData(GLEScontext * ctx,GLintptr offset,GLsizei dataSize)354 ScopedFetchUnpackData(GLEScontext* ctx, GLintptr offset,
355 GLsizei dataSize) : mCtx(ctx) {
356 mData = ctx->dispatcher().glMapBufferRange(
357 GL_PIXEL_UNPACK_BUFFER,
358 offset, dataSize, GL_MAP_READ_BIT);
359 if (mData) {
360 ctx->dispatcher().glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING,
361 &mUnpackBuffer);
362 ctx->dispatcher().glBindBuffer(GL_PIXEL_UNPACK_BUFFER,
363 0);
364 }
365 }
~ScopedFetchUnpackData()366 ~ScopedFetchUnpackData() {
367 if (mData) {
368 mCtx->dispatcher().glBindBuffer(GL_PIXEL_UNPACK_BUFFER,
369 mUnpackBuffer);
370 mCtx->dispatcher().glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
371 }
372 }
data()373 void* data() {
374 return mData;
375 }
376 private:
377 const GLEScontext* mCtx;
378 void* mData = nullptr;
379 GLint mUnpackBuffer = 0;
380 };
381
doCompressedTexImage2D(GLEScontext * ctx,GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,const GLvoid * data,glTexImage2D_t glTexImage2DPtr)382 void doCompressedTexImage2D(GLEScontext* ctx, GLenum target, GLint level,
383 GLenum internalformat, GLsizei width,
384 GLsizei height, GLint border,
385 GLsizei imageSize, const GLvoid* data,
386 glTexImage2D_t glTexImage2DPtr) {
387 /* XXX: This is just a hack to fix the resolve of glTexImage2D problem
388 It will be removed when we'll no longer link against ligGL */
389 /*typedef void (GLAPIENTRY *glTexImage2DPtr_t ) (
390 GLenum target, GLint level, GLint internalformat,
391 GLsizei width, GLsizei height, GLint border,
392 GLenum format, GLenum type, const GLvoid *pixels);
393
394 glTexImage2DPtr_t glTexImage2DPtr;
395 glTexImage2DPtr = (glTexImage2DPtr_t)funcPtr;*/
396 bool needUnpackBuffer = false;
397 if (ctx->getMajorVersion() >= 3) {
398 GLint unpackBuffer = 0;
399 ctx->dispatcher().glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING,
400 &unpackBuffer);
401 needUnpackBuffer = unpackBuffer;
402 }
403
404 if (isEtcFormat(internalformat)) {
405 GLint format = GL_RGB;
406 GLint type = GL_UNSIGNED_BYTE;
407 GLint convertedInternalFormat = decompressedInternalFormat(ctx, internalformat);
408 ETC2ImageFormat etcFormat = EtcRGB8;
409 switch (internalformat) {
410 case GL_COMPRESSED_RGB8_ETC2:
411 case GL_ETC1_RGB8_OES:
412 break;
413 case GL_COMPRESSED_RGBA8_ETC2_EAC:
414 etcFormat = EtcRGBA8;
415 format = GL_RGBA;
416 break;
417 case GL_COMPRESSED_SRGB8_ETC2:
418 break;
419 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
420 etcFormat = EtcRGBA8;
421 format = GL_RGBA;
422 break;
423 case GL_COMPRESSED_R11_EAC:
424 etcFormat = EtcR11;
425 format = GL_RED;
426 type = GL_FLOAT;
427 break;
428 case GL_COMPRESSED_SIGNED_R11_EAC:
429 etcFormat = EtcSignedR11;
430 format = GL_RED;
431 type = GL_FLOAT;
432 break;
433 case GL_COMPRESSED_RG11_EAC:
434 etcFormat = EtcRG11;
435 format = GL_RG;
436 type = GL_FLOAT;
437 break;
438 case GL_COMPRESSED_SIGNED_RG11_EAC:
439 etcFormat = EtcSignedRG11;
440 format = GL_RG;
441 type = GL_FLOAT;
442 break;
443 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
444 etcFormat = EtcRGB8A1;
445 format = GL_RGBA;
446 break;
447 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
448 etcFormat = EtcRGB8A1;
449 format = GL_RGBA;
450 break;
451 }
452 int pixelSize = etc_get_decoded_pixel_size(etcFormat);
453 GLsizei compressedSize =
454 etc_get_encoded_data_size(etcFormat, width, height);
455 SET_ERROR_IF((compressedSize != imageSize), GL_INVALID_VALUE);
456 std::unique_ptr<ScopedFetchUnpackData> unpackData;
457 bool emulateCompressedData = false;
458 if (needUnpackBuffer) {
459 unpackData.reset(new ScopedFetchUnpackData(ctx,
460 reinterpret_cast<GLintptr>(data), compressedSize));
461 data = unpackData->data();
462 SET_ERROR_IF(!data, GL_INVALID_OPERATION);
463 } else {
464 if (!data) {
465 emulateCompressedData = true;
466 data = new char[compressedSize];
467 }
468 }
469
470 const int32_t align = ctx->getUnpackAlignment()-1;
471 const int32_t bpr = ((width * pixelSize) + align) & ~align;
472 const size_t size = bpr * height;
473 std::unique_ptr<etc1_byte[]> pOut(new etc1_byte[size]);
474
475 int res =
476 etc2_decode_image(
477 (const etc1_byte*)data, etcFormat, pOut.get(),
478 width, height, bpr);
479 SET_ERROR_IF(res!=0, GL_INVALID_VALUE);
480
481 glTexImage2DPtr(target, level, convertedInternalFormat,
482 width, height, border, format, type, pOut.get());
483 if (emulateCompressedData) {
484 delete [] (char*)data;
485 }
486 } else if (isAstcFormat(internalformat)) {
487 // TODO: fix the case when GL_PIXEL_UNPACK_BUFFER is bound
488 astc_codec::FootprintType footprint;
489 bool srgb;
490 getAstcFormatInfo(internalformat, &footprint, &srgb);
491
492 const int32_t align = ctx->getUnpackAlignment() - 1;
493 const int32_t stride = ((width * 4) + align) & ~align;
494 const size_t size = stride * height;
495
496 AlignedBuf<uint8_t, 64> alignedUncompressedData(size);
497
498 const bool result = astc_codec::ASTCDecompressToRGBA(
499 reinterpret_cast<const uint8_t*>(data), imageSize, width,
500 height, footprint, alignedUncompressedData.data(), size,
501 stride);
502 SET_ERROR_IF(!result, GL_INVALID_VALUE);
503
504 glTexImage2DPtr(target, level, srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8, width,
505 height, border, GL_RGBA, GL_UNSIGNED_BYTE,
506 alignedUncompressedData.data());
507
508 } else if (isPaletteFormat(internalformat)) {
509 // TODO: fix the case when GL_PIXEL_UNPACK_BUFFER is bound
510 SET_ERROR_IF(
511 level > log2(ctx->getMaxTexSize()) ||
512 border !=0 || level > 0 ||
513 !GLESvalidate::texImgDim(
514 width, height, ctx->getMaxTexSize() + 2),
515 GL_INVALID_VALUE);
516 SET_ERROR_IF(!data,GL_INVALID_OPERATION);
517
518 int nMipmaps = -level + 1;
519 GLsizei tmpWidth = width;
520 GLsizei tmpHeight = height;
521
522 for(int i = 0; i < nMipmaps; i++)
523 {
524 GLenum uncompressedFrmt;
525 unsigned char* uncompressed =
526 uncompressTexture(internalformat, uncompressedFrmt,
527 width, height, imageSize, data, i);
528 glTexImage2DPtr(target, i, uncompressedFrmt,
529 tmpWidth, tmpHeight, border,
530 uncompressedFrmt, GL_UNSIGNED_BYTE, uncompressed);
531 tmpWidth /= 2;
532 tmpHeight /= 2;
533 delete [] uncompressed;
534 }
535 } else {
536 SET_ERROR_IF(1, GL_INVALID_ENUM);
537 }
538 }
539
deleteRenderbufferGlobal(GLuint rbo)540 void deleteRenderbufferGlobal(GLuint rbo) {
541 if (rbo) {
542 GLEScontext::dispatcher().glDeleteRenderbuffers(1, &rbo);
543 }
544 }
545
isCubeMapFaceTarget(GLenum target)546 bool isCubeMapFaceTarget(GLenum target) {
547 switch (target) {
548 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
549 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
550 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
551 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
552 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
553 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
554 return true;
555 }
556 return false;
557 }
558
isCoreProfileEmulatedFormat(GLenum format)559 bool isCoreProfileEmulatedFormat(GLenum format) {
560 switch (format) {
561 case GL_ALPHA:
562 case GL_LUMINANCE:
563 case GL_LUMINANCE_ALPHA:
564 return true;
565 default:
566 return false;
567 }
568 }
569
getCoreProfileEmulatedFormat(GLenum format)570 GLenum getCoreProfileEmulatedFormat(GLenum format) {
571 switch (format) {
572 case GL_ALPHA:
573 case GL_LUMINANCE:
574 return GL_RED;
575 case GL_LUMINANCE_ALPHA:
576 return GL_RG;
577 }
578 return format;
579 }
580
getCoreProfileEmulatedInternalFormat(GLint internalformat,GLenum type)581 GLint getCoreProfileEmulatedInternalFormat(GLint internalformat, GLenum type) {
582 switch (internalformat) {
583 case GL_ALPHA:
584 case GL_LUMINANCE:
585 switch (type) {
586 case GL_UNSIGNED_BYTE:
587 return GL_R8;
588 case GL_FLOAT:
589 return GL_R32F;
590 case GL_HALF_FLOAT:
591 return GL_R16F;
592 }
593 return GL_R8;
594 case GL_LUMINANCE_ALPHA:
595 switch (type) {
596 case GL_UNSIGNED_BYTE:
597 return GL_RG8;
598 case GL_FLOAT:
599 return GL_RG32F;
600 case GL_HALF_FLOAT:
601 return GL_RG16F;
602 }
603 return GL_RG8;
604 }
605 fprintf(stderr,
606 "%s: warning: unsupported alpha/luminance internal format 0x%x type 0x%x\n",
607 __func__, internalformat, type);
608 return GL_R8;
609 }
610
getSwizzleForEmulatedFormat(GLenum format)611 TextureSwizzle getSwizzleForEmulatedFormat(GLenum format) {
612 TextureSwizzle res;
613 switch (format) {
614 case GL_ALPHA:
615 res.toRed = GL_ZERO;
616 res.toGreen = GL_ZERO;
617 res.toBlue = GL_ZERO;
618 res.toAlpha = GL_RED;
619 break;
620 case GL_LUMINANCE:
621 res.toRed = GL_RED;
622 res.toGreen = GL_RED;
623 res.toBlue = GL_RED;
624 res.toAlpha = GL_ONE;
625 break;
626 case GL_LUMINANCE_ALPHA:
627 res.toRed = GL_RED;
628 res.toGreen = GL_RED;
629 res.toBlue = GL_RED;
630 res.toAlpha = GL_GREEN;
631 break;
632 default:
633 break;
634 }
635 return res;
636 }
637
638 // Inverse swizzle: if we were writing fragments back to this texture,
639 // how should the components be re-arranged?
getInverseSwizzleForEmulatedFormat(GLenum format)640 TextureSwizzle getInverseSwizzleForEmulatedFormat(GLenum format) {
641 TextureSwizzle res;
642 switch (format) {
643 case GL_ALPHA:
644 res.toRed = GL_ALPHA;
645 res.toGreen = GL_ZERO;
646 res.toBlue = GL_ZERO;
647 res.toAlpha = GL_ZERO;
648 break;
649 case GL_LUMINANCE:
650 res.toRed = GL_RED;
651 res.toGreen = GL_ZERO;
652 res.toBlue = GL_ZERO;
653 res.toAlpha = GL_ZERO;
654 break;
655 case GL_LUMINANCE_ALPHA:
656 res.toRed = GL_RED;
657 res.toGreen = GL_ALPHA;
658 res.toBlue = GL_ZERO;
659 res.toAlpha = GL_ZERO;
660 break;
661 default:
662 break;
663 }
664 return res;
665 }
666
swizzleComponentOf(const TextureSwizzle & s,GLenum component)667 GLenum swizzleComponentOf(const TextureSwizzle& s, GLenum component) {
668 switch (component) {
669 case GL_RED: return s.toRed;
670 case GL_GREEN: return s.toGreen;
671 case GL_BLUE: return s.toBlue;
672 case GL_ALPHA: return s.toAlpha;
673 }
674 // Identity map for GL_ZERO / GL_ONE
675 return component;
676 }
677
concatSwizzles(const TextureSwizzle & first,const TextureSwizzle & next)678 TextureSwizzle concatSwizzles(const TextureSwizzle& first,
679 const TextureSwizzle& next) {
680
681 TextureSwizzle result;
682 result.toRed = swizzleComponentOf(first, next.toRed);
683 result.toGreen = swizzleComponentOf(first, next.toGreen);
684 result.toBlue = swizzleComponentOf(first, next.toBlue);
685 result.toAlpha = swizzleComponentOf(first, next.toAlpha);
686 return result;
687 }
688
isSwizzleParam(GLenum pname)689 bool isSwizzleParam(GLenum pname) {
690 switch (pname) {
691 case GL_TEXTURE_SWIZZLE_R:
692 case GL_TEXTURE_SWIZZLE_G:
693 case GL_TEXTURE_SWIZZLE_B:
694 case GL_TEXTURE_SWIZZLE_A:
695 return true;
696 default:
697 return false;
698 }
699 }
700
isIntegerInternalFormat(GLint internalformat)701 bool isIntegerInternalFormat(GLint internalformat) {
702 switch (internalformat) {
703 case GL_R8I:
704 case GL_R8UI:
705 case GL_R16I:
706 case GL_R16UI:
707 case GL_R32I:
708 case GL_R32UI:
709 case GL_RG8I:
710 case GL_RG8UI:
711 case GL_RG16I:
712 case GL_RG16UI:
713 case GL_RG32I:
714 case GL_RG32UI:
715 case GL_RGB8I:
716 case GL_RGB8UI:
717 case GL_RGB16I:
718 case GL_RGB16UI:
719 case GL_RGB32I:
720 case GL_RGB32UI:
721 case GL_RGBA8I:
722 case GL_RGBA8UI:
723 case GL_RGBA16I:
724 case GL_RGBA16UI:
725 case GL_RGBA32I:
726 case GL_RGBA32UI:
727 return true;
728 default:
729 return false;
730 }
731 }
732
doCompressedTexImage2DNative(GLEScontext * ctx,GLenum target,GLint level,GLenum internalformat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,const GLvoid * data)733 void doCompressedTexImage2DNative(GLEScontext* ctx, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
734 // AlignedBuf<uint8_t, 64> alignedData(imageSize);
735 // memcpy(alignedData.data(), data, imageSize);
736 // GLint err = ctx->dispatcher().glGetError();
737 ctx->dispatcher().glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
738 // 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);
739 // err = ctx->dispatcher().glGetError(); if (err) {
740 // fprintf(stderr, "%s:%d err 0x%x\n", __func__, __LINE__, err);
741 // }
742 }
743
doCompressedTexSubImage2DNative(GLEScontext * ctx,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,const GLvoid * data)744 void doCompressedTexSubImage2DNative(GLEScontext* ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
745 // AlignedBuf<uint8_t, 64> alignedData(imageSize);
746 // memcpy(alignedData.data(), data, imageSize);
747 // GLint err = ctx->dispatcher().glGetError();
748 ctx->dispatcher().glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
749 // 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);
750 // err = ctx->dispatcher().glGetError(); if (err) {
751 // fprintf(stderr, "%s:%d err 0x%x\n", __func__, __LINE__, err);
752 // }
753 }
754
forEachEtc2Format(std::function<void (GLint format)> f)755 void forEachEtc2Format(std::function<void(GLint format)> f) {
756 f(GL_COMPRESSED_RGB8_ETC2);
757 f(GL_COMPRESSED_SRGB8_ETC2);
758 f(GL_COMPRESSED_RGBA8_ETC2_EAC);
759 f(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
760 f(GL_COMPRESSED_R11_EAC);
761 f(GL_COMPRESSED_SIGNED_R11_EAC);
762 f(GL_COMPRESSED_RG11_EAC);
763 f(GL_COMPRESSED_SIGNED_RG11_EAC);
764 f(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2);
765 f(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
766 }
767
forEachAstcFormat(std::function<void (GLint format)> f)768 void forEachAstcFormat(std::function<void(GLint format)> f) {
769
770 #define CALL_ON_ASTC_FORMAT(typeName, footprintType, srgbValue) \
771 f(typeName);
772
773 ASTC_FORMATS_LIST(CALL_ON_ASTC_FORMAT)
774 }
775
forEachBptcFormat(std::function<void (GLint format)> f)776 void forEachBptcFormat(std::function<void(GLint format)> f) {
777 f(GL_COMPRESSED_RGBA_BPTC_UNORM_EXT);
778 f(GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT);
779 f(GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT);
780 f(GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT);
781 }
782
forEachS3tcFormat(std::function<void (GLint format)> f)783 void forEachS3tcFormat(std::function<void(GLint format)> f) {
784 f(GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
785 f(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
786 f(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
787 f(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
788 f(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT);
789 f(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT);
790 f(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT);
791 f(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT);
792 }
793
isEtc2OrAstcFormat(GLenum format)794 bool isEtc2OrAstcFormat(GLenum format) {
795 switch (format) {
796 case GL_COMPRESSED_RGB8_ETC2:
797 case GL_COMPRESSED_SRGB8_ETC2:
798 case GL_COMPRESSED_RGBA8_ETC2_EAC:
799 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
800 case GL_COMPRESSED_R11_EAC:
801 case GL_COMPRESSED_SIGNED_R11_EAC:
802 case GL_COMPRESSED_RG11_EAC:
803 case GL_COMPRESSED_SIGNED_RG11_EAC:
804 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
805 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
806 return true;
807 default:
808 break;
809 }
810 return isAstcFormat(format);
811 }
812
shouldPassthroughCompressedFormat(GLEScontext * ctx,GLenum internalformat)813 bool shouldPassthroughCompressedFormat(GLEScontext* ctx, GLenum internalformat) {
814 if (isEtc2Format(internalformat)) {
815 return ctx->getCaps()->hasEtc2Support;
816 } else if (isAstcFormat(internalformat)) {
817 return ctx->getCaps()->hasAstcSupport;
818 } else if (isBptcFormat(internalformat)) {
819 return ctx->getCaps()->hasBptcSupport;
820 } else if (isS3tcFormat(internalformat)) {
821 return ctx->getCaps()->hasS3tcSupport;
822 }
823 return false;
824 }
825
s_texAlign(uint32_t v,uint32_t align)826 static uint32_t s_texAlign(uint32_t v, uint32_t align) {
827 uint32_t rem = v % align;
828 return rem ? (v + (align - rem)) : v;
829 }
830
831 // s_computePixelSize is both in the host and the guest. Consider moving it to
832 // android-emugl/shared
833
s_computePixelSize(GLenum format,GLenum type)834 static int s_computePixelSize(GLenum format, GLenum type) {
835 #define FORMAT_ERROR(format, type) \
836 fprintf(stderr, "%s:%d unknown format/type 0x%x 0x%x\n", __FUNCTION__, \
837 __LINE__, format, type);
838
839 switch (type) {
840 case GL_BYTE:
841 switch (format) {
842 case GL_R8:
843 case GL_R8I:
844 case GL_R8_SNORM:
845 case GL_RED:
846 return 1;
847 case GL_RED_INTEGER:
848 return 1;
849 case GL_RG8:
850 case GL_RG8I:
851 case GL_RG8_SNORM:
852 case GL_RG:
853 return 1 * 2;
854 case GL_RG_INTEGER:
855 return 1 * 2;
856 case GL_RGB8:
857 case GL_RGB8I:
858 case GL_RGB8_SNORM:
859 case GL_RGB:
860 return 1 * 3;
861 case GL_RGB_INTEGER:
862 return 1 * 3;
863 case GL_RGBA8:
864 case GL_RGBA8I:
865 case GL_RGBA8_SNORM:
866 case GL_RGBA:
867 return 1 * 4;
868 case GL_RGBA_INTEGER:
869 return 1 * 4;
870 default:
871 FORMAT_ERROR(format, type);
872 }
873 break;
874 case GL_UNSIGNED_BYTE:
875 switch (format) {
876 case GL_R8:
877 case GL_R8UI:
878 case GL_RED:
879 return 1;
880 case GL_RED_INTEGER:
881 return 1;
882 case GL_ALPHA8_EXT:
883 case GL_ALPHA:
884 return 1;
885 case GL_LUMINANCE8_EXT:
886 case GL_LUMINANCE:
887 return 1;
888 case GL_LUMINANCE8_ALPHA8_EXT:
889 case GL_LUMINANCE_ALPHA:
890 return 1 * 2;
891 case GL_RG8:
892 case GL_RG8UI:
893 case GL_RG:
894 return 1 * 2;
895 case GL_RG_INTEGER:
896 return 1 * 2;
897 case GL_RGB8:
898 case GL_RGB8UI:
899 case GL_SRGB8:
900 case GL_RGB:
901 return 1 * 3;
902 case GL_RGB_INTEGER:
903 return 1 * 3;
904 case GL_RGBA8:
905 case GL_RGBA8UI:
906 case GL_SRGB8_ALPHA8:
907 case GL_RGBA:
908 return 1 * 4;
909 case GL_RGBA_INTEGER:
910 return 1 * 4;
911 case GL_BGRA_EXT:
912 case GL_BGRA8_EXT:
913 return 1 * 4;
914 default:
915 FORMAT_ERROR(format, type);
916 }
917 break;
918 case GL_SHORT:
919 switch (format) {
920 case GL_R16I:
921 case GL_RED_INTEGER:
922 return 2;
923 case GL_RG16I:
924 case GL_RG_INTEGER:
925 return 2 * 2;
926 case GL_RGB16I:
927 case GL_RGB_INTEGER:
928 return 2 * 3;
929 case GL_RGBA16I:
930 case GL_RGBA_INTEGER:
931 return 2 * 4;
932 default:
933 FORMAT_ERROR(format, type);
934 }
935 break;
936 case GL_UNSIGNED_SHORT:
937 switch (format) {
938 case GL_DEPTH_COMPONENT16:
939 case GL_DEPTH_COMPONENT:
940 return 2;
941 case GL_R16UI:
942 case GL_RED_INTEGER:
943 return 2;
944 case GL_RG16UI:
945 case GL_RG_INTEGER:
946 return 2 * 2;
947 case GL_RGB16UI:
948 case GL_RGB_INTEGER:
949 return 2 * 3;
950 case GL_RGBA16UI:
951 case GL_RGBA_INTEGER:
952 return 2 * 4;
953 default:
954 FORMAT_ERROR(format, type);
955 }
956 break;
957 case GL_INT:
958 switch (format) {
959 case GL_R32I:
960 case GL_RED_INTEGER:
961 return 4;
962 case GL_RG32I:
963 case GL_RG_INTEGER:
964 return 4 * 2;
965 case GL_RGB32I:
966 case GL_RGB_INTEGER:
967 return 4 * 3;
968 case GL_RGBA32I:
969 case GL_RGBA_INTEGER:
970 return 4 * 4;
971 default:
972 FORMAT_ERROR(format, type);
973 }
974 break;
975 case GL_UNSIGNED_INT:
976 switch (format) {
977 case GL_DEPTH_COMPONENT16:
978 case GL_DEPTH_COMPONENT24:
979 case GL_DEPTH_COMPONENT32_OES:
980 case GL_DEPTH_COMPONENT:
981 return 4;
982 case GL_R32UI:
983 case GL_RED_INTEGER:
984 return 4;
985 case GL_RG32UI:
986 case GL_RG_INTEGER:
987 return 4 * 2;
988 case GL_RGB32UI:
989 case GL_RGB_INTEGER:
990 return 4 * 3;
991 case GL_RGBA32UI:
992 case GL_RGBA_INTEGER:
993 return 4 * 4;
994 default:
995 FORMAT_ERROR(format, type);
996 }
997 break;
998 case GL_UNSIGNED_SHORT_4_4_4_4:
999 case GL_UNSIGNED_SHORT_5_5_5_1:
1000 case GL_UNSIGNED_SHORT_5_6_5:
1001 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
1002 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
1003 return 2;
1004 case GL_UNSIGNED_INT_10F_11F_11F_REV:
1005 case GL_UNSIGNED_INT_5_9_9_9_REV:
1006 case GL_UNSIGNED_INT_2_10_10_10_REV:
1007 case GL_UNSIGNED_INT_24_8_OES:
1008 return 4;
1009 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
1010 return 4 + 4;
1011 case GL_FLOAT:
1012 switch (format) {
1013 case GL_DEPTH_COMPONENT32F:
1014 case GL_DEPTH_COMPONENT:
1015 return 4;
1016 case GL_ALPHA32F_EXT:
1017 case GL_ALPHA:
1018 return 4;
1019 case GL_LUMINANCE32F_EXT:
1020 case GL_LUMINANCE:
1021 return 4;
1022 case GL_LUMINANCE_ALPHA32F_EXT:
1023 case GL_LUMINANCE_ALPHA:
1024 return 4 * 2;
1025 case GL_RED:
1026 return 4;
1027 case GL_R32F:
1028 return 4;
1029 case GL_RG:
1030 return 4 * 2;
1031 case GL_RG32F:
1032 return 4 * 2;
1033 case GL_RGB:
1034 return 4 * 3;
1035 case GL_RGB32F:
1036 return 4 * 3;
1037 case GL_RGBA:
1038 return 4 * 4;
1039 case GL_RGBA32F:
1040 return 4 * 4;
1041 default:
1042 FORMAT_ERROR(format, type);
1043 }
1044 break;
1045 case GL_HALF_FLOAT:
1046 case GL_HALF_FLOAT_OES:
1047 switch (format) {
1048 case GL_ALPHA16F_EXT:
1049 case GL_ALPHA:
1050 return 2;
1051 case GL_LUMINANCE16F_EXT:
1052 case GL_LUMINANCE:
1053 return 2;
1054 case GL_LUMINANCE_ALPHA16F_EXT:
1055 case GL_LUMINANCE_ALPHA:
1056 return 2 * 2;
1057 case GL_RED:
1058 return 2;
1059 case GL_R16F:
1060 return 2;
1061 case GL_RG:
1062 return 2 * 2;
1063 case GL_RG16F:
1064 return 2 * 2;
1065 case GL_RGB:
1066 return 2 * 3;
1067 case GL_RGB16F:
1068 return 2 * 3;
1069 case GL_RGBA:
1070 return 2 * 4;
1071 case GL_RGBA16F:
1072 return 2 * 4;
1073 default:
1074 FORMAT_ERROR(format, type);
1075 }
1076 break;
1077 default:
1078 FORMAT_ERROR(format, type);
1079 }
1080
1081 return 0;
1082 }
1083
texImageSize(GLenum internalformat,GLenum type,int unpackAlignment,GLsizei width,GLsizei height)1084 uint32_t texImageSize(GLenum internalformat,
1085 GLenum type,
1086 int unpackAlignment,
1087 GLsizei width,
1088 GLsizei height) {
1089
1090 uint32_t alignedWidth = s_texAlign(width, unpackAlignment);
1091 uint32_t pixelSize = s_computePixelSize(internalformat, type);
1092 uint32_t totalSize = pixelSize * alignedWidth * height;
1093
1094 return totalSize;
1095 }
1096