Fix texture uploads using different formats. Bug 21716622 Change-Id: I3154fc0c3da5c9f2f280101e8e5840ca45eb144e Reviewed-on: https://swiftshader-review.googlesource.com/3446 Reviewed-by: Nicolas Capens <capn@google.com> Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/common/Image.cpp b/src/OpenGL/common/Image.cpp index c1f939a..830be02 100644 --- a/src/OpenGL/common/Image.cpp +++ b/src/OpenGL/common/Image.cpp
@@ -11,6 +11,7 @@ #include "Image.hpp" +#include "Renderer/Blitter.hpp" #include "../libEGL/Texture.hpp" #include "../common/debug.h" #include "Common/Thread.hpp" @@ -356,6 +357,77 @@ namespace egl { + sw::Format ConvertFormatType(GLenum format, GLenum type) + { + switch(format) + { + case GL_LUMINANCE: + switch(type) + { + case GL_UNSIGNED_BYTE: return sw::FORMAT_L8; + case GL_HALF_FLOAT: return sw::FORMAT_L16F; + case GL_HALF_FLOAT_OES: return sw::FORMAT_L16F; + case GL_FLOAT: return sw::FORMAT_L32F; + default: UNREACHABLE(); + } + break; + case GL_LUMINANCE_ALPHA: + switch(type) + { + case GL_UNSIGNED_BYTE: return sw::FORMAT_A8L8; + case GL_HALF_FLOAT: return sw::FORMAT_A16L16F; + case GL_HALF_FLOAT_OES: return sw::FORMAT_A16L16F; + case GL_FLOAT: return sw::FORMAT_A32L32F; + default: UNREACHABLE(); + } + break; + case GL_RGBA: + switch(type) + { + case GL_UNSIGNED_BYTE: return sw::FORMAT_A8B8G8R8; + case GL_UNSIGNED_SHORT_4_4_4_4: return sw::FORMAT_R4G4B4A4; + case GL_UNSIGNED_SHORT_5_5_5_1: return sw::FORMAT_R5G5B5A1; + case GL_HALF_FLOAT: return sw::FORMAT_A16B16G16R16F; + case GL_HALF_FLOAT_OES: return sw::FORMAT_A16B16G16R16F; + case GL_FLOAT: return sw::FORMAT_A32B32G32R32F; + default: UNREACHABLE(); + } + break; + case GL_BGRA_EXT: + switch(type) + { + case GL_UNSIGNED_BYTE: return sw::FORMAT_A8R8G8B8; + default: UNREACHABLE(); + } + break; + case GL_RGB: + switch(type) + { + case GL_UNSIGNED_BYTE: return sw::FORMAT_B8G8R8; + case GL_UNSIGNED_SHORT_5_6_5: return sw::FORMAT_R5G6B5; + case GL_HALF_FLOAT: return sw::FORMAT_B16G16R16F; + case GL_HALF_FLOAT_OES: return sw::FORMAT_B16G16R16F; + case GL_FLOAT: return sw::FORMAT_B32G32R32F; + default: UNREACHABLE(); + } + break; + case GL_ALPHA: + switch(type) + { + case GL_UNSIGNED_BYTE: return sw::FORMAT_A8; + case GL_HALF_FLOAT: return sw::FORMAT_A16F; + case GL_HALF_FLOAT_OES: return sw::FORMAT_A16F; + case GL_FLOAT: return sw::FORMAT_A32F; + default: UNREACHABLE(); + } + break; + default: + UNREACHABLE(); + } + + return sw::FORMAT_NULL; + } + sw::Format SelectInternalFormat(GLenum format, GLenum type) { if(format == GL_ETC1_RGB8_OES) @@ -588,119 +660,130 @@ GLsizei inputPitch = (unpackInfo.rowLength == 0) ? ComputePitch(width, format, type, unpackInfo.alignment) : unpackInfo.rowLength; GLsizei inputHeight = (unpackInfo.imageHeight == 0) ? height : unpackInfo.imageHeight; input = ((char*)input) + (unpackInfo.skipImages * inputHeight + unpackInfo.skipRows) * inputPitch + unpackInfo.skipPixels; - void *buffer = lock(0, 0, sw::LOCK_WRITEONLY); - if(buffer) + if(SelectInternalFormat(format, type) == internalFormat) { - switch(type) - { - case GL_UNSIGNED_BYTE: - switch(format) - { - case GL_ALPHA: - LoadImageData<Alpha>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_LUMINANCE: - LoadImageData<Luminance>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_LUMINANCE_ALPHA: - LoadImageData<LuminanceAlpha>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_RGB: - LoadImageData<UByteRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_RGBA: - case GL_BGRA_EXT: - LoadImageData<UByte4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - default: UNREACHABLE(); - } - break; - case GL_UNSIGNED_SHORT_5_6_5: - switch(format) - { - case GL_RGB: - LoadImageData<RGB565>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - default: UNREACHABLE(); - } - break; - case GL_UNSIGNED_SHORT_4_4_4_4: - switch(format) - { - case GL_RGBA: - LoadImageData<RGBA4444>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - default: UNREACHABLE(); - } - break; - case GL_UNSIGNED_SHORT_5_5_5_1: - switch(format) - { - case GL_RGBA: - LoadImageData<RGBA5551>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - default: UNREACHABLE(); - } - break; - case GL_FLOAT: - switch(format) - { - // float textures are converted to RGBA, not BGRA - case GL_ALPHA: - LoadImageData<AlphaFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_LUMINANCE: - LoadImageData<LuminanceFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_LUMINANCE_ALPHA: - LoadImageData<LuminanceAlphaFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_RGB: - LoadImageData<FloatRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_RGBA: - LoadImageData<Float4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - default: UNREACHABLE(); - } - break; - case GL_HALF_FLOAT: - case GL_HALF_FLOAT_OES: - switch(format) - { - case GL_ALPHA: - LoadImageData<AlphaHalfFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_LUMINANCE: - LoadImageData<LuminanceHalfFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_LUMINANCE_ALPHA: - LoadImageData<LuminanceAlphaHalfFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_RGB: - LoadImageData<HalfFloatRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_RGBA: - LoadImageData<HalfFloat4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - default: UNREACHABLE(); - } - break; - case GL_UNSIGNED_SHORT: - LoadImageData<D16>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_UNSIGNED_INT: - LoadImageData<D32>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); - break; - case GL_UNSIGNED_INT_24_8_OES: - loadD24S8ImageData(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, input, buffer); - break; - default: UNREACHABLE(); - } - } + void *buffer = lock(0, 0, sw::LOCK_WRITEONLY); - unlock(); + if(buffer) + { + switch(type) + { + case GL_UNSIGNED_BYTE: + switch(format) + { + case GL_ALPHA: + LoadImageData<Alpha>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_LUMINANCE: + LoadImageData<Luminance>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_LUMINANCE_ALPHA: + LoadImageData<LuminanceAlpha>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_RGB: + LoadImageData<UByteRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_RGBA: + case GL_BGRA_EXT: + LoadImageData<UByte4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + default: UNREACHABLE(); + } + break; + case GL_UNSIGNED_SHORT_5_6_5: + switch(format) + { + case GL_RGB: + LoadImageData<RGB565>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + default: UNREACHABLE(); + } + break; + case GL_UNSIGNED_SHORT_4_4_4_4: + switch(format) + { + case GL_RGBA: + LoadImageData<RGBA4444>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + default: UNREACHABLE(); + } + break; + case GL_UNSIGNED_SHORT_5_5_5_1: + switch(format) + { + case GL_RGBA: + LoadImageData<RGBA5551>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + default: UNREACHABLE(); + } + break; + case GL_FLOAT: + switch(format) + { + // float textures are converted to RGBA, not BGRA + case GL_ALPHA: + LoadImageData<AlphaFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_LUMINANCE: + LoadImageData<LuminanceFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_LUMINANCE_ALPHA: + LoadImageData<LuminanceAlphaFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_RGB: + LoadImageData<FloatRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_RGBA: + LoadImageData<Float4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + default: UNREACHABLE(); + } + break; + case GL_HALF_FLOAT: + case GL_HALF_FLOAT_OES: + switch(format) + { + case GL_ALPHA: + LoadImageData<AlphaHalfFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_LUMINANCE: + LoadImageData<LuminanceHalfFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_LUMINANCE_ALPHA: + LoadImageData<LuminanceAlphaHalfFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_RGB: + LoadImageData<HalfFloatRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_RGBA: + LoadImageData<HalfFloat4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + default: UNREACHABLE(); + } + break; + case GL_UNSIGNED_SHORT: + LoadImageData<D16>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_UNSIGNED_INT: + LoadImageData<D32>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer, internalFormat); + break; + case GL_UNSIGNED_INT_24_8_OES: + loadD24S8ImageData(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, input, buffer); + break; + default: UNREACHABLE(); + } + } + + unlock(); + } + else + { + sw::Surface source(width, height, depth, ConvertFormatType(format, type), const_cast<void*>(input), inputPitch, inputPitch * inputHeight); + sw::Rect sourceRect(0, 0, width, height); + sw::Rect destRect(xoffset, yoffset, xoffset + width, yoffset + height); + sw::blitter.blit(&source, sourceRect, this, destRect, false); + } } void Image::loadD24S8ImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, const void *input, void *buffer)