Enable R5G6B5 as an internal format.

Bug 20891368

Change-Id: Iea526eebe65616079578563126a6958d87647eb1
Reviewed-on: https://swiftshader-review.googlesource.com/3255
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 fd9ab52..a0f7ac6 100644
--- a/src/OpenGL/common/Image.cpp
+++ b/src/OpenGL/common/Image.cpp
@@ -186,17 +186,7 @@
 	template<>
 	void LoadImageRow<RGB565>(const unsigned char *source, unsigned char *dest, GLint xoffset, GLsizei width)
 	{
-		const unsigned short *source565 = reinterpret_cast<const unsigned short*>(source);
-		unsigned char *destB = dest + xoffset * 4;
-
-		for(int x = 0; x < width; x++)
-		{
-			unsigned short rgba = source565[x];
-			destB[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
-			destB[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
-			destB[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
-			destB[4 * x + 3] = 0xFF;
-		}
+		memcpy(dest + xoffset * 2, source, width * 2);
 	}
 
 	template<>
@@ -587,7 +577,7 @@
 		}
 		else if(type == GL_UNSIGNED_SHORT_5_6_5)
 		{
-			return sw::FORMAT_X8R8G8B8;
+			return sw::FORMAT_R5G6B5;
 		}
 		else UNREACHABLE(type);
 
diff --git a/src/OpenGL/libGL/Image.cpp b/src/OpenGL/libGL/Image.cpp
index b01712a..c444434 100644
--- a/src/OpenGL/libGL/Image.cpp
+++ b/src/OpenGL/libGL/Image.cpp
@@ -214,7 +214,7 @@
 		}
 		else if(type == GL_UNSIGNED_SHORT_5_6_5)
 		{
-			return sw::FORMAT_X8R8G8B8;
+			return sw::FORMAT_R5G6B5;
 		}
         else if(type == GL_UNSIGNED_INT_8_8_8_8_REV)
         {
@@ -504,16 +504,9 @@
 		for(int y = 0; y < height; y++)
 		{
 			const unsigned short *source = reinterpret_cast<const unsigned short*>(static_cast<const unsigned char*>(input) + y * inputPitch);
-			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 4;
+			unsigned char *dest = static_cast<unsigned char*>(buffer) + (y + yoffset) * getPitch() + xoffset * 2;
 			
-			for(int x = 0; x < width; x++)
-			{
-				unsigned short rgba = source[x];
-				dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2);
-				dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9);
-				dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13);
-				dest[4 * x + 3] = 0xFF;
-			}
+			memcpy(dest, source, width * 2);
 		}
 	}
 
diff --git a/src/Renderer/Surface.cpp b/src/Renderer/Surface.cpp
index 79e4c0b..b84ba1c 100644
--- a/src/Renderer/Surface.cpp
+++ b/src/Renderer/Surface.cpp
@@ -1416,7 +1416,6 @@
 			switch(source.format)
 			{
 			case FORMAT_R8G8B8:		decodeR8G8B8(destination, source);		break;   // FIXME: Check destination format
-			case FORMAT_R5G6B5:		decodeR5G6B5(destination, source);		break;   // FIXME: Check destination format
 			case FORMAT_X1R5G5B5:	decodeX1R5G5B5(destination, source);	break;   // FIXME: Check destination format
 			case FORMAT_A1R5G5B5:	decodeA1R5G5B5(destination, source);	break;   // FIXME: Check destination format
 			case FORMAT_X4R4G4B4:	decodeX4R4G4B4(destination, source);	break;   // FIXME: Check destination format
@@ -1554,44 +1553,6 @@
 		}
 	}
 
-	void Surface::decodeR5G6B5(Buffer &destination, const Buffer &source)
-	{
-		unsigned char *sourceSlice = (unsigned char*)source.buffer;
-		unsigned char *destinationSlice = (unsigned char*)destination.buffer;
-
-		for(int z = 0; z < destination.depth && z < source.depth; z++)
-		{
-			unsigned char *sourceRow = sourceSlice;
-			unsigned char *destinationRow = destinationSlice;
-
-			for(int y = 0; y < destination.height && y < source.height; y++)
-			{
-				unsigned char *sourceElement = sourceRow;
-				unsigned char *destinationElement = destinationRow;
-
-				for(int x = 0; x < destination.width && x < source.width; x++)
-				{
-					unsigned int rgb = *(unsigned short*)sourceElement;
-						
-					unsigned int r = (((rgb & 0xF800) * 67385 + 0x800000) >> 8) & 0x00FF0000;
-					unsigned int g = (((rgb & 0x07E0) * 8289  + 0x8000) >> 8) & 0x0000FF00;
-					unsigned int b = (((rgb & 0x001F) * 2106  + 0x80) >> 8);
-
-					*(unsigned int*)destinationElement = 0xFF000000 | r | g | b;
-
-					sourceElement += source.bytes;
-					destinationElement += destination.bytes;
-				}
-
-				sourceRow += source.pitchB;
-				destinationRow += destination.pitchB;
-			}
-
-			sourceSlice += source.sliceB;
-			destinationSlice += destination.sliceB;
-		}
-	}
-
 	void Surface::decodeX1R5G5B5(Buffer &destination, const Buffer &source)
 	{
 		unsigned char *sourceSlice = (unsigned char*)source.buffer;
@@ -2460,6 +2421,7 @@
 	{
 		switch(format)
 		{
+		case FORMAT_R5G6B5:
 		case FORMAT_X8R8G8B8:
 		case FORMAT_X8B8G8R8:
 		case FORMAT_A8R8G8B8:
@@ -2507,6 +2469,7 @@
 		switch(format)
 		{
 		case FORMAT_NULL:
+		case FORMAT_R5G6B5:
 		case FORMAT_X8R8G8B8:
 		case FORMAT_X8B8G8R8:
 		case FORMAT_A8R8G8B8:
@@ -2686,30 +2649,31 @@
 	{
 		switch(format)
 		{
-		case FORMAT_X8R8G8B8:		return 3;
-		case FORMAT_X8B8G8R8:		return 3;
-		case FORMAT_A8R8G8B8:		return 4;
-		case FORMAT_A8B8G8R8:		return 4;
-		case FORMAT_G8R8:			return 2;
-		case FORMAT_G16R16:			return 2;
-		case FORMAT_A16B16G16R16:	return 4;
-		case FORMAT_V8U8:			return 2;
-		case FORMAT_Q8W8V8U8:		return 4;
-		case FORMAT_X8L8V8U8:		return 3;
-		case FORMAT_V16U16:			return 2;
-		case FORMAT_A16W16V16U16:	return 4;
-		case FORMAT_Q16W16V16U16:	return 4;
-		case FORMAT_R32F:			return 1;
-		case FORMAT_G32R32F:		return 2;
-		case FORMAT_A32B32G32R32F:	return 4;
-		case FORMAT_D32F_LOCKABLE:	return 1;
-		case FORMAT_D32FS8_TEXTURE:	return 1;
-		case FORMAT_D32FS8_SHADOW:	return 1;
-		case FORMAT_A8:				return 1;
-		case FORMAT_R8:				return 1;
-		case FORMAT_L8:				return 1;
-		case FORMAT_L16:			return 1;
-		case FORMAT_A8L8:			return 2;
+		case FORMAT_R5G6B5:         return 3;
+		case FORMAT_X8R8G8B8:       return 3;
+		case FORMAT_X8B8G8R8:       return 3;
+		case FORMAT_A8R8G8B8:       return 4;
+		case FORMAT_A8B8G8R8:       return 4;
+		case FORMAT_G8R8:           return 2;
+		case FORMAT_G16R16:         return 2;
+		case FORMAT_A16B16G16R16:   return 4;
+		case FORMAT_V8U8:           return 2;
+		case FORMAT_Q8W8V8U8:       return 4;
+		case FORMAT_X8L8V8U8:       return 3;
+		case FORMAT_V16U16:         return 2;
+		case FORMAT_A16W16V16U16:   return 4;
+		case FORMAT_Q16W16V16U16:   return 4;
+		case FORMAT_R32F:           return 1;
+		case FORMAT_G32R32F:        return 2;
+		case FORMAT_A32B32G32R32F:  return 4;
+		case FORMAT_D32F_LOCKABLE:  return 1;
+		case FORMAT_D32FS8_TEXTURE: return 1;
+		case FORMAT_D32FS8_SHADOW:  return 1;
+		case FORMAT_A8:             return 1;
+		case FORMAT_R8:             return 1;
+		case FORMAT_L8:             return 1;
+		case FORMAT_L16:            return 1;
+		case FORMAT_A8L8:           return 2;
 		case FORMAT_YV12_BT601:     return 3;
 		case FORMAT_YV12_BT709:     return 3;
 		case FORMAT_YV12_JFIF:      return 3;
@@ -3593,8 +3557,9 @@
 		case FORMAT_R4G4B4A4:
 		case FORMAT_A8B8G8R8:
 			return FORMAT_A8B8G8R8;
-		case FORMAT_R3G3B2:
 		case FORMAT_R5G6B5:
+			return FORMAT_R5G6B5;
+		case FORMAT_R3G3B2:
 		case FORMAT_R8G8B8:
 		case FORMAT_X4R4G4B4:
 		case FORMAT_X1R5G5B5:
diff --git a/src/Renderer/Surface.hpp b/src/Renderer/Surface.hpp
index 9860b6d..23a392d 100644
--- a/src/Renderer/Surface.hpp
+++ b/src/Renderer/Surface.hpp
@@ -388,7 +388,6 @@
 		};

 

 		static void decodeR8G8B8(Buffer &destination, const Buffer &source);

-		static void decodeR5G6B5(Buffer &destination, const Buffer &source);

 		static void decodeX1R5G5B5(Buffer &destination, const Buffer &source);

 		static void decodeA1R5G5B5(Buffer &destination, const Buffer &source);

 		static void decodeX4R4G4B4(Buffer &destination, const Buffer &source);