Implement R5G6B5 write masking.

Bug 20891368

Change-Id: Ie4e153330c0a422c849953caf02b199df860b8f0
Reviewed-on: https://swiftshader-review.googlesource.com/3256
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/Shader/Constants.cpp b/src/Shader/Constants.cpp
index c9965ff..474842b 100644
--- a/src/Shader/Constants.cpp
+++ b/src/Shader/Constants.cpp
@@ -238,6 +238,19 @@
 			invMaskQ23X[i][1] = ~-(i >> 3 & 1);
 		}
 
+		for(int i = 0; i < 8; i++)
+		{
+			mask565Q[i][0] =
+			mask565Q[i][1] =
+			mask565Q[i][2] =
+			mask565Q[i][3] = (i & 0x1 ? 0x001F : 0) | (i & 0x2 ? 0x07E0 : 0) | (i & 0x4 ? 0xF800 : 0);
+
+			invMask565Q[i][0] =
+			invMask565Q[i][1] =
+			invMask565Q[i][2] =
+			invMask565Q[i][3] = ~mask565Q[i][0];
+		}
+
 		for(int i = 0; i < 4; i++)
 		{
 			maskW01Q[i][0] =  -(i >> 0 & 1);
diff --git a/src/Shader/Constants.hpp b/src/Shader/Constants.hpp
index c556b5e..a7bebb4 100644
--- a/src/Shader/Constants.hpp
+++ b/src/Shader/Constants.hpp
@@ -64,6 +64,8 @@
 		word4 invMaskW01Q[4];

 		dword4 maskD01X[4];

 		dword4 invMaskD01X[4];

+		word4 mask565Q[8];

+		word4 invMask565Q[8];

 

 		unsigned short sRGBtoLinear8_12[256];

 		unsigned short sRGBtoLinear6_12[64];

diff --git a/src/Shader/PixelRoutine.cpp b/src/Shader/PixelRoutine.cpp
index e1a5fb6..dded202 100644
--- a/src/Shader/PixelRoutine.cpp
+++ b/src/Shader/PixelRoutine.cpp
@@ -2871,32 +2871,40 @@
 		case FORMAT_R5G6B5:
 			{
 				Pointer<Byte> buffer = cBuffer + 2 * x;
+				Int value = *Pointer<Int>(buffer);
 
-				//Int value = *Pointer<Int>(buffer);
+				Int c01 = Extract(As<Int2>(current.x), 0);
 
-				if((rgbaWriteMask & 0x00000007) != 0x00000007)
+				if((bgraWriteMask & 0x00000007) != 0x00000007)
 				{
-					UNIMPLEMENTED();
+					Int masked = value;
+					c01 &= *Pointer<Int>(r.constants + OFFSET(Constants,mask565Q[bgraWriteMask & 0x7][0]));
+					masked &= *Pointer<Int>(r.constants + OFFSET(Constants,invMask565Q[bgraWriteMask & 0x7][0]));
+					c01 |= masked;
 				}
 
-				//current.x &= *Pointer<Short4>(r.constants + OFFSET(Constants,maskD01Q) + xMask * 8);
-				//value &= *Pointer<Short4>(r.constants + OFFSET(Constants,invMaskD01Q) + xMask * 8);
-				//current.x |= value;
-				*Pointer<Int>(buffer) = Extract(As<Int2>(current.x), 0);
+				c01 &= *Pointer<Int>(r.constants + OFFSET(Constants,maskW4Q[0][0]) + xMask * 8);
+				value &= *Pointer<Int>(r.constants + OFFSET(Constants,invMaskW4Q[0][0]) + xMask * 8);
+				c01 |= value;
+				*Pointer<Int>(buffer) = c01;
 
 				buffer += *Pointer<Int>(r.data + OFFSET(DrawData,colorPitchB[index]));
+				value = *Pointer<Int>(buffer);
 
-				//value = *Pointer<Short4>(buffer);
+				Int c23 = Extract(As<Int2>(current.x), 1);
 
-				if((rgbaWriteMask & 0x00000007) != 0x00000007)
+				if((bgraWriteMask & 0x00000007) != 0x00000007)
 				{
-					UNIMPLEMENTED();
+					Int masked = value;
+					c23 &= *Pointer<Int>(r.constants + OFFSET(Constants,mask565Q[bgraWriteMask & 0x7][0]));
+					masked &= *Pointer<Int>(r.constants + OFFSET(Constants,invMask565Q[bgraWriteMask & 0x7][0]));
+					c23 |= masked;
 				}
 
-				//current.y &= *Pointer<Short4>(r.constants + OFFSET(Constants,maskD23Q) + xMask * 8);
-				//value &= *Pointer<Short4>(r.constants + OFFSET(Constants,invMaskD23Q) + xMask * 8);
-				//current.y |= value;
-				*Pointer<Int>(buffer) = Extract(As<Int2>(current.x), 1);
+				c23 &= *Pointer<Int>(r.constants + OFFSET(Constants,maskW4Q[0][2]) + xMask * 8);
+				value &= *Pointer<Int>(r.constants + OFFSET(Constants,invMaskW4Q[0][2]) + xMask * 8);
+				c23 |= value;
+				*Pointer<Int>(buffer) = c23;
 			}
 			break;
 		case FORMAT_A8G8R8B8Q: