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