| #include "IOStream.h" |
| |
| #include "GL2Encoder.h" |
| |
| #include <GLES3/gl31.h> |
| |
| #include <vector> |
| |
| #include <assert.h> |
| |
| void IOStream::readbackPixels(void* context, int width, int height, unsigned int format, unsigned int type, void* pixels) { |
| GL2Encoder *ctx = (GL2Encoder *)context; |
| assert (ctx->state() != NULL); |
| |
| int bpp = 0; |
| int startOffset = 0; |
| int pixelRowSize = 0; |
| int totalRowSize = 0; |
| int skipRows = 0; |
| |
| ctx->state()->getPackingOffsets2D(width, height, format, type, |
| &bpp, |
| &startOffset, |
| &pixelRowSize, |
| &totalRowSize, |
| &skipRows); |
| |
| size_t pixelDataSize = |
| ctx->state()->pixelDataSize( |
| width, height, 1, format, type, 1 /* is pack */); |
| |
| if (startOffset == 0 && |
| pixelRowSize == totalRowSize) { |
| // fast path |
| readback(pixels, pixelDataSize); |
| } else if (pixelRowSize == totalRowSize && (pixelRowSize == width * bpp)) { |
| // fast path but with skip in the beginning |
| std::vector<char> paddingToDiscard(startOffset, 0); |
| readback(&paddingToDiscard[0], startOffset); |
| readback((char*)pixels + startOffset, pixelDataSize - startOffset); |
| } else { |
| |
| if (startOffset > 0) { |
| std::vector<char> paddingToDiscard(startOffset, 0); |
| readback(&paddingToDiscard[0], startOffset); |
| } |
| // need to read back row by row |
| size_t paddingSize = totalRowSize - pixelRowSize; |
| std::vector<char> paddingToDiscard(paddingSize, 0); |
| |
| char* start = (char*)pixels + startOffset; |
| |
| for (int i = 0; i < height; i++) { |
| if (pixelRowSize > width * bpp) { |
| size_t rowSlack = pixelRowSize - width * bpp; |
| std::vector<char> rowSlackToDiscard(rowSlack, 0); |
| readback(start, width * bpp); |
| readback(&rowSlackToDiscard[0], rowSlack); |
| readback(&paddingToDiscard[0], paddingSize); |
| start += totalRowSize; |
| } else { |
| readback(start, pixelRowSize); |
| readback(&paddingToDiscard[0], paddingSize); |
| start += totalRowSize; |
| } |
| } |
| } |
| } |
| |
| void IOStream::uploadPixels(void* context, int width, int height, int depth, unsigned int format, unsigned int type, const void* pixels) { |
| GL2Encoder *ctx = (GL2Encoder *)context; |
| assert (ctx->state() != NULL); |
| |
| if (1 == depth) { |
| int bpp = 0; |
| int startOffset = 0; |
| int pixelRowSize = 0; |
| int totalRowSize = 0; |
| int skipRows = 0; |
| |
| ctx->state()->getUnpackingOffsets2D(width, height, format, type, |
| &bpp, |
| &startOffset, |
| &pixelRowSize, |
| &totalRowSize, |
| &skipRows); |
| |
| size_t pixelDataSize = |
| ctx->state()->pixelDataSize( |
| width, height, 1, format, type, 0 /* is unpack */); |
| |
| if (startOffset == 0 && |
| pixelRowSize == totalRowSize) { |
| // fast path |
| writeFully(pixels, pixelDataSize); |
| } else if (pixelRowSize == totalRowSize && (pixelRowSize == width * bpp)) { |
| // fast path but with skip in the beginning |
| std::vector<char> paddingToDiscard(startOffset, 0); |
| writeFully(&paddingToDiscard[0], startOffset); |
| writeFully((char*)pixels + startOffset, pixelDataSize - startOffset); |
| } else { |
| |
| if (startOffset > 0) { |
| std::vector<char> paddingToDiscard(startOffset, 0); |
| writeFully(&paddingToDiscard[0], startOffset); |
| } |
| // need to upload row by row |
| size_t paddingSize = totalRowSize - pixelRowSize; |
| std::vector<char> paddingToDiscard(paddingSize, 0); |
| |
| char* start = (char*)pixels + startOffset; |
| |
| for (int i = 0; i < height; i++) { |
| if (pixelRowSize > width * bpp) { |
| size_t rowSlack = pixelRowSize - width * bpp; |
| std::vector<char> rowSlackToDiscard(rowSlack, 0); |
| writeFully(start, width * bpp); |
| writeFully(&rowSlackToDiscard[0], rowSlack); |
| writeFully(&paddingToDiscard[0], paddingSize); |
| start += totalRowSize; |
| } else { |
| writeFully(start, pixelRowSize); |
| writeFully(&paddingToDiscard[0], paddingSize); |
| start += totalRowSize; |
| } |
| } |
| } |
| } else { |
| int bpp = 0; |
| int startOffset = 0; |
| int pixelRowSize = 0; |
| int totalRowSize = 0; |
| int pixelImageSize = 0; |
| int totalImageSize = 0; |
| int skipRows = 0; |
| int skipImages = 0; |
| |
| ctx->state()->getUnpackingOffsets3D(width, height, depth, format, type, |
| &bpp, |
| &startOffset, |
| &pixelRowSize, |
| &totalRowSize, |
| &pixelImageSize, |
| &totalImageSize, |
| &skipRows, |
| &skipImages); |
| |
| size_t pixelDataSize = |
| ctx->state()->pixelDataSize( |
| width, height, depth, format, type, 0 /* is unpack */); |
| |
| |
| if (startOffset == 0 && |
| pixelRowSize == totalRowSize && |
| pixelImageSize == totalImageSize) { |
| // fast path |
| writeFully(pixels, pixelDataSize); |
| } else if (pixelRowSize == totalRowSize && |
| pixelImageSize == totalImageSize && |
| pixelRowSize == (width * bpp)) { |
| // fast path but with skip in the beginning |
| std::vector<char> paddingToDiscard(startOffset, 0); |
| writeFully(&paddingToDiscard[0], startOffset); |
| writeFully((char*)pixels + startOffset, pixelDataSize - startOffset); |
| } else { |
| |
| if (startOffset > 0) { |
| std::vector<char> paddingToDiscard(startOffset, 0); |
| writeFully(&paddingToDiscard[0], startOffset); |
| } |
| // need to upload row by row |
| size_t paddingSize = totalRowSize - pixelRowSize; |
| std::vector<char> paddingToDiscard(paddingSize, 0); |
| |
| char* start = (char*)pixels + startOffset; |
| |
| size_t imageSlack = totalImageSize - pixelImageSize; |
| std::vector<char> imageSlackToDiscard(imageSlack, 0); |
| |
| for (int k = 0; k < depth; ++k) { |
| for (int i = 0; i < height; i++) { |
| if (pixelRowSize > width * bpp) { |
| size_t rowSlack = pixelRowSize - width * bpp; |
| std::vector<char> rowSlackToDiscard(rowSlack, 0); |
| writeFully(start, width * bpp); |
| writeFully(&rowSlackToDiscard[0], rowSlack); |
| writeFully(&paddingToDiscard[0], paddingSize); |
| start += totalRowSize; |
| } else { |
| writeFully(start, pixelRowSize); |
| writeFully(&paddingToDiscard[0], paddingSize); |
| start += totalRowSize; |
| } |
| } |
| if (imageSlack > 0) { |
| writeFully(&imageSlackToDiscard[0], imageSlack); |
| start += imageSlack; |
| } |
| } |
| } |
| } |
| } |