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