1 #include "IOStream.h"
2 
3 #include "GL2Encoder.h"
4 
5 #include <GLES3/gl31.h>
6 
7 #include <vector>
8 
9 #include <assert.h>
10 
readbackPixels(void * context,int width,int height,unsigned int format,unsigned int type,void * pixels)11 void IOStream::readbackPixels(void* context, int width, int height, unsigned int format, unsigned int type, void* pixels) {
12     GL2Encoder *ctx = (GL2Encoder *)context;
13     assert (ctx->state() != NULL);
14 
15     int bpp = 0;
16     int startOffset = 0;
17     int pixelRowSize = 0;
18     int totalRowSize = 0;
19     int skipRows = 0;
20 
21     ctx->state()->getPackingOffsets2D(width, height, format, type,
22                                       &bpp,
23                                       &startOffset,
24                                       &pixelRowSize,
25                                       &totalRowSize,
26                                       &skipRows);
27 
28     size_t pixelDataSize =
29         ctx->state()->pixelDataSize(
30             width, height, 1, format, type, 1 /* is pack */);
31 
32     if (startOffset == 0 &&
33         pixelRowSize == totalRowSize) {
34         // fast path
35         readback(pixels, pixelDataSize);
36     } else if (pixelRowSize == totalRowSize && (pixelRowSize == width * bpp)) {
37         // fast path but with skip in the beginning
38         std::vector<char> paddingToDiscard(startOffset, 0);
39         readback(&paddingToDiscard[0], startOffset);
40         readback((char*)pixels + startOffset, pixelDataSize - startOffset);
41     } else {
42         int totalReadback = 0;
43 
44         if (startOffset > 0) {
45             std::vector<char> paddingToDiscard(startOffset, 0);
46             readback(&paddingToDiscard[0], startOffset);
47             totalReadback += startOffset;
48         }
49         // need to read back row by row
50         size_t paddingSize = totalRowSize - pixelRowSize;
51         std::vector<char> paddingToDiscard(paddingSize, 0);
52 
53         char* start = (char*)pixels + startOffset;
54 
55         for (int i = 0; i < height; i++) {
56             if (pixelRowSize != width * bpp) {
57                 size_t rowSlack = pixelRowSize - width * bpp;
58                 std::vector<char> rowSlackToDiscard(rowSlack, 0);
59                 readback(start, width * bpp);
60                 readback(&rowSlackToDiscard[0], rowSlack);
61                 totalReadback += pixelRowSize;
62                 readback(&paddingToDiscard[0], paddingSize);
63                 totalReadback += paddingSize;
64                 start += totalRowSize;
65             } else {
66                 readback(start, pixelRowSize);
67                 totalReadback += pixelRowSize;
68                 readback(&paddingToDiscard[0], paddingSize);
69                 totalReadback += paddingSize;
70                 start += totalRowSize;
71             }
72         }
73     }
74 }
75 
uploadPixels(void * context,int width,int height,int depth,unsigned int format,unsigned int type,const void * pixels)76 void IOStream::uploadPixels(void* context, int width, int height, int depth, unsigned int format, unsigned int type, const void* pixels) {
77     GL2Encoder *ctx = (GL2Encoder *)context;
78     assert (ctx->state() != NULL);
79 
80     if (1 == depth) {
81         int bpp = 0;
82         int startOffset = 0;
83         int pixelRowSize = 0;
84         int totalRowSize = 0;
85         int skipRows = 0;
86 
87         ctx->state()->getUnpackingOffsets2D(width, height, format, type,
88                 &bpp,
89                 &startOffset,
90                 &pixelRowSize,
91                 &totalRowSize,
92                 &skipRows);
93 
94         size_t pixelDataSize =
95             ctx->state()->pixelDataSize(
96                     width, height, 1, format, type, 0 /* is unpack */);
97 
98         if (startOffset == 0 &&
99                 pixelRowSize == totalRowSize) {
100             // fast path
101             writeFully(pixels, pixelDataSize);
102         } else if (pixelRowSize == totalRowSize && (pixelRowSize == width * bpp)) {
103             // fast path but with skip in the beginning
104             std::vector<char> paddingToDiscard(startOffset, 0);
105             writeFully(&paddingToDiscard[0], startOffset);
106             writeFully((char*)pixels + startOffset, pixelDataSize - startOffset);
107         } else {
108             int totalReadback = 0;
109 
110             if (startOffset > 0) {
111                 std::vector<char> paddingToDiscard(startOffset, 0);
112                 writeFully(&paddingToDiscard[0], startOffset);
113                 totalReadback += startOffset;
114             }
115             // need to upload row by row
116             size_t paddingSize = totalRowSize - pixelRowSize;
117             std::vector<char> paddingToDiscard(paddingSize, 0);
118 
119             char* start = (char*)pixels + startOffset;
120 
121             for (int i = 0; i < height; i++) {
122                 if (pixelRowSize != width * bpp) {
123                     size_t rowSlack = pixelRowSize - width * bpp;
124                     std::vector<char> rowSlackToDiscard(rowSlack, 0);
125                     writeFully(start, width * bpp);
126                     writeFully(&rowSlackToDiscard[0], rowSlack);
127                     totalReadback += pixelRowSize;
128                     writeFully(&paddingToDiscard[0], paddingSize);
129                     totalReadback += paddingSize;
130                     start += totalRowSize;
131                 } else {
132                     writeFully(start, pixelRowSize);
133                     totalReadback += pixelRowSize;
134                     writeFully(&paddingToDiscard[0], paddingSize);
135                     totalReadback += paddingSize;
136                     start += totalRowSize;
137                 }
138             }
139         }
140     } else {
141         int bpp = 0;
142         int startOffset = 0;
143         int pixelRowSize = 0;
144         int totalRowSize = 0;
145         int pixelImageSize = 0;
146         int totalImageSize = 0;
147         int skipRows = 0;
148         int skipImages = 0;
149 
150         ctx->state()->getUnpackingOffsets3D(width, height, depth, format, type,
151                 &bpp,
152                 &startOffset,
153                 &pixelRowSize,
154                 &totalRowSize,
155                 &pixelImageSize,
156                 &totalImageSize,
157                 &skipRows,
158                 &skipImages);
159 
160         size_t pixelDataSize =
161             ctx->state()->pixelDataSize(
162                     width, height, depth, format, type, 0 /* is unpack */);
163 
164         size_t sent = 0;
165 
166         if (startOffset == 0 &&
167             pixelRowSize == totalRowSize &&
168             pixelImageSize == totalImageSize) {
169             // fast path
170             writeFully(pixels, pixelDataSize);
171             sent += pixelDataSize;
172         } else if (pixelRowSize == totalRowSize &&
173                    pixelImageSize == totalImageSize &&
174                    pixelRowSize == (width * bpp)) {
175             // fast path but with skip in the beginning
176             std::vector<char> paddingToDiscard(startOffset, 0);
177             writeFully(&paddingToDiscard[0], startOffset);
178             writeFully((char*)pixels + startOffset, pixelDataSize - startOffset);
179             sent += pixelDataSize;
180         } else {
181             int totalReadback = 0;
182 
183             if (startOffset > 0) {
184                 std::vector<char> paddingToDiscard(startOffset, 0);
185                 writeFully(&paddingToDiscard[0], startOffset);
186                 totalReadback += startOffset;
187             }
188             // need to upload row by row
189             size_t paddingSize = totalRowSize - pixelRowSize;
190             std::vector<char> paddingToDiscard(paddingSize, 0);
191 
192             char* start = (char*)pixels + startOffset;
193 
194             size_t rowSlack = pixelRowSize - width * bpp;
195             std::vector<char> rowSlackToDiscard(rowSlack, 0);
196 
197             size_t imageSlack = totalImageSize - pixelImageSize;
198             std::vector<char> imageSlackToDiscard(imageSlack, 0);
199 
200             for (int k = 0; k < depth; ++k) {
201                 for (int i = 0; i < height; i++) {
202                     if (pixelRowSize != width * bpp) {
203                         writeFully(start, width * bpp);
204                         writeFully(&rowSlackToDiscard[0], rowSlack);
205                         totalReadback += pixelRowSize;
206                         writeFully(&paddingToDiscard[0], paddingSize);
207                         totalReadback += paddingSize;
208                         start += totalRowSize;
209                     } else {
210                         writeFully(start, pixelRowSize);
211                         totalReadback += pixelRowSize;
212                         writeFully(&paddingToDiscard[0], paddingSize);
213                         totalReadback += paddingSize;
214                         start += totalRowSize;
215                     }
216                 }
217                 if (imageSlack > 0) {
218                     writeFully(&imageSlackToDiscard[0], imageSlack);
219                     start += imageSlack;
220                     totalReadback += imageSlack;
221                 }
222             }
223         }
224     }
225 }
226