Texture load functionality for integer types

- Added cases required to load integer type textures into
  swiftshader's internal formats.
- Cleaned up copy functions that simply perform a memcpy
  for a given number of bytes per row.
- Removed unused functionality for mini floats. Right now,
  all we need is the ability to import these formats, so
  there's currently no need to keep the export code.

Change-Id: I61500c41e668f885d3ec1e687b6f888c117221f2
Reviewed-on: https://swiftshader-review.googlesource.com/4140
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/Common/Math.hpp b/src/Common/Math.hpp
index c58bb52..2f74d05 100644
--- a/src/Common/Math.hpp
+++ b/src/Common/Math.hpp
@@ -346,211 +346,28 @@
 

 	class RGB9E5Data

 	{

-		union

-		{

-			struct

-			{

-				unsigned int R : 9;

-				unsigned int G : 9;

-				unsigned int B : 9;

-				unsigned int E : 5;

-			};

-			unsigned int uint;

-		};

-

-		// Exponent Bias

-		static const int Bias = 15;

-

-		// Number of mantissa bits per component

-		static const int MantissaBits = 9;

+		unsigned int R : 9;

+		unsigned int G : 9;

+		unsigned int B : 9;

+		unsigned int E : 5;

 

 	public:

-		RGB9E5Data(float red, float green, float blue)

+		void toRGBFloats(float* rgb) const

 		{

-			// Maximum allowed biased exponent value

-			static const int MaxExponent = 31;

+			static const float Offset = -24.0f; // Exponent Bias (15) + Number of mantissa bits per component (9) = 24

 

-			static const float MaxValue = ((pow(2.0f, MantissaBits) - 1) / pow(2.0f, MantissaBits)) * pow(2.0f, MaxExponent - Bias);

-

-			const float red_c = sw::max(0.0f, sw::min(MaxValue, red));

-			const float green_c = sw::max(0.0f, sw::min(MaxValue, green));

-			const float blue_c = sw::max(0.0f, sw::min(MaxValue, blue));

-

-			const float max_c = sw::max(sw::max(red_c, green_c), blue_c);

-			const float exp_p = sw::max(-Bias - 1.0f, floorf(log(max_c))) + 1.0f + Bias;

-			const int max_s = static_cast<int>(floor((max_c / (pow(2.0f, exp_p - Bias - MantissaBits))) + 0.5f));

-			const int exp_s = static_cast<int>((max_s < pow(2.0f, MantissaBits)) ? exp_p : exp_p + 1);

-

-			R = static_cast<unsigned int>(floor((red_c / (pow(2.0f, exp_s - Bias - MantissaBits))) + 0.5f));

-			G = static_cast<unsigned int>(floor((green_c / (pow(2.0f, exp_s - Bias - MantissaBits))) + 0.5f));

-			B = static_cast<unsigned int>(floor((blue_c / (pow(2.0f, exp_s - Bias - MantissaBits))) + 0.5f));

-			E = exp_s;

-		}

-

-		void toRGBFloats(float *red, float *green, float *blue) const

-		{

-			*red = R * pow(2.0f, (int)E - Bias - MantissaBits);

-			*green = G * pow(2.0f, (int)E - Bias - MantissaBits);

-			*blue = B * pow(2.0f, (int)E - Bias - MantissaBits);

-		}

-

-		unsigned int toUInt() const

-		{

-			return uint;

+			const float factor = powf(2.0f, static_cast<float>(E) + Offset);

+			rgb[0] = static_cast<float>(R) * factor;

+			rgb[1] = static_cast<float>(G) * factor;

+			rgb[2] = static_cast<float>(B) * factor;

 		}

 	};

 

 	class R11G11B10FData

 	{

-		union

-		{

-			struct

-			{

-				unsigned int R : 11;

-				unsigned int G : 11;

-				unsigned int B : 10;

-			};

-

-			unsigned int uint;

-		};

-

-		static inline unsigned short float32ToFloat11(float fp32)

-		{

-			const unsigned int float32MantissaMask = 0x7FFFFF;

-			const unsigned int float32ExponentMask = 0x7F800000;

-			const unsigned int float32SignMask = 0x80000000;

-			const unsigned int float32ValueMask = ~float32SignMask;

-			const unsigned int float32ExponentFirstBit = 23;

-			const unsigned int float32ExponentBias = 127;

-

-			const unsigned short float11Max = 0x7BF;

-			const unsigned short float11MantissaMask = 0x3F;

-			const unsigned short float11ExponentMask = 0x7C0;

-			const unsigned short float11BitMask = 0x7FF;

-			const unsigned int float11ExponentBias = 14;

-

-			const unsigned int float32Maxfloat11 = 0x477E0000;

-			const unsigned int float32Minfloat11 = 0x38800000;

-

-			const unsigned int float32Bits = *(unsigned int*)(&fp32);

-			const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;

-

-			unsigned int float32Val = float32Bits & float32ValueMask;

-

-			if((float32Val & float32ExponentMask) == float32ExponentMask)

-			{

-				// INF or NAN

-				if((float32Val & float32MantissaMask) != 0)

-				{

-					return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask);

-				}

-				else if(float32Sign)

-				{

-					// -INF is clamped to 0 since float11 is positive only

-					return 0;

-				}

-				else

-				{

-					return float11ExponentMask;

-				}

-			}

-			else if(float32Sign)

-			{

-				// float11 is positive only, so clamp to zero

-				return 0;

-			}

-			else if(float32Val > float32Maxfloat11)

-			{

-				// The number is too large to be represented as a float11, set to max

-				return float11Max;

-			}

-			else

-			{

-				if(float32Val < float32Minfloat11)

-				{

-					// The number is too small to be represented as a normalized float11

-					// Convert it to a denormalized value.

-					const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit);

-					float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;

-				}

-				else

-				{

-					// Rebias the exponent to represent the value as a normalized float11

-					float32Val += 0xC8000000;

-				}

-

-				return ((float32Val + 0xFFFF + ((float32Val >> 17) & 1)) >> 17) & float11BitMask;

-			}

-		}

-

-		static inline unsigned short float32ToFloat10(float fp32)

-		{

-			const unsigned int float32MantissaMask = 0x7FFFFF;

-			const unsigned int float32ExponentMask = 0x7F800000;

-			const unsigned int float32SignMask = 0x80000000;

-			const unsigned int float32ValueMask = ~float32SignMask;

-			const unsigned int float32ExponentFirstBit = 23;

-			const unsigned int float32ExponentBias = 127;

-

-			const unsigned short float10Max = 0x3DF;

-			const unsigned short float10MantissaMask = 0x1F;

-			const unsigned short float10ExponentMask = 0x3E0;

-			const unsigned short float10BitMask = 0x3FF;

-			const unsigned int float10ExponentBias = 14;

-

-			const unsigned int float32Maxfloat10 = 0x477C0000;

-			const unsigned int float32Minfloat10 = 0x38800000;

-

-			const unsigned int float32Bits = *(unsigned int*)(&fp32);

-			const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;

-

-			unsigned int float32Val = float32Bits & float32ValueMask;

-

-			if((float32Val & float32ExponentMask) == float32ExponentMask)

-			{

-				// INF or NAN

-				if((float32Val & float32MantissaMask) != 0)

-				{

-					return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask);

-				}

-				else if(float32Sign)

-				{

-					// -INF is clamped to 0 since float11 is positive only

-					return 0;

-				}

-				else

-				{

-					return float10ExponentMask;

-				}

-			}

-			else if(float32Sign)

-			{

-				// float10 is positive only, so clamp to zero

-				return 0;

-			}

-			else if(float32Val > float32Maxfloat10)

-			{

-				// The number is too large to be represented as a float11, set to max

-				return float10Max;

-			}

-			else

-			{

-				if(float32Val < float32Minfloat10)

-				{

-					// The number is too small to be represented as a normalized float11

-					// Convert it to a denormalized value.

-					const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit);

-					float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;

-				}

-				else

-				{

-					// Rebias the exponent to represent the value as a normalized float11

-					float32Val += 0xC8000000;

-				}

-

-				return ((float32Val + 0x1FFFF + ((float32Val >> 18) & 1)) >> 18) & float10BitMask;

-			}

-		}

+		unsigned int R : 11;

+		unsigned int G : 11;

+		unsigned int B : 10;

 

 		static inline float float11ToFloat32(unsigned short fp11)

 		{

@@ -635,23 +452,11 @@
 		}

 

 	public:

-		R11G11B10FData(float r, float g, float b)

+		void toRGBFloats(float* rgb) const

 		{

-			R = float32ToFloat11(r);

-			G = float32ToFloat11(g);

-			B = float32ToFloat10(b);

-		}

-

-		void toRGBFloats(float *red, float *green, float *blue) const

-		{

-			*red = float11ToFloat32(R);

-			*green = float11ToFloat32(G);

-			*blue = float10ToFloat32(B);

-		}

-

-		unsigned int toUInt() const

-		{

-			return uint;

+			rgb[0] = float11ToFloat32(R);

+			rgb[1] = float11ToFloat32(G);

+			rgb[2] = float10ToFloat32(B);

 		}

 	};

 }

diff --git a/src/OpenGL/common/Image.cpp b/src/OpenGL/common/Image.cpp
index b77f6a7..04914c8 100644
--- a/src/OpenGL/common/Image.cpp
+++ b/src/OpenGL/common/Image.cpp
@@ -14,6 +14,7 @@
 #include "Renderer/Blitter.hpp"
 #include "../libEGL/Texture.hpp"
 #include "../common/debug.h"
+#include "Common/Math.hpp"
 #include "Common/Thread.hpp"
 
 #include <GLES/glext.h>
@@ -31,28 +32,39 @@
 
 	enum DataType
 	{
-		Alpha,
+		Bytes_1,
+		Bytes_2,
+		Bytes_4,
+		Bytes_8,
+		Bytes_16,
 		AlphaFloat,
 		AlphaHalfFloat,
-		Luminance,
 		LuminanceFloat,
 		LuminanceHalfFloat,
-		LuminanceAlpha,
 		LuminanceAlphaFloat,
 		LuminanceAlphaHalfFloat,
+		ByteRGB,
 		UByteRGB,
+		ShortRGB,
+		UShortRGB,
+		IntRGB,
+		UIntRGB,
 		RGB565,
 		FloatRGB,
 		HalfFloatRGB,
-		UByte4,
 		RGBA4444,
 		RGBA5551,
-		Float4,
-		HalfFloat4,
+		RGB10A2UI,
+		R11G11B10F,
+		RGB9E5,
+		SRGB,
+		SRGBA,
 		D16,
 		D24,
 		D32,
+		D32F,
 		S8,
+		S24_8,
 	};
 
 	template<DataType dataType>
@@ -62,12 +74,36 @@
 	}
 
 	template<>
-	void LoadImageRow<Alpha>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	void LoadImageRow<Bytes_1>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
 	{
 		memcpy(dest + xoffset, source, width);
 	}
 
 	template<>
+	void LoadImageRow<Bytes_2>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		memcpy(dest + xoffset * 2, source, width * 2);
+	}
+
+	template<>
+	void LoadImageRow<Bytes_4>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		memcpy(dest + xoffset * 4, source, width * 4);
+	}
+
+	template<>
+	void LoadImageRow<Bytes_8>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		memcpy(dest + xoffset * 8, source, width * 8);
+	}
+
+	template<>
+	void LoadImageRow<Bytes_16>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		memcpy(dest + xoffset * 16, source, width * 16);
+	}
+
+	template<>
 	void LoadImageRow<AlphaFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
 	{
 		const float *sourceF = reinterpret_cast<const float*>(source);
@@ -98,12 +134,6 @@
 	}
 
 	template<>
-	void LoadImageRow<Luminance>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
-	{
-		memcpy(dest + xoffset, source, width);
-	}
-
-	template<>
 	void LoadImageRow<LuminanceFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
 	{
 		const float *sourceF = reinterpret_cast<const float*>(source);
@@ -134,12 +164,6 @@
 	}
 
 	template<>
-	void LoadImageRow<LuminanceAlpha>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
-	{
-		memcpy(dest + xoffset * 2, source, width * 2);
-	}
-
-	template<>
 	void LoadImageRow<LuminanceAlphaFloat>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
 	{
 		const float *sourceF = reinterpret_cast<const float*>(source);
@@ -170,6 +194,20 @@
 	}
 
 	template<>
+	void LoadImageRow<ByteRGB>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		unsigned char *destB = dest + xoffset * 4;
+
+		for(int x = 0; x < width; x++)
+		{
+			destB[4 * x + 0] = source[x * 3 + 0];
+			destB[4 * x + 1] = source[x * 3 + 1];
+			destB[4 * x + 2] = source[x * 3 + 2];
+			destB[4 * x + 3] = 0x7F;
+		}
+	}
+
+	template<>
 	void LoadImageRow<UByteRGB>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
 	{
 		unsigned char *destB = dest + xoffset * 4;
@@ -184,6 +222,66 @@
 	}
 
 	template<>
+	void LoadImageRow<ShortRGB>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		const unsigned short *sourceS = reinterpret_cast<const unsigned short*>(source);
+		unsigned short *destS = reinterpret_cast<unsigned short*>(dest + xoffset * 8);
+
+		for(int x = 0; x < width; x++)
+		{
+			destS[4 * x + 0] = sourceS[x * 3 + 0];
+			destS[4 * x + 1] = sourceS[x * 3 + 1];
+			destS[4 * x + 2] = sourceS[x * 3 + 2];
+			destS[4 * x + 3] = 0x7FFF;
+		}
+	}
+
+	template<>
+	void LoadImageRow<UShortRGB>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		const unsigned short *sourceS = reinterpret_cast<const unsigned short*>(source);
+		unsigned short *destS = reinterpret_cast<unsigned short*>(dest + xoffset * 8);
+
+		for(int x = 0; x < width; x++)
+		{
+			destS[4 * x + 0] = sourceS[x * 3 + 0];
+			destS[4 * x + 1] = sourceS[x * 3 + 1];
+			destS[4 * x + 2] = sourceS[x * 3 + 2];
+			destS[4 * x + 3] = 0xFFFF;
+		}
+	}
+
+	template<>
+	void LoadImageRow<IntRGB>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		const unsigned int *sourceI = reinterpret_cast<const unsigned int*>(source);
+		unsigned int *destI = reinterpret_cast<unsigned int*>(dest + xoffset * 16);
+
+		for(int x = 0; x < width; x++)
+		{
+			destI[4 * x + 0] = sourceI[x * 3 + 0];
+			destI[4 * x + 1] = sourceI[x * 3 + 1];
+			destI[4 * x + 2] = sourceI[x * 3 + 2];
+			destI[4 * x + 3] = 0x7FFFFFFF;
+		}
+	}
+
+	template<>
+	void LoadImageRow<UIntRGB>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		const unsigned int *sourceI = reinterpret_cast<const unsigned int*>(source);
+		unsigned int *destI = reinterpret_cast<unsigned int*>(dest + xoffset * 16);
+
+		for(int x = 0; x < width; x++)
+		{
+			destI[4 * x + 0] = sourceI[x * 3 + 0];
+			destI[4 * x + 1] = sourceI[x * 3 + 1];
+			destI[4 * x + 2] = sourceI[x * 3 + 2];
+			destI[4 * x + 3] = 0xFFFFFFFF;
+		}
+	}
+
+	template<>
 	void LoadImageRow<RGB565>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
 	{
 		memcpy(dest + xoffset * 2, source, width * 2);
@@ -220,12 +318,6 @@
 	}
 
 	template<>
-	void LoadImageRow<UByte4>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
-	{
-		memcpy(dest + xoffset * 4, source, width * 4);
-	}
-
-	template<>
 	void LoadImageRow<RGBA4444>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
 	{
 		const unsigned short *source4444 = reinterpret_cast<const unsigned short*>(source);
@@ -258,15 +350,75 @@
 	}
 
 	template<>
-	void LoadImageRow<Float4>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	void LoadImageRow<RGB10A2UI>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
 	{
-		memcpy(dest + xoffset * 16, source, width * 16);
+		const unsigned int *source1010102U = reinterpret_cast<const unsigned int*>(source);
+		unsigned short *dest16U = reinterpret_cast<unsigned short*>(dest + xoffset * 8);
+
+		for(int x = 0; x < width; x++)
+		{
+			unsigned int rgba = source1010102U[x];
+			dest16U[4 * x + 0] = (rgba & 0x00000FFC) >> 2;
+			dest16U[4 * x + 1] = (rgba & 0x003FF000) >> 12;
+			dest16U[4 * x + 2] = (rgba & 0xFFC00000) >> 22;
+			dest16U[4 * x + 3] = (rgba & 0x00000003);
+		}
 	}
 
 	template<>
-	void LoadImageRow<HalfFloat4>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	void LoadImageRow<R11G11B10F>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
 	{
-		memcpy(dest + xoffset * 8, source, width * 8);
+		const sw::R11G11B10FData *sourceRGB = reinterpret_cast<const sw::R11G11B10FData*>(source);
+		float *destF = reinterpret_cast<float*>(dest + xoffset * 16);
+
+		for(int x = 0; x < width; x++, sourceRGB++, destF+=4)
+		{
+			sourceRGB->toRGBFloats(destF);
+			destF[3] = 1.0f;
+		}
+	}
+
+	template<>
+	void LoadImageRow<RGB9E5>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		const sw::RGB9E5Data *sourceRGB = reinterpret_cast<const sw::RGB9E5Data*>(source);
+		float *destF = reinterpret_cast<float*>(dest + xoffset * 16);
+
+		for(int x = 0; x < width; x++, sourceRGB++, destF += 4)
+		{
+			sourceRGB->toRGBFloats(destF);
+			destF[3] = 1.0f;
+		}
+	}
+
+	template<>
+	void LoadImageRow<SRGB>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		dest += xoffset * 4;
+
+		for(int x = 0; x < width; x++)
+		{
+			for(int rgb = 0; rgb < 3; ++rgb)
+			{
+				*dest++ = sw::sRGB8toLinear8(*source++);
+			}
+			*dest++ = 255;
+		}
+	}
+
+	template<>
+	void LoadImageRow<SRGBA>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		dest += xoffset * 4;
+
+		for(int x = 0; x < width; x++)
+		{
+			for(int rgb = 0; rgb < 3; ++rgb)
+			{
+				*dest++ = sw::sRGB8toLinear8(*source++);
+			}
+			*dest++ = *source++;
+		}
 	}
 
 	template<>
@@ -317,6 +469,32 @@
 		}
 	}
 
+	template<>
+	void LoadImageRow<D32F>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		struct D32FS8 { float depth32f; unsigned int stencil24_8; };
+		const D32FS8 *sourceD32FS8 = reinterpret_cast<const D32FS8*>(source);
+		float *destF = reinterpret_cast<float*>(dest + xoffset * 4);
+
+		for(int x = 0; x < width; x++)
+		{
+			destF[x] = sourceD32FS8[x].depth32f;
+		}
+	}
+
+	template<>
+	void LoadImageRow<S24_8>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
+	{
+		struct D32FS8 { float depth32f; unsigned int stencil24_8; };
+		const D32FS8 *sourceD32FS8 = reinterpret_cast<const D32FS8*>(source);
+		unsigned char *destI = dest + xoffset;
+
+		for(int x = 0; x < width; x++)
+		{
+			destI[x] = static_cast<unsigned char>(sourceD32FS8[x].stencil24_8 & 0x000000FF);   // FIXME: Quad layout
+		}
+	}
+
 	template<DataType dataType>
 	void LoadImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, int destPitch, GLsizei destHeight, const void *input, void *buffer)
 	{
@@ -351,6 +529,12 @@
 			default: UNREACHABLE(type);
 			}
 			break;
+		case GL_LUMINANCE8_EXT:
+			return sw::FORMAT_L8;
+		case GL_LUMINANCE16F_EXT:
+			return sw::FORMAT_L16F;
+		case GL_LUMINANCE32F_EXT:
+			return sw::FORMAT_L32F;
 		case GL_LUMINANCE_ALPHA:
 			switch(type)
 			{
@@ -361,6 +545,12 @@
 			default: UNREACHABLE(type);
 			}
 			break;
+		case GL_LUMINANCE8_ALPHA8_EXT:
+			return sw::FORMAT_A8L8;
+		case GL_LUMINANCE_ALPHA16F_EXT:
+			return sw::FORMAT_A16L16F;
+		case GL_LUMINANCE_ALPHA32F_EXT:
+			return sw::FORMAT_A32L32F;
 		case GL_RGBA:
 			switch(type)
 			{
@@ -401,6 +591,12 @@
 			default: UNREACHABLE(type);
 			}
 			break;
+		case GL_ALPHA8_EXT:
+			return sw::FORMAT_A8;
+		case GL_ALPHA16F_EXT:
+			return sw::FORMAT_A16F;
+		case GL_ALPHA32F_EXT:
+			return sw::FORMAT_A32F;
 		default:
 			UNREACHABLE(format);
 		}
@@ -503,85 +699,248 @@
 			break;
 		}
 
-		if(type == GL_FLOAT)
+		switch(type)
 		{
+		case GL_FLOAT:
+			switch(format)
+			{
+			case GL_RED:
+			case GL_R32F:
+				return sw::FORMAT_R32F;
+			case GL_RG:
+			case GL_RG32F:
+				return sw::FORMAT_G32R32F;
+			case GL_RGB:
+			case GL_RGB32F:
+			case GL_RGBA:
+			case GL_RGBA32F:
 			return sw::FORMAT_A32B32G32R32F;
-		}
-		else if(type == GL_HALF_FLOAT || type == GL_HALF_FLOAT_OES)
-		{
+			case GL_DEPTH_COMPONENT:
+			case GL_DEPTH_COMPONENT32F:
+				return sw::FORMAT_D32F;
+			default:
+				UNREACHABLE(format);
+			}
+		case GL_HALF_FLOAT:
+		case GL_HALF_FLOAT_OES:
+			switch(format)
+			{
+			case GL_RED:
+			case GL_R16F:
+				return sw::FORMAT_R16F;
+			case GL_RG:
+			case GL_RG16F:
+				return sw::FORMAT_G16R16F;
+			case GL_RGB:
+			case GL_RGB16F:
+			case GL_RGBA:
+			case GL_RGBA16F:
 			return sw::FORMAT_A16B16G16R16F;
-		}
-		else if(type == GL_UNSIGNED_BYTE)
-		{
-			if(format == GL_LUMINANCE)
+			default:
+				UNREACHABLE(format);
+			}
+		case GL_BYTE:
+			switch(format)
 			{
+			case GL_R8_SNORM:
+			case GL_R8:
+			case GL_RED:
+				return sw::FORMAT_R8I_SNORM;
+			case GL_R8I:
+			case GL_RED_INTEGER:
+				return sw::FORMAT_R8I;
+			case GL_RG8_SNORM:
+			case GL_RG8:
+			case GL_RG:
+				return sw::FORMAT_G8R8I_SNORM;
+			case GL_RG8I:
+			case GL_RG_INTEGER:
+				return sw::FORMAT_G8R8I;
+			case GL_RGB8_SNORM:
+			case GL_RGB8:
+			case GL_RGB:
+				return sw::FORMAT_X8B8G8R8I_SNORM;
+			case GL_RGB8I:
+			case GL_RGB_INTEGER:
+				return sw::FORMAT_X8B8G8R8I;
+			case GL_RGBA8_SNORM:
+			case GL_RGBA8:
+			case GL_RGBA:
+				return sw::FORMAT_A8B8G8R8I_SNORM;
+			case GL_RGBA8I:
+			case GL_RGBA_INTEGER:
+				return sw::FORMAT_A8B8G8R8I;
+			default:
+				UNREACHABLE(format);
+			}
+		case GL_UNSIGNED_BYTE:
+			switch(format)
+			{
+			case GL_LUMINANCE:
+			case GL_LUMINANCE8_EXT:
 				return sw::FORMAT_L8;
-			}
-			else if(format == GL_LUMINANCE_ALPHA)
-			{
+			case GL_LUMINANCE_ALPHA:
+			case GL_LUMINANCE8_ALPHA8_EXT:
 				return sw::FORMAT_A8L8;
-			}
-			else if(format == GL_RGBA)
-			{
-				return sw::FORMAT_A8B8G8R8;
-			}
-			else if(format == GL_BGRA_EXT)
-			{
-				return sw::FORMAT_A8R8G8B8;
-			}
-			else if(format == GL_RGB)
-			{
+			case GL_R8_SNORM:
+			case GL_R8:
+			case GL_RED:
+				return sw::FORMAT_R8;
+			case GL_R8UI:
+			case GL_RED_INTEGER:
+				return sw::FORMAT_R8UI;
+			case GL_RG8_SNORM:
+			case GL_RG8:
+			case GL_RG:
+				return sw::FORMAT_G8R8;
+			case GL_RG8UI:
+			case GL_RG_INTEGER:
+				return sw::FORMAT_G8R8UI;
+			case GL_RGB8_SNORM:
+			case GL_RGB8:
+			case GL_RGB:
+			case GL_SRGB8:
 				return sw::FORMAT_X8B8G8R8;
-			}
-			else if(format == GL_ALPHA)
-			{
+			case GL_RGB8UI:
+			case GL_RGB_INTEGER:
+				return sw::FORMAT_X8B8G8R8UI;
+			case GL_RGBA8_SNORM:
+			case GL_RGBA8:
+			case GL_RGBA:
+			case GL_SRGB8_ALPHA8:
+				return sw::FORMAT_A8B8G8R8;
+			case GL_RGBA8UI:
+			case GL_RGBA_INTEGER:
+				return sw::FORMAT_A8B8G8R8UI;
+			case GL_BGRA_EXT:
+				return sw::FORMAT_A8R8G8B8;
+			case GL_ALPHA:
+			case GL_ALPHA8_EXT:
 				return sw::FORMAT_A8;
+			default:
+				UNREACHABLE(format);
 			}
-			else if(format == SW_YV12_BT601)
+		case GL_SHORT:
+			switch(format)
 			{
-				return sw::FORMAT_YV12_BT601;
+			case GL_R16I:
+			case GL_RED_INTEGER:
+				return sw::FORMAT_R16I;
+			case GL_RG16I:
+			case GL_RG_INTEGER:
+				return sw::FORMAT_G16R16I;
+			case GL_RGB16I:
+			case GL_RGB_INTEGER:
+				return sw::FORMAT_X16B16G16R16I;
+			case GL_RGBA16I:
+			case GL_RGBA_INTEGER:
+				return sw::FORMAT_A16B16G16R16I;
+			default:
+				UNREACHABLE(format);
 			}
-			else if(format == SW_YV12_BT709)
+		case GL_UNSIGNED_SHORT:
+			switch(format)
 			{
-				return sw::FORMAT_YV12_BT709;
+			case GL_R16UI:
+			case GL_RED_INTEGER:
+				return sw::FORMAT_R16UI;
+			case GL_RG16UI:
+			case GL_RG_INTEGER:
+				return sw::FORMAT_G16R16UI;
+			case GL_RGB16UI:
+			case GL_RGB_INTEGER:
+				return sw::FORMAT_X16B16G16R16UI;
+			case GL_RGBA16UI:
+			case GL_RGBA_INTEGER:
+				return sw::FORMAT_A16B16G16R16UI;
+			case GL_DEPTH_COMPONENT:
+			case GL_DEPTH_COMPONENT16:
+				return sw::FORMAT_D32FS8_TEXTURE;
+			default:
+				UNREACHABLE(format);
 			}
-			else if(format == SW_YV12_JFIF)
+		case GL_INT:
+			switch(format)
 			{
-				return sw::FORMAT_YV12_JFIF;
+			case GL_RED_INTEGER:
+			case GL_R32I:
+				return sw::FORMAT_R32I;
+			case GL_RG_INTEGER:
+			case GL_RG32I:
+				return sw::FORMAT_G32R32I;
+			case GL_RGB_INTEGER:
+			case GL_RGB32I:
+				return sw::FORMAT_X32B32G32R32I;
+			case GL_RGBA_INTEGER:
+			case GL_RGBA32I:
+				return sw::FORMAT_A32B32G32R32I;
+			default:
+				UNREACHABLE(format);
 			}
-			else UNREACHABLE(format);
-		}
-		else if(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT)
-		{
-			if(format == GL_DEPTH_COMPONENT)
+		case GL_UNSIGNED_INT:
+			switch(format)
+			{
+			case GL_RED_INTEGER:
+			case GL_R32UI:
+				return sw::FORMAT_R32UI;
+			case GL_RG_INTEGER:
+			case GL_RG32UI:
+				return sw::FORMAT_G32R32UI;
+			case GL_RGB_INTEGER:
+			case GL_RGB32UI:
+				return sw::FORMAT_X32B32G32R32UI;
+			case GL_RGBA_INTEGER:
+			case GL_RGBA32UI:
+				return sw::FORMAT_A32B32G32R32UI;
+			case GL_DEPTH_COMPONENT:
+			case GL_DEPTH_COMPONENT16:
+			case GL_DEPTH_COMPONENT24:
+			case GL_DEPTH_COMPONENT32_OES:
+				return sw::FORMAT_D32FS8_TEXTURE;
+			default:
+				UNREACHABLE(format);
+			}
+		case GL_UNSIGNED_INT_24_8_OES:
+			if(format == GL_DEPTH_STENCIL || format == GL_DEPTH24_STENCIL8)
 			{
 				return sw::FORMAT_D32FS8_TEXTURE;
 			}
 			else UNREACHABLE(format);
-		}
-		else if(type == GL_UNSIGNED_INT_24_8_OES)
-		{
-			if(format == GL_DEPTH_STENCIL_OES)
+		case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+			if(format == GL_DEPTH_STENCIL || format == GL_DEPTH32F_STENCIL8)
 			{
 				return sw::FORMAT_D32FS8_TEXTURE;
 			}
 			else UNREACHABLE(format);
-		}
-		else if(type == GL_UNSIGNED_SHORT_4_4_4_4)
-		{
+		case GL_UNSIGNED_SHORT_4_4_4_4:
 			return sw::FORMAT_A8R8G8B8;
-		}
-		else if(type == GL_UNSIGNED_SHORT_5_5_5_1)
-		{
+		case GL_UNSIGNED_SHORT_5_5_5_1:
 			return sw::FORMAT_A8R8G8B8;
-		}
-		else if(type == GL_UNSIGNED_SHORT_5_6_5)
-		{
+		case GL_UNSIGNED_SHORT_5_6_5:
 			return sw::FORMAT_R5G6B5;
+		case GL_UNSIGNED_INT_2_10_10_10_REV:
+			if(format == GL_RGB10_A2UI)
+			{
+				return sw::FORMAT_A16B16G16R16UI;
+			}
+			else
+			{
+				return sw::FORMAT_A2B10G10R10;
+			}
+		case GL_UNSIGNED_INT_10F_11F_11F_REV:
+		case GL_UNSIGNED_INT_5_9_9_9_REV:
+			return sw::FORMAT_A32B32G32R32F;
+		case SW_YV12_BT601:
+			return sw::FORMAT_YV12_BT601;
+		case SW_YV12_BT709:
+			return sw::FORMAT_YV12_BT709;
+		case SW_YV12_JFIF:
+			return sw::FORMAT_YV12_JFIF;
+		default:
+			UNREACHABLE(type);
 		}
-		else UNREACHABLE(type);
 
-		return sw::FORMAT_A8B8G8R8;
+		return sw::FORMAT_NULL;
 	}
 
 	// Returns the size, in bytes, of a single texel in an Image
@@ -589,34 +948,155 @@
 	{
 		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: UNREACHABLE(format);
+			}
+			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:        return sizeof(unsigned char) * 4;
 			default: UNREACHABLE(format);
 			}
 			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: UNREACHABLE(format);
+			}
+			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: UNREACHABLE(format);
+			}
+			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: UNREACHABLE(format);
+			}
+			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: UNREACHABLE(format);
+			}
+			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:
 			return sizeof(unsigned short);
-		case GL_UNSIGNED_INT:
+		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: UNREACHABLE(format);
 			}
 			break;
@@ -624,11 +1104,20 @@
 		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: UNREACHABLE(format);
 			}
 			break;
@@ -765,8 +1254,13 @@
 		GLsizei inputPitch = ComputePitch((unpackInfo.rowLength == 0) ? width : unpackInfo.rowLength, format, type, unpackInfo.alignment);
 		GLsizei inputHeight = (unpackInfo.imageHeight == 0) ? height : unpackInfo.imageHeight;
 		input = ((char*)input) + (unpackInfo.skipImages * inputHeight + unpackInfo.skipRows) * inputPitch + unpackInfo.skipPixels;
+		sw::Format selectedInternalFormat = SelectInternalFormat(format, type);
+		if(selectedInternalFormat == sw::FORMAT_NULL)
+		{
+			return;
+		}
 
-		if(SelectInternalFormat(format, type) == internalFormat)
+		if(selectedInternalFormat == internalFormat)
 		{
 			void *buffer = lock(0, 0, sw::LOCK_WRITEONLY);
 
@@ -774,24 +1268,90 @@
 			{
 				switch(type)
 				{
+				case GL_BYTE:
+					switch(format)
+					{
+					case GL_R8:
+					case GL_R8I:
+					case GL_R8_SNORM:
+					case GL_RED:
+					case GL_RED_INTEGER:
+					case GL_ALPHA:
+					case GL_ALPHA8_EXT:
+					case GL_LUMINANCE:
+					case GL_LUMINANCE8_EXT:
+						LoadImageData<Bytes_1>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RG8:
+					case GL_RG8I:
+					case GL_RG8_SNORM:
+					case GL_RG:
+					case GL_RG_INTEGER:
+					case GL_LUMINANCE_ALPHA:
+					case GL_LUMINANCE8_ALPHA8_EXT:
+						LoadImageData<Bytes_2>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RGB8:
+					case GL_RGB8I:
+					case GL_RGB8_SNORM:
+					case GL_RGB:
+					case GL_RGB_INTEGER:
+						LoadImageData<ByteRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RGBA8:
+					case GL_RGBA8I:
+					case GL_RGBA8_SNORM:
+					case GL_RGBA:
+					case GL_RGBA_INTEGER:
+					case GL_BGRA_EXT:
+						LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					default: UNREACHABLE(format);
+					}
+					break;
 				case GL_UNSIGNED_BYTE:
 					switch(format)
 					{
+					case GL_R8:
+					case GL_R8UI:
+					case GL_R8_SNORM:
+					case GL_RED:
+					case GL_RED_INTEGER:
 					case GL_ALPHA:
-						LoadImageData<Alpha>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
-						break;
+					case GL_ALPHA8_EXT:
 					case GL_LUMINANCE:
-						LoadImageData<Luminance>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+					case GL_LUMINANCE8_EXT:
+						LoadImageData<Bytes_1>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
+					case GL_RG8:
+					case GL_RG8UI:
+					case GL_RG8_SNORM:
+					case GL_RG:
+					case GL_RG_INTEGER:
 					case GL_LUMINANCE_ALPHA:
-						LoadImageData<LuminanceAlpha>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+					case GL_LUMINANCE8_ALPHA8_EXT:
+						LoadImageData<Bytes_2>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
+					case GL_RGB8:
+					case GL_RGB8UI:
+					case GL_RGB8_SNORM:
 					case GL_RGB:
+					case GL_RGB_INTEGER:
 						LoadImageData<UByteRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
+					case GL_RGBA8:
+					case GL_RGBA8UI:
+					case GL_RGBA8_SNORM:
 					case GL_RGBA:
+					case GL_RGBA_INTEGER:
 					case GL_BGRA_EXT:
-						LoadImageData<UByte4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_SRGB8:
+						LoadImageData<SRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_SRGB8_ALPHA8:
+						LoadImageData<SRGBA>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
 					default: UNREACHABLE(format);
 					}
@@ -799,6 +1359,7 @@
 				case GL_UNSIGNED_SHORT_5_6_5:
 					switch(format)
 					{
+					case GL_RGB565:
 					case GL_RGB:
 						LoadImageData<RGB565>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
@@ -808,6 +1369,7 @@
 				case GL_UNSIGNED_SHORT_4_4_4_4:
 					switch(format)
 					{
+					case GL_RGBA4:
 					case GL_RGBA:
 						LoadImageData<RGBA4444>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
@@ -817,30 +1379,82 @@
 				case GL_UNSIGNED_SHORT_5_5_5_1:
 					switch(format)
 					{
+					case GL_RGB5_A1:
 					case GL_RGBA:
 						LoadImageData<RGBA5551>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
 					default: UNREACHABLE(format);
 					}
 					break;
+				case GL_UNSIGNED_INT_10F_11F_11F_REV:
+					switch(format)
+					{
+					case GL_R11F_G11F_B10F:
+					case GL_RGB:
+						LoadImageData<R11G11B10F>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					default: UNREACHABLE(format);
+					}
+					break;
+				case GL_UNSIGNED_INT_5_9_9_9_REV:
+					switch(format)
+					{
+					case GL_RGB9_E5:
+					case GL_RGB:
+						LoadImageData<RGB9E5>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					default: UNREACHABLE(format);
+					}
+					break;
+				case GL_UNSIGNED_INT_2_10_10_10_REV:
+					switch(format)
+					{
+					case GL_RGB10_A2UI:
+						LoadImageData<RGB10A2UI>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RGB10_A2:
+					case GL_RGBA:
+					case GL_RGBA_INTEGER:
+						LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					default: UNREACHABLE(format);
+					}
+					break;
 				case GL_FLOAT:
 					switch(format)
 					{
 					// float textures are converted to RGBA, not BGRA
 					case GL_ALPHA:
+					case GL_ALPHA32F_EXT:
 						LoadImageData<AlphaFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
 					case GL_LUMINANCE:
+					case GL_LUMINANCE32F_EXT:
 						LoadImageData<LuminanceFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
 					case GL_LUMINANCE_ALPHA:
+					case GL_LUMINANCE_ALPHA32F_EXT:
 						LoadImageData<LuminanceAlphaFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
+					case GL_RED:
+					case GL_R32F:
+						LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RG:
+					case GL_RG32F:
+						LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
 					case GL_RGB:
+					case GL_RGB32F:
 						LoadImageData<FloatRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
 					case GL_RGBA:
-						LoadImageData<Float4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+					case GL_RGBA32F:
+						LoadImageData<Bytes_16>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_DEPTH_COMPONENT:
+					case GL_DEPTH_COMPONENT32F:
+						LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
 					default: UNREACHABLE(format);
 					}
@@ -850,32 +1464,172 @@
 					switch(format)
 					{
 					case GL_ALPHA:
+					case GL_ALPHA16F_EXT:
 						LoadImageData<AlphaHalfFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
 					case GL_LUMINANCE:
+					case GL_LUMINANCE16F_EXT:
 						LoadImageData<LuminanceHalfFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
 					case GL_LUMINANCE_ALPHA:
+					case GL_LUMINANCE_ALPHA16F_EXT:
 						LoadImageData<LuminanceAlphaHalfFloat>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
+					case GL_RED:
+					case GL_R16F:
+						LoadImageData<Bytes_2>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RG:
+					case GL_RG16F:
+						LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
 					case GL_RGB:
+					case GL_RGB16F:
 						LoadImageData<HalfFloatRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
 					case GL_RGBA:
-						LoadImageData<HalfFloat4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+					case GL_RGBA16F:
+						LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					default: UNREACHABLE(format);
+					}
+					break;
+				case GL_SHORT:
+					switch(format)
+					{
+					case GL_R16I:
+					case GL_RED:
+					case GL_RED_INTEGER:
+					case GL_ALPHA:
+					case GL_LUMINANCE:
+						LoadImageData<Bytes_2>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RG16I:
+					case GL_RG:
+					case GL_RG_INTEGER:
+					case GL_LUMINANCE_ALPHA:
+						LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RGB16I:
+					case GL_RGB:
+					case GL_RGB_INTEGER:
+						LoadImageData<ShortRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RGBA16I:
+					case GL_RGBA:
+					case GL_RGBA_INTEGER:
+					case GL_BGRA_EXT:
+						LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
 						break;
 					default: UNREACHABLE(format);
 					}
 					break;
 				case GL_UNSIGNED_SHORT:
-					LoadImageData<D16>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+					switch(format)
+					{
+					case GL_R16UI:
+					case GL_RED:
+					case GL_RED_INTEGER:
+					case GL_ALPHA:
+					case GL_LUMINANCE:
+						LoadImageData<Bytes_2>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RG16UI:
+					case GL_RG:
+					case GL_RG_INTEGER:
+					case GL_LUMINANCE_ALPHA:
+						LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RGB16UI:
+					case GL_RGB:
+					case GL_RGB_INTEGER:
+						LoadImageData<UShortRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RGBA16UI:
+					case GL_RGBA:
+					case GL_RGBA_INTEGER:
+					case GL_BGRA_EXT:
+						LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_DEPTH_COMPONENT:
+					case GL_DEPTH_COMPONENT16:
+						LoadImageData<D16>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					default: UNREACHABLE(format);
+					}
+					break;
+				case GL_INT:
+					switch(format)
+					{
+					case GL_R32I:
+					case GL_RED:
+					case GL_RED_INTEGER:
+					case GL_ALPHA:
+					case GL_LUMINANCE:
+						LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RG32I:
+					case GL_RG:
+					case GL_RG_INTEGER:
+					case GL_LUMINANCE_ALPHA:
+						LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RGB32I:
+					case GL_RGB:
+					case GL_RGB_INTEGER:
+						LoadImageData<IntRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RGBA32I:
+					case GL_RGBA:
+					case GL_RGBA_INTEGER:
+					case GL_BGRA_EXT:
+						LoadImageData<Bytes_16>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					default: UNREACHABLE(format);
+					}
 					break;
 				case GL_UNSIGNED_INT:
-					LoadImageData<D32>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+					switch(format)
+					{
+					case GL_R32UI:
+					case GL_RED:
+					case GL_RED_INTEGER:
+					case GL_ALPHA:
+					case GL_LUMINANCE:
+						LoadImageData<Bytes_2>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RG32UI:
+					case GL_RG:
+					case GL_RG_INTEGER:
+					case GL_LUMINANCE_ALPHA:
+						LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RGB32UI:
+					case GL_RGB:
+					case GL_RGB_INTEGER:
+						LoadImageData<UIntRGB>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_RGBA32UI:
+					case GL_RGBA:
+					case GL_RGBA_INTEGER:
+					case GL_BGRA_EXT:
+						LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					case GL_DEPTH_COMPONENT16:
+					case GL_DEPTH_COMPONENT24:
+					case GL_DEPTH_COMPONENT32_OES:
+					case GL_DEPTH_COMPONENT:
+						LoadImageData<D32>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+						break;
+					default: UNREACHABLE(format);
+					}
 					break;
 				case GL_UNSIGNED_INT_24_8_OES:
 					loadD24S8ImageData(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, input, buffer);
 					break;
+				case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+					loadD32FS8ImageData(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, input, buffer);
+					break;
 				default: UNREACHABLE(type);
 				}
 			}
@@ -905,6 +1659,20 @@
 		}
 	}
 
+	void Image::loadD32FS8ImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, const void *input, void *buffer)
+	{
+		LoadImageData<D32F>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
+
+		unsigned char *stencil = reinterpret_cast<unsigned char*>(lockStencil(0, sw::PUBLIC));
+
+		if(stencil)
+		{
+			LoadImageData<S24_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getStencilPitchB(), getHeight(), input, stencil);
+
+			unlockStencil();
+		}
+	}
+
 	void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels)
 	{
 		if(zoffset != 0 || depth != 1)
diff --git a/src/OpenGL/common/Image.hpp b/src/OpenGL/common/Image.hpp
index db24d8b..3b09bc7 100644
--- a/src/OpenGL/common/Image.hpp
+++ b/src/OpenGL/common/Image.hpp
@@ -171,6 +171,7 @@
 	virtual ~Image();

 

 	void loadD24S8ImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, const void *input, void *buffer);

+	void loadD32FS8ImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, const void *input, void *buffer);

 };

 

 #ifdef __ANDROID__