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)