Integer types support in Blitter

The blitter now supports integer types. This means:
- It supports conversions to/from integer types from/to
  other already supported types.
- It supports integer to integer conversions without going
  to an intermediate float format.

Also added a Blitter::GetScale() function to avoid having
2 instances of the same switch statement in the code and
added the read/write utility functions. The final Blitter
code is not longer peppered with switch statements and is,
hopefully, easier to read that way.

Change-Id: I80de519aaaa768f8cedd98f97dc4414dda75bf54
Reviewed-on: https://swiftshader-review.googlesource.com/4113
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/Renderer/Surface.cpp b/src/Renderer/Surface.cpp
index b5f244d..61fc9bc 100644
--- a/src/Renderer/Surface.cpp
+++ b/src/Renderer/Surface.cpp
@@ -2290,11 +2290,30 @@
 		{
 		case FORMAT_R5G6B5:
 		case FORMAT_X8R8G8B8:
+		case FORMAT_X8B8G8R8I:
 		case FORMAT_X8B8G8R8:
 		case FORMAT_A8R8G8B8:
+		case FORMAT_A8B8G8R8I:
+		case FORMAT_R8UI:
+		case FORMAT_G8R8UI:
+		case FORMAT_X8B8G8R8UI:
+		case FORMAT_A8B8G8R8UI:
 		case FORMAT_A8B8G8R8:
+		case FORMAT_G8R8I:
 		case FORMAT_G8R8:
+		case FORMAT_R8I_SNORM:
+		case FORMAT_G8R8I_SNORM:
+		case FORMAT_X8B8G8R8I_SNORM:
+		case FORMAT_A8B8G8R8I_SNORM:
+		case FORMAT_R16I:
+		case FORMAT_R16UI:
+		case FORMAT_G16R16I:
+		case FORMAT_G16R16UI:
 		case FORMAT_G16R16:
+		case FORMAT_X16B16G16R16I:
+		case FORMAT_X16B16G16R16UI:
+		case FORMAT_A16B16G16R16I:
+		case FORMAT_A16B16G16R16UI:
 		case FORMAT_A16B16G16R16:
 		case FORMAT_V8U8:
 		case FORMAT_Q8W8V8U8:
@@ -2303,6 +2322,7 @@
 		case FORMAT_A16W16V16U16:
 		case FORMAT_Q16W16V16U16:
 		case FORMAT_A8:
+		case FORMAT_R8I:
 		case FORMAT_R8:
 		case FORMAT_L8:
 		case FORMAT_L16:
@@ -2310,6 +2330,14 @@
 		case FORMAT_YV12_BT601:
 		case FORMAT_YV12_BT709:
 		case FORMAT_YV12_JFIF:
+		case FORMAT_R32I:
+		case FORMAT_R32UI:
+		case FORMAT_G32R32I:
+		case FORMAT_G32R32UI:
+		case FORMAT_X32B32G32R32I:
+		case FORMAT_X32B32G32R32UI:
+		case FORMAT_A32B32G32R32I:
+		case FORMAT_A32B32G32R32UI:
 			return false;
 		case FORMAT_R32F:
 		case FORMAT_G32R32F:
@@ -2512,6 +2540,40 @@
 		}
 	}
 
+	bool Surface::isNonNormalizedInteger(Format format)
+	{
+		switch(format)
+		{
+		case FORMAT_A8B8G8R8I:
+		case FORMAT_X8B8G8R8I:
+		case FORMAT_G8R8I:
+		case FORMAT_R8I:
+		case FORMAT_A8B8G8R8UI:
+		case FORMAT_X8B8G8R8UI:
+		case FORMAT_G8R8UI:
+		case FORMAT_R8UI:
+		case FORMAT_A16B16G16R16I:
+		case FORMAT_X16B16G16R16I:
+		case FORMAT_G16R16I:
+		case FORMAT_R16I:
+		case FORMAT_A16B16G16R16UI:
+		case FORMAT_X16B16G16R16UI:
+		case FORMAT_G16R16UI:
+		case FORMAT_R16UI:
+		case FORMAT_A32B32G32R32I:
+		case FORMAT_X32B32G32R32I:
+		case FORMAT_G32R32I:
+		case FORMAT_R32I:
+		case FORMAT_A32B32G32R32UI:
+		case FORMAT_X32B32G32R32UI:
+		case FORMAT_G32R32UI:
+		case FORMAT_R32UI:
+			return true;
+		default:
+			return false;
+		}
+	}
+
 	int Surface::componentCount(Format format)
 	{
 		switch(format)
@@ -3300,48 +3362,42 @@
 		external.write(x, y, color);
 	}
 
-	Color<float> Surface::readInternal(int x, int y, int z) const
+	void Surface::copyInternal(const Surface* source, int x, int y, float srcX, float srcY, bool filter)
 	{
-		ASSERT(internal.lock != LOCK_UNLOCKED);
+		ASSERT(internal.lock != LOCK_UNLOCKED && source && source->internal.lock != LOCK_UNLOCKED);
 
-		return internal.read(x, y, z);
-	}
+		sw::Color<float> color;
 
-	Color<float> Surface::readInternal(int x, int y) const
-	{
-		ASSERT(internal.lock != LOCK_UNLOCKED);
-
-		return internal.read(x, y);
-	}
-
-	Color<float> Surface::sampleInternal(float x, float y, float z) const
-	{
-		ASSERT(internal.lock != LOCK_UNLOCKED);
-
-		return internal.sample(x, y, z);
-	}
-
-	Color<float> Surface::sampleInternal(float x, float y) const
-	{
-		ASSERT(internal.lock != LOCK_UNLOCKED);
-
-		return internal.sample(x, y);
-	}
-
-	void Surface::writeInternal(int x, int y, int z, const Color<float> &color)
-	{
-		ASSERT(internal.lock != LOCK_UNLOCKED);
-
-		internal.write(x, y, z, color);
-	}
-
-	void Surface::writeInternal(int x, int y, const Color<float> &color)
-	{
-		ASSERT(internal.lock != LOCK_UNLOCKED);
+		if(!filter)
+		{
+			color = source->internal.read((int)srcX, (int)srcY);
+		}
+		else   // Bilinear filtering
+		{
+			color = source->internal.sample(srcX, srcY);
+		}
 
 		internal.write(x, y, color);
 	}
 
+	void Surface::copyInternal(const Surface* source, int x, int y, int z, float srcX, float srcY, float srcZ, bool filter)
+	{
+		ASSERT(internal.lock != LOCK_UNLOCKED && source && source->internal.lock != LOCK_UNLOCKED);
+
+		sw::Color<float> color;
+
+		if(!filter)
+		{
+			color = source->internal.read((int)srcX, (int)srcY, int(srcZ));
+		}
+		else   // Bilinear filtering
+		{
+			color = source->internal.sample(srcX, srcY, srcZ);
+		}
+
+		internal.write(x, y, z, color);
+	}
+
 	bool Surface::hasStencil() const
 	{
 		return isStencil(external.format);