1 #include "GLESTextureUtils.h"
2
3 #include "glUtils.h"
4
5 #if PLATFORM_SDK_VERSION < 26
6 #include <cutils/log.h>
7 #else
8 #include <log/log.h>
9 #endif
10
11 namespace GLESTextureUtils {
12
13 // Based on computations in
14 // https://swiftshader.googlesource.com/SwiftShader/+/master/src/OpenGL/common/Image.cpp
15 // such as Image::loadImageData,
16 // ComputePitch/ComputePackingOffset
17
18 #define HIGHEST_MULTIPLE_OF(align, x) \
19 (( ( x ) + ( align ) - 1) & ~( ( align ) - 1)) \
20
computePixelSize(GLenum format,GLenum type)21 static int computePixelSize(GLenum format, GLenum type) {
22
23 #define FORMAT_ERROR(format, type) \
24 ALOGE("%s:%d unknown format/type 0x%x 0x%x", __FUNCTION__, __LINE__, format, type) \
25
26 switch(type) {
27 case GL_BYTE:
28 switch(format) {
29 case GL_R8:
30 case GL_R8I:
31 case GL_R8_SNORM:
32 case GL_RED: return sizeof(char);
33 case GL_RED_INTEGER: return sizeof(char);
34 case GL_RG8:
35 case GL_RG8I:
36 case GL_RG8_SNORM:
37 case GL_RG: return sizeof(char) * 2;
38 case GL_RG_INTEGER: return sizeof(char) * 2;
39 case GL_RGB8:
40 case GL_RGB8I:
41 case GL_RGB8_SNORM:
42 case GL_RGB: return sizeof(char) * 3;
43 case GL_RGB_INTEGER: return sizeof(char) * 3;
44 case GL_RGBA8:
45 case GL_RGBA8I:
46 case GL_RGBA8_SNORM:
47 case GL_RGBA: return sizeof(char) * 4;
48 case GL_RGBA_INTEGER: return sizeof(char) * 4;
49 default: FORMAT_ERROR(format, type);
50 }
51 break;
52 case GL_UNSIGNED_BYTE:
53 switch(format) {
54 case GL_R8:
55 case GL_R8UI:
56 case GL_RED: return sizeof(unsigned char);
57 case GL_RED_INTEGER: return sizeof(unsigned char);
58 case GL_ALPHA8_EXT:
59 case GL_ALPHA: return sizeof(unsigned char);
60 case GL_LUMINANCE8_EXT:
61 case GL_LUMINANCE: return sizeof(unsigned char);
62 case GL_LUMINANCE8_ALPHA8_EXT:
63 case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2;
64 case GL_RG8:
65 case GL_RG8UI:
66 case GL_RG: return sizeof(unsigned char) * 2;
67 case GL_RG_INTEGER: return sizeof(unsigned char) * 2;
68 case GL_RGB8:
69 case GL_RGB8UI:
70 case GL_SRGB8:
71 case GL_RGB: return sizeof(unsigned char) * 3;
72 case GL_RGB_INTEGER: return sizeof(unsigned char) * 3;
73 case GL_RGBA8:
74 case GL_RGBA8UI:
75 case GL_SRGB8_ALPHA8:
76 case GL_RGBA: return sizeof(unsigned char) * 4;
77 case GL_RGBA_INTEGER: return sizeof(unsigned char) * 4;
78 case GL_BGRA_EXT:
79 case GL_BGRA8_EXT: return sizeof(unsigned char)* 4;
80 default: FORMAT_ERROR(format, type);
81 }
82 break;
83 case GL_SHORT:
84 switch(format) {
85 case GL_R16I:
86 case GL_RED_INTEGER: return sizeof(short);
87 case GL_RG16I:
88 case GL_RG_INTEGER: return sizeof(short) * 2;
89 case GL_RGB16I:
90 case GL_RGB_INTEGER: return sizeof(short) * 3;
91 case GL_RGBA16I:
92 case GL_RGBA_INTEGER: return sizeof(short) * 4;
93 default: FORMAT_ERROR(format, type);
94 }
95 break;
96 case GL_UNSIGNED_SHORT:
97 switch(format) {
98 case GL_DEPTH_COMPONENT16:
99 case GL_DEPTH_COMPONENT: return sizeof(unsigned short);
100 case GL_R16UI:
101 case GL_RED_INTEGER: return sizeof(unsigned short);
102 case GL_RG16UI:
103 case GL_RG_INTEGER: return sizeof(unsigned short) * 2;
104 case GL_RGB16UI:
105 case GL_RGB_INTEGER: return sizeof(unsigned short) * 3;
106 case GL_RGBA16UI:
107 case GL_RGBA_INTEGER: return sizeof(unsigned short) * 4;
108 default: FORMAT_ERROR(format, type);
109 }
110 break;
111 case GL_INT:
112 switch(format) {
113 case GL_R32I:
114 case GL_RED_INTEGER: return sizeof(int);
115 case GL_RG32I:
116 case GL_RG_INTEGER: return sizeof(int) * 2;
117 case GL_RGB32I:
118 case GL_RGB_INTEGER: return sizeof(int) * 3;
119 case GL_RGBA32I:
120 case GL_RGBA_INTEGER: return sizeof(int) * 4;
121 default: FORMAT_ERROR(format, type);
122 }
123 break;
124 case GL_UNSIGNED_INT:
125 switch(format) {
126 case GL_DEPTH_COMPONENT16:
127 case GL_DEPTH_COMPONENT24:
128 case GL_DEPTH_COMPONENT32_OES:
129 case GL_DEPTH_COMPONENT: return sizeof(unsigned int);
130 case GL_R32UI:
131 case GL_RED_INTEGER: return sizeof(unsigned int);
132 case GL_RG32UI:
133 case GL_RG_INTEGER: return sizeof(unsigned int) * 2;
134 case GL_RGB32UI:
135 case GL_RGB_INTEGER: return sizeof(unsigned int) * 3;
136 case GL_RGBA32UI:
137 case GL_RGBA_INTEGER: return sizeof(unsigned int) * 4;
138 default: FORMAT_ERROR(format, type);
139 }
140 break;
141 case GL_UNSIGNED_SHORT_4_4_4_4:
142 case GL_UNSIGNED_SHORT_5_5_5_1:
143 case GL_UNSIGNED_SHORT_5_6_5:
144 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
145 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
146 return sizeof(unsigned short);
147 case GL_UNSIGNED_INT_10F_11F_11F_REV:
148 case GL_UNSIGNED_INT_5_9_9_9_REV:
149 case GL_UNSIGNED_INT_2_10_10_10_REV:
150 case GL_UNSIGNED_INT_24_8_OES:
151 return sizeof(unsigned int);
152 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
153 return sizeof(float) + sizeof(unsigned int);
154 case GL_FLOAT:
155 switch(format) {
156 case GL_DEPTH_COMPONENT32F:
157 case GL_DEPTH_COMPONENT: return sizeof(float);
158 case GL_ALPHA32F_EXT:
159 case GL_ALPHA: return sizeof(float);
160 case GL_LUMINANCE32F_EXT:
161 case GL_LUMINANCE: return sizeof(float);
162 case GL_LUMINANCE_ALPHA32F_EXT:
163 case GL_LUMINANCE_ALPHA: return sizeof(float) * 2;
164 case GL_RED: return sizeof(float);
165 case GL_R32F: return sizeof(float);
166 case GL_RG: return sizeof(float) * 2;
167 case GL_RG32F: return sizeof(float) * 2;
168 case GL_RGB: return sizeof(float) * 3;
169 case GL_RGB32F: return sizeof(float) * 3;
170 case GL_RGBA: return sizeof(float) * 4;
171 case GL_RGBA32F: return sizeof(float) * 4;
172 default: FORMAT_ERROR(format, type);
173 }
174 break;
175 case GL_HALF_FLOAT:
176 case GL_HALF_FLOAT_OES:
177 switch(format) {
178 case GL_ALPHA16F_EXT:
179 case GL_ALPHA: return sizeof(unsigned short);
180 case GL_LUMINANCE16F_EXT:
181 case GL_LUMINANCE: return sizeof(unsigned short);
182 case GL_LUMINANCE_ALPHA16F_EXT:
183 case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2;
184 case GL_RED: return sizeof(unsigned short);
185 case GL_R16F: return sizeof(unsigned short);
186 case GL_RG: return sizeof(unsigned short) * 2;
187 case GL_RG16F: return sizeof(unsigned short) * 2;
188 case GL_RGB: return sizeof(unsigned short) * 3;
189 case GL_RGB16F: return sizeof(unsigned short) * 3;
190 case GL_RGBA: return sizeof(unsigned short) * 4;
191 case GL_RGBA16F: return sizeof(unsigned short) * 4;
192 default: FORMAT_ERROR(format, type);
193 }
194 break;
195 default: FORMAT_ERROR(format, type);
196 }
197
198 return 0;
199 }
200
computePitch(GLsizei inputWidth,GLenum format,GLenum type,int align)201 static int computePitch(GLsizei inputWidth, GLenum format, GLenum type, int align) {
202 GLsizei unaligned_width = computePixelSize(format, type) * inputWidth;
203 return HIGHEST_MULTIPLE_OF(align, unaligned_width);
204 }
205
computePackingOffset(GLenum format,GLenum type,GLsizei width,GLsizei height,int align,int skipPixels,int skipRows,int skipImages)206 static int computePackingOffset(GLenum format, GLenum type, GLsizei width, GLsizei height, int align, int skipPixels, int skipRows, int skipImages) {
207 GLsizei alignedPitch = computePitch(width, format, type, align);
208 int packingOffsetRows =
209 (skipImages * height + skipRows);
210 int res = packingOffsetRows * alignedPitch + skipPixels * computePixelSize(format, type);
211
212 return res;
213 }
214
computeTextureStartEnd(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int unpackAlignment,int unpackRowLength,int unpackImageHeight,int unpackSkipPixels,int unpackSkipRows,int unpackSkipImages,int * start,int * end)215 void computeTextureStartEnd(
216 GLsizei width, GLsizei height, GLsizei depth,
217 GLenum format, GLenum type,
218 int unpackAlignment,
219 int unpackRowLength,
220 int unpackImageHeight,
221 int unpackSkipPixels,
222 int unpackSkipRows,
223 int unpackSkipImages,
224 int* start,
225 int* end) {
226
227 GLsizei inputWidth = (unpackRowLength == 0) ? width : unpackRowLength;
228 GLsizei inputPitch = computePitch(inputWidth, format, type, unpackAlignment);
229 GLsizei inputHeight = (unpackImageHeight == 0) ? height : unpackImageHeight;
230
231 ALOGV("%s: input idim %d %d %d w p h %d %d %d:", __FUNCTION__, width, height, depth, inputWidth, inputPitch, inputHeight);
232
233 int startVal = computePackingOffset(format, type, inputWidth, inputHeight, unpackAlignment, unpackSkipPixels, unpackSkipRows, unpackSkipImages);
234 int endVal = startVal + inputPitch * inputHeight * depth;
235
236 if (start) *start = startVal;
237 if (end) *end = endVal;
238
239 ALOGV("%s: start/end: %d %d", __FUNCTION__, *start, *end);
240
241 }
242
computeTotalImageSize(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int unpackAlignment,int unpackRowLength,int unpackImageHeight,int unpackSkipPixels,int unpackSkipRows,int unpackSkipImages)243 int computeTotalImageSize(
244 GLsizei width, GLsizei height, GLsizei depth,
245 GLenum format, GLenum type,
246 int unpackAlignment,
247 int unpackRowLength,
248 int unpackImageHeight,
249 int unpackSkipPixels,
250 int unpackSkipRows,
251 int unpackSkipImages) {
252
253 int start, end;
254 computeTextureStartEnd(
255 width, height, depth,
256 format, type,
257 unpackAlignment,
258 unpackRowLength,
259 unpackImageHeight,
260 unpackSkipPixels,
261 unpackSkipRows,
262 unpackSkipImages,
263 &start,
264 &end);
265 return end;
266 }
267
computeNeededBufferSize(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int unpackAlignment,int unpackRowLength,int unpackImageHeight,int unpackSkipPixels,int unpackSkipRows,int unpackSkipImages)268 int computeNeededBufferSize(
269 GLsizei width, GLsizei height, GLsizei depth,
270 GLenum format, GLenum type,
271 int unpackAlignment,
272 int unpackRowLength,
273 int unpackImageHeight,
274 int unpackSkipPixels,
275 int unpackSkipRows,
276 int unpackSkipImages) {
277
278 int start, end;
279 computeTextureStartEnd(
280 width, height, depth,
281 format, type,
282 unpackAlignment,
283 unpackRowLength,
284 unpackImageHeight,
285 unpackSkipPixels,
286 unpackSkipRows,
287 unpackSkipImages,
288 &start,
289 &end);
290 return end - start;
291 }
292
computePackingOffsets2D(GLsizei width,GLsizei height,GLenum format,GLenum type,int packAlignment,int packRowLength,int packSkipPixels,int packSkipRows,int * bpp,int * startOffset,int * packingPixelRowSize,int * packingTotalRowSize)293 void computePackingOffsets2D(
294 GLsizei width, GLsizei height,
295 GLenum format, GLenum type,
296 int packAlignment,
297 int packRowLength,
298 int packSkipPixels,
299 int packSkipRows,
300 int* bpp,
301 int* startOffset,
302 int* packingPixelRowSize,
303 int* packingTotalRowSize) {
304
305 int widthTotal = (packRowLength == 0) ? width : packRowLength;
306 int totalRowSize = computePitch(widthTotal, format, type, packAlignment);
307 int pixelsOnlyRowSize = computePitch(width, format, type, packAlignment);
308
309 int packingOffsetStart =
310 computePackingOffset(
311 format, type, widthTotal, height, packAlignment, packSkipPixels, packSkipRows, 0 /* skip images = 0 */);
312
313 if (bpp) *bpp = computePixelSize(format, type);
314 if (startOffset) *startOffset = packingOffsetStart;
315 if (packingPixelRowSize) *packingPixelRowSize = pixelsOnlyRowSize;
316 if (packingTotalRowSize) *packingTotalRowSize = totalRowSize;
317 }
318
computePackingOffsets3D(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int packAlignment,int packRowLength,int packImageHeight,int packSkipPixels,int packSkipRows,int packSkipImages,int * bpp,int * startOffset,int * packingPixelRowSize,int * packingTotalRowSize,int * packingPixelImageSize,int * packingTotalImageSize)319 void computePackingOffsets3D(
320 GLsizei width, GLsizei height, GLsizei depth,
321 GLenum format, GLenum type,
322 int packAlignment,
323 int packRowLength,
324 int packImageHeight,
325 int packSkipPixels,
326 int packSkipRows,
327 int packSkipImages,
328 int* bpp,
329 int* startOffset,
330 int* packingPixelRowSize,
331 int* packingTotalRowSize,
332 int* packingPixelImageSize,
333 int* packingTotalImageSize) {
334
335 int widthTotal = (packRowLength == 0) ? width : packRowLength;
336 int totalRowSize = computePitch(widthTotal, format, type, packAlignment);
337 int pixelsOnlyRowSize = computePitch(width, format, type, packAlignment);
338
339 int heightTotal = packImageHeight == 0 ? height : packImageHeight;
340 int totalImageSize = totalRowSize * heightTotal;
341 int pixelsOnlyImageSize = totalRowSize * height;
342
343 int packingOffsetStart =
344 computePackingOffset(
345 format, type, widthTotal, heightTotal, packAlignment, packSkipPixels, packSkipRows, packSkipImages);
346
347 if (bpp) *bpp = computePixelSize(format, type);
348 if (startOffset) *startOffset = packingOffsetStart;
349 if (packingPixelRowSize) *packingPixelRowSize = pixelsOnlyRowSize;
350 if (packingTotalRowSize) *packingTotalRowSize = totalRowSize;
351 if (packingPixelImageSize) *packingPixelImageSize = pixelsOnlyImageSize;
352 if (packingTotalImageSize) *packingTotalImageSize = totalImageSize;
353 }
354
355 } // namespace GLESTextureUtils
356