Improve color clear precision.

Change-Id: Ib9dadf3d8fee0f63deb10e6754856c0530c928ab
Reviewed-on: https://swiftshader-review.googlesource.com/3995
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/Renderer/Surface.cpp b/src/Renderer/Surface.cpp
index 3a72601..0919066 100644
--- a/src/Renderer/Surface.cpp
+++ b/src/Renderer/Surface.cpp
@@ -2797,7 +2797,7 @@
 		}
 	}
 
-	void Surface::clearColorBuffer(unsigned int colorARGB, unsigned int rgbaMask, int x0, int y0, int width, int height)
+	void Surface::clearColorBuffer(float red, float green, float blue, float alpha, unsigned int rgbaMask, int x0, int y0, int width, int height)
 	{
 		// FIXME: Also clear buffers in other formats?
 
@@ -2837,30 +2837,39 @@
 					case FORMAT_A8R8G8B8:
 				//	case FORMAT_X8G8R8B8Q:   // FIXME
 				//	case FORMAT_A8G8R8B8Q:   // FIXME
-						if(rgbaMask == 0xF || (internal.format == FORMAT_X8R8G8B8 && rgbaMask == 0x7))
 						{
-							memfill4(target, colorARGB, 4 * (x1 - x0));
-						}
-						else
-						{
-							unsigned int bgraMask = (rgbaMask & 0x1 ? 0x00FF0000 : 0) | (rgbaMask & 0x2 ? 0x0000FF00 : 0) | (rgbaMask & 0x4 ? 0x000000FF : 0) | (rgbaMask & 0x8 ? 0xFF000000 : 0);
-							unsigned int invMask = ~bgraMask;
-							unsigned int maskedColor = colorARGB & bgraMask;
-							unsigned int *target32 = (unsigned int*)target;
+							unsigned char r8 = iround(red * 0xFF);
+							unsigned char g8 = iround(green * 0xFF);
+							unsigned char b8 = iround(blue * 0xFF);
+							unsigned char a8 = iround(alpha * 0xFF);
+							unsigned char a8r8g8b8[4] = {b8, g8, r8, a8};
+							unsigned int colorARGB = (unsigned int&)a8r8g8b8;
 
-							for(int x = 0; x < width; x++)
+							if(rgbaMask == 0xF || (internal.format == FORMAT_X8R8G8B8 && rgbaMask == 0x7))
 							{
-								target32[x] = maskedColor | (target32[x] & invMask);
+								memfill4(target, colorARGB, 4 * (x1 - x0));
+							}
+							else
+							{
+								unsigned int bgraMask = (rgbaMask & 0x1 ? 0x00FF0000 : 0) | (rgbaMask & 0x2 ? 0x0000FF00 : 0) | (rgbaMask & 0x4 ? 0x000000FF : 0) | (rgbaMask & 0x8 ? 0xFF000000 : 0);
+								unsigned int invMask = ~bgraMask;
+								unsigned int maskedColor = colorARGB & bgraMask;
+								unsigned int *target32 = (unsigned int*)target;
+
+								for(int x = 0; x < width; x++)
+								{
+									target32[x] = maskedColor | (target32[x] & invMask);
+								}
 							}
 						}
 						break;
 					case FORMAT_X8B8G8R8:
 					case FORMAT_A8B8G8R8:
 						{
-							unsigned char r8 = (colorARGB & 0x00FF0000) >> 16;
-							unsigned char g8 = (colorARGB & 0x0000FF00) >> 8;
-							unsigned char b8 = (colorARGB & 0x000000FF) >> 0;
-							unsigned char a8 = (colorARGB & 0xFF000000) >> 24;
+							unsigned char r8 = iround(red * 0xFF);
+							unsigned char g8 = iround(green * 0xFF);
+							unsigned char b8 = iround(blue * 0xFF);
+							unsigned char a8 = iround(alpha * 0xFF);
 							unsigned char a8b8g8r8[4] = {r8, g8, b8, a8};
 							unsigned int colorABGR = (unsigned int&)a8b8g8r8;
 
@@ -2884,8 +2893,8 @@
 						break;
 					case FORMAT_G8R8:
 						{
-							unsigned char r8 = (colorARGB & 0x00FF0000) >> 16;
-							unsigned char g8 = (colorARGB & 0x0000FF00) >> 8;
+							unsigned char r8 = iround(red * 0xFF);
+							unsigned char g8 = iround(green * 0xFF);
 							unsigned char g8r8[4] = {r8, g8, r8, g8};
 
 							if((rgbaMask & 0x3) == 0x3)
@@ -2908,10 +2917,8 @@
 						break;
 					case FORMAT_G16R16:
 						{
-							unsigned char r8 = (colorARGB & 0x00FF0000) >> 16;
-							unsigned char g8 = (colorARGB & 0x0000FF00) >> 8;
-							unsigned short r16 = (r8 << 8) | r8;
-							unsigned short g16 = (g8 << 8) | g8;
+							unsigned char r16 = iround(red * 0xFFFF);
+							unsigned char g16 = iround(green * 0xFFFF);
 							unsigned short g16r16[2] = {r16, g16};
 
 							if((rgbaMask & 0x3) == 0x3)
@@ -2934,14 +2941,10 @@
 						break;
 					case FORMAT_A16B16G16R16:
 						{
-							unsigned char r8 = (colorARGB & 0x00FF0000) >> 16;
-							unsigned char g8 = (colorARGB & 0x0000FF00) >> 8;
-							unsigned char b8 = (colorARGB & 0x000000FF) >> 0;
-							unsigned char a8 = (colorARGB & 0xFF000000) >> 24;
-							unsigned short r16 = (r8 << 8) | r8;
-							unsigned short g16 = (g8 << 8) | g8;
-							unsigned short b16 = (b8 << 8) | b8;
-							unsigned short a16 = (a8 << 8) | a8;
+							unsigned char r16 = iround(red * 0xFFFF);
+							unsigned char g16 = iround(green * 0xFFFF);
+							unsigned char b16 = iround(blue * 0xFFFF);
+							unsigned char a16 = iround(alpha * 0xFFFF);
 
 							if(rgbaMask == 0xF)
 							{
@@ -2965,63 +2968,52 @@
 					case FORMAT_R32F:
 						if(rgbaMask & 0x1)
 						{
-							float r32f = (float)(colorARGB & 0x00FF0000) / 0x00FF0000;
-
 							for(int x = 0; x < width; x++)
 							{
-								((float*)target)[x] = r32f;
+								((float*)target)[x] = red;
 							}
 						}
 						break;
 					case FORMAT_G32R32F:
+						if((rgbaMask & 0x3) == 0x3)
 						{
-							float r32f = (float)(colorARGB & 0x00FF0000) / 0x00FF0000;
-							float g32f = (float)(colorARGB & 0x0000FF00) / 0x0000FF00;
-
-							if((rgbaMask & 0x3) == 0x3)
+							for(int x = 0; x < width; x++)
 							{
-								for(int x = 0; x < width; x++)
-								{
-									((float*)target)[2 * x + 0] = r32f;
-									((float*)target)[2 * x + 1] = g32f;
-								}
+								((float*)target)[2 * x + 0] = red;
+								((float*)target)[2 * x + 1] = green;
 							}
-							else
-							{
-								if(rgbaMask & 0x1) for(int x = 0; x < width; x++) ((float*)target)[2 * x + 0] = r32f;
-								if(rgbaMask & 0x2) for(int x = 0; x < width; x++) ((float*)target)[2 * x + 1] = g32f;
-							}
+						}
+						else
+						{
+							if(rgbaMask & 0x1) for(int x = 0; x < width; x++) ((float*)target)[2 * x + 0] = red;
+							if(rgbaMask & 0x2) for(int x = 0; x < width; x++) ((float*)target)[2 * x + 1] = green;
 						}
 						break;
 					case FORMAT_A32B32G32R32F:
+						if(rgbaMask == 0xF)
 						{
-							float r32f = (float)(colorARGB & 0x00FF0000) / 0x00FF0000;
-							float g32f = (float)(colorARGB & 0x0000FF00) / 0x0000FF00;
-							float b32f = (float)(colorARGB & 0x000000FF) / 0x000000FF;
-							float a32f = (float)(colorARGB & 0xFF000000) / 0xFF000000;
-
-							if(rgbaMask == 0xF)
+							for(int x = 0; x < width; x++)
 							{
-								for(int x = 0; x < width; x++)
-								{
-									((float*)target)[4 * x + 0] = r32f;
-									((float*)target)[4 * x + 1] = g32f;
-									((float*)target)[4 * x + 2] = b32f;
-									((float*)target)[4 * x + 3] = a32f;
-								}
+								((float*)target)[4 * x + 0] = red;
+								((float*)target)[4 * x + 1] = green;
+								((float*)target)[4 * x + 2] = blue;
+								((float*)target)[4 * x + 3] = alpha;
 							}
-							else
-							{
-								if(rgbaMask & 0x1) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 0] = r32f;
-								if(rgbaMask & 0x2) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 1] = g32f;
-								if(rgbaMask & 0x4) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 2] = b32f;
-								if(rgbaMask & 0x8) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 3] = a32f;
-							}
+						}
+						else
+						{
+							if(rgbaMask & 0x1) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 0] = red;
+							if(rgbaMask & 0x2) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 1] = green;
+							if(rgbaMask & 0x4) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 2] = blue;
+							if(rgbaMask & 0x8) for(int x = 0; x < width; x++) ((float*)target)[4 * x + 3] = alpha;
 						}
 						break;
 					case FORMAT_R5G6B5:
 						{
-							unsigned int r5g6b5 = ((colorARGB >> 8) & 0xF800) | ((colorARGB >> 5) & 0x07E0) | ((colorARGB >> 3) & 0x001F);
+							unsigned int r5 = iround(red * 0x1F);
+							unsigned int g6 = iround(green * 0x3F);
+							unsigned int b5 = iround(blue * 0x1F);
+							unsigned int r5g6b5 = (r5 << 11) | (g6 << 5) | b5;
 
 							if((rgbaMask & 0x7) == 0x7)
 							{