#include "GLESTextureUtils.h" #include "glUtils.h" #include <cutils/log.h> namespace GLESTextureUtils { // Based on computations in // https://swiftshader.googlesource.com/SwiftShader/+/master/src/OpenGL/common/Image.cpp // such as Image::loadImageData, // ComputePitch/ComputePackingOffset #define HIGHEST_MULTIPLE_OF(align, x) \ (( ( x ) + ( align ) - 1) & ~( ( align ) - 1)) \ static int computePixelSize(GLenum format, GLenum type) { #define FORMAT_ERROR(format, type) \ ALOGE("%s:%d unknown format/type 0x%x 0x%x", __FUNCTION__, __LINE__, format, type) \ switch(type) { case GL_BYTE: switch(format) { case GL_R8: case GL_R8I: case GL_R8_SNORM: case GL_RED: return sizeof(char); case GL_RED_INTEGER: return sizeof(char); case GL_RG8: case GL_RG8I: case GL_RG8_SNORM: case GL_RG: return sizeof(char) * 2; case GL_RG_INTEGER: return sizeof(char) * 2; case GL_RGB8: case GL_RGB8I: case GL_RGB8_SNORM: case GL_RGB: return sizeof(char) * 3; case GL_RGB_INTEGER: return sizeof(char) * 3; case GL_RGBA8: case GL_RGBA8I: case GL_RGBA8_SNORM: case GL_RGBA: return sizeof(char) * 4; case GL_RGBA_INTEGER: return sizeof(char) * 4; default: FORMAT_ERROR(format, type); } break; case GL_UNSIGNED_BYTE: switch(format) { case GL_R8: case GL_R8UI: case GL_RED: return sizeof(unsigned char); case GL_RED_INTEGER: return sizeof(unsigned char); case GL_ALPHA8_EXT: case GL_ALPHA: return sizeof(unsigned char); case GL_LUMINANCE8_EXT: case GL_LUMINANCE: return sizeof(unsigned char); case GL_LUMINANCE8_ALPHA8_EXT: case GL_LUMINANCE_ALPHA: return sizeof(unsigned char) * 2; case GL_RG8: case GL_RG8UI: case GL_RG: return sizeof(unsigned char) * 2; case GL_RG_INTEGER: return sizeof(unsigned char) * 2; case GL_RGB8: case GL_RGB8UI: case GL_SRGB8: case GL_RGB: return sizeof(unsigned char) * 3; case GL_RGB_INTEGER: return sizeof(unsigned char) * 3; case GL_RGBA8: case GL_RGBA8UI: case GL_SRGB8_ALPHA8: case GL_RGBA: return sizeof(unsigned char) * 4; case GL_RGBA_INTEGER: return sizeof(unsigned char) * 4; case GL_BGRA_EXT: case GL_BGRA8_EXT: return sizeof(unsigned char)* 4; default: FORMAT_ERROR(format, type); } break; case GL_SHORT: switch(format) { case GL_R16I: case GL_RED_INTEGER: return sizeof(short); case GL_RG16I: case GL_RG_INTEGER: return sizeof(short) * 2; case GL_RGB16I: case GL_RGB_INTEGER: return sizeof(short) * 3; case GL_RGBA16I: case GL_RGBA_INTEGER: return sizeof(short) * 4; default: FORMAT_ERROR(format, type); } break; case GL_UNSIGNED_SHORT: switch(format) { case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT: return sizeof(unsigned short); case GL_R16UI: case GL_RED_INTEGER: return sizeof(unsigned short); case GL_RG16UI: case GL_RG_INTEGER: return sizeof(unsigned short) * 2; case GL_RGB16UI: case GL_RGB_INTEGER: return sizeof(unsigned short) * 3; case GL_RGBA16UI: case GL_RGBA_INTEGER: return sizeof(unsigned short) * 4; default: FORMAT_ERROR(format, type); } break; case GL_INT: switch(format) { case GL_R32I: case GL_RED_INTEGER: return sizeof(int); case GL_RG32I: case GL_RG_INTEGER: return sizeof(int) * 2; case GL_RGB32I: case GL_RGB_INTEGER: return sizeof(int) * 3; case GL_RGBA32I: case GL_RGBA_INTEGER: return sizeof(int) * 4; default: FORMAT_ERROR(format, type); } break; case GL_UNSIGNED_INT: switch(format) { case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32_OES: case GL_DEPTH_COMPONENT: return sizeof(unsigned int); case GL_R32UI: case GL_RED_INTEGER: return sizeof(unsigned int); case GL_RG32UI: case GL_RG_INTEGER: return sizeof(unsigned int) * 2; case GL_RGB32UI: case GL_RGB_INTEGER: return sizeof(unsigned int) * 3; case GL_RGBA32UI: case GL_RGBA_INTEGER: return sizeof(unsigned int) * 4; default: FORMAT_ERROR(format, type); } break; case GL_UNSIGNED_SHORT_4_4_4_4: case GL_UNSIGNED_SHORT_5_5_5_1: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: return sizeof(unsigned short); case GL_UNSIGNED_INT_10F_11F_11F_REV: case GL_UNSIGNED_INT_5_9_9_9_REV: case GL_UNSIGNED_INT_2_10_10_10_REV: case GL_UNSIGNED_INT_24_8_OES: return sizeof(unsigned int); case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: return sizeof(float) + sizeof(unsigned int); case GL_FLOAT: switch(format) { case GL_DEPTH_COMPONENT32F: case GL_DEPTH_COMPONENT: return sizeof(float); case GL_ALPHA32F_EXT: case GL_ALPHA: return sizeof(float); case GL_LUMINANCE32F_EXT: case GL_LUMINANCE: return sizeof(float); case GL_LUMINANCE_ALPHA32F_EXT: case GL_LUMINANCE_ALPHA: return sizeof(float) * 2; case GL_RED: return sizeof(float); case GL_R32F: return sizeof(float); case GL_RG: return sizeof(float) * 2; case GL_RG32F: return sizeof(float) * 2; case GL_RGB: return sizeof(float) * 3; case GL_RGB32F: return sizeof(float) * 3; case GL_RGBA: return sizeof(float) * 4; case GL_RGBA32F: return sizeof(float) * 4; default: FORMAT_ERROR(format, type); } break; case GL_HALF_FLOAT: case GL_HALF_FLOAT_OES: switch(format) { case GL_ALPHA16F_EXT: case GL_ALPHA: return sizeof(unsigned short); case GL_LUMINANCE16F_EXT: case GL_LUMINANCE: return sizeof(unsigned short); case GL_LUMINANCE_ALPHA16F_EXT: case GL_LUMINANCE_ALPHA: return sizeof(unsigned short) * 2; case GL_RED: return sizeof(unsigned short); case GL_R16F: return sizeof(unsigned short); case GL_RG: return sizeof(unsigned short) * 2; case GL_RG16F: return sizeof(unsigned short) * 2; case GL_RGB: return sizeof(unsigned short) * 3; case GL_RGB16F: return sizeof(unsigned short) * 3; case GL_RGBA: return sizeof(unsigned short) * 4; case GL_RGBA16F: return sizeof(unsigned short) * 4; default: FORMAT_ERROR(format, type); } break; default: FORMAT_ERROR(format, type); } return 0; } static int computePitch(GLsizei inputWidth, GLenum format, GLenum type, int align) { GLsizei unaligned_width = computePixelSize(format, type) * inputWidth; return HIGHEST_MULTIPLE_OF(align, unaligned_width); } static int computePackingOffset(GLenum format, GLenum type, GLsizei width, GLsizei height, int align, int skipPixels, int skipRows, int skipImages) { GLsizei alignedPitch = computePitch(width, format, type, align); int packingOffsetRows = (skipImages * height + skipRows); return packingOffsetRows * alignedPitch + skipPixels * computePixelSize(format, type); } void 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) { GLsizei inputWidth = (unpackRowLength == 0) ? width : unpackRowLength; GLsizei inputPitch = computePitch(inputWidth, format, type, unpackAlignment); GLsizei inputHeight = (unpackImageHeight == 0) ? height : unpackImageHeight; ALOGV("%s: input idim %d %d %d w p h %d %d %d:", __FUNCTION__, width, height, depth, inputWidth, inputPitch, inputHeight); int startVal = computePackingOffset(format, type, inputWidth, inputHeight, unpackAlignment, unpackSkipPixels, unpackSkipRows, unpackSkipImages); int endVal = startVal + inputPitch * inputHeight * depth; if (start) *start = startVal; if (end) *end = endVal; ALOGV("%s: start/end: %d %d", __FUNCTION__, *start, *end); } int computeTotalImageSize( GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int unpackAlignment, int unpackRowLength, int unpackImageHeight, int unpackSkipPixels, int unpackSkipRows, int unpackSkipImages) { int start, end; computeTextureStartEnd( width, height, depth, format, type, unpackAlignment, unpackRowLength, unpackImageHeight, unpackSkipPixels, unpackSkipRows, unpackSkipImages, &start, &end); return end; } int computeNeededBufferSize( GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int unpackAlignment, int unpackRowLength, int unpackImageHeight, int unpackSkipPixels, int unpackSkipRows, int unpackSkipImages) { int start, end; computeTextureStartEnd( width, height, depth, format, type, unpackAlignment, unpackRowLength, unpackImageHeight, unpackSkipPixels, unpackSkipRows, unpackSkipImages, &start, &end); return end - start; } void computePackingOffsets2D( GLsizei width, GLsizei height, GLenum format, GLenum type, int packAlignment, int packRowLength, int packSkipPixels, int packSkipRows, int* startOffset, int* packingPixelRowSize, int* packingTotalRowSize) { int widthTotal = (packRowLength == 0) ? width : packRowLength; int totalRowSize = computePitch(widthTotal, format, type, packAlignment); int pixelsOnlyRowSize = computePitch(width, format, type, packAlignment); int packingOffsetStart = computePackingOffset( format, type, widthTotal, height, packAlignment, packSkipPixels, packSkipRows, 0 /* skip images = 0 */); if (startOffset) *startOffset = packingOffsetStart; if (packingPixelRowSize) *packingPixelRowSize = pixelsOnlyRowSize; if (packingTotalRowSize) *packingTotalRowSize = totalRowSize; } } // namespace GLESTextureUtils