Fix blitting of various packed formats

Added clamping to zero when going from a signed to an unsigned format
to fix the output when the input contained negative numbers.

Refactored 4444 formats so that they have the same code structure as
other packed formats (like 5551 or 1010102, for example) and fixed an
error for VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, when writeRGBA was
false, the channels were in the wrong order.

Bug: b/202978657
Change-Id: I4216e6f989866cc9b0c1ccbf24d7223ca38a6529
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/58170
Tested-by: Alexis Hétu <sugoi@google.com>
Commit-Queue: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Device/Blitter.cpp b/src/Device/Blitter.cpp
index 226b521..3d74428 100644
--- a/src/Device/Blitter.cpp
+++ b/src/Device/Blitter.cpp
@@ -576,21 +576,25 @@
 		}
 		break;
 	case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
-		if(writeR || writeG || writeB || writeA)
+		if(writeRGBA)
 		{
-			*Pointer<UShort>(element) = (writeR ? ((UShort(RoundInt(Float(c.x))) & UShort(0xF)) << UShort(12)) : (*Pointer<UShort>(element) & UShort(0x000F))) |
-			                            (writeG ? ((UShort(RoundInt(Float(c.y))) & UShort(0xF)) << UShort(8)) : (*Pointer<UShort>(element) & UShort(0x00F0))) |
-			                            (writeB ? ((UShort(RoundInt(Float(c.z))) & UShort(0xF)) << UShort(4)) : (*Pointer<UShort>(element) & UShort(0x0F00))) |
-			                            (writeA ? (UShort(RoundInt(Float(c.w))) & UShort(0xF)) : (*Pointer<UShort>(element) & UShort(0xF000)));
+			*Pointer<UShort>(element) = UShort(PackFields(RoundInt(c) & Int4(0xF), { 12, 8, 4, 0 }));
+		}
+		else
+		{
+			unsigned short mask = (writeA ? 0x000F : 0x0000) |
+			                      (writeB ? 0x00F0 : 0x0000) |
+			                      (writeG ? 0x0F00 : 0x0000) |
+			                      (writeR ? 0xF000 : 0x0000);
+			unsigned short unmask = ~mask;
+			*Pointer<UShort>(element) = (*Pointer<UShort>(element) & UShort(unmask)) |
+			                            (UShort(PackFields(RoundInt(c) & Int4(0xF), { 12, 8, 4, 0 })) & UShort(mask));
 		}
 		break;
 	case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
 		if(writeRGBA)
 		{
-			*Pointer<UShort>(element) = UShort(RoundInt(Float(c.w)) & Int(0xF)) |
-			                            UShort((RoundInt(Float(c.x)) & Int(0xF)) << 4) |
-			                            UShort((RoundInt(Float(c.y)) & Int(0xF)) << 8) |
-			                            UShort((RoundInt(Float(c.z)) & Int(0xF)) << 12);
+			*Pointer<UShort>(element) = UShort(PackFields(RoundInt(c) & Int4(0xF), { 4, 8, 12, 0 }));
 		}
 		else
 		{
@@ -600,20 +604,13 @@
 			                      (writeB ? 0xF000 : 0x0000);
 			unsigned short unmask = ~mask;
 			*Pointer<UShort>(element) = (*Pointer<UShort>(element) & UShort(unmask)) |
-			                            ((UShort(RoundInt(Float(c.w)) & Int(0xF)) |
-			                              UShort((RoundInt(Float(c.x)) & Int(0xF)) << 4) |
-			                              UShort((RoundInt(Float(c.y)) & Int(0xF)) << 8) |
-			                              UShort((RoundInt(Float(c.z)) & Int(0xF)) << 12)) &
-			                             UShort(mask));
+			                            (UShort(PackFields(RoundInt(c) & Int4(0xF), { 4, 8, 12, 0 })) & UShort(mask));
 		}
 		break;
 	case VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT:
 		if(writeRGBA)
 		{
-			*Pointer<UShort>(element) = UShort(RoundInt(Float(c.z)) & Int(0xF)) |
-			                            UShort((RoundInt(Float(c.y)) & Int(0xF)) << 4) |
-			                            UShort((RoundInt(Float(c.x)) & Int(0xF)) << 8) |
-			                            UShort((RoundInt(Float(c.w)) & Int(0xF)) << 12);
+			*Pointer<UShort>(element) = UShort(PackFields(RoundInt(c) & Int4(0xF), { 8, 4, 0, 12 }));
 		}
 		else
 		{
@@ -623,20 +620,13 @@
 			                      (writeA ? 0xF000 : 0x0000);
 			unsigned short unmask = ~mask;
 			*Pointer<UShort>(element) = (*Pointer<UShort>(element) & UShort(unmask)) |
-			                            ((UShort(RoundInt(Float(c.w)) & Int(0xF)) |
-			                              UShort((RoundInt(Float(c.x)) & Int(0xF)) << 4) |
-			                              UShort((RoundInt(Float(c.y)) & Int(0xF)) << 8) |
-			                              UShort((RoundInt(Float(c.z)) & Int(0xF)) << 12)) &
-			                             UShort(mask));
+			                            (UShort(PackFields(RoundInt(c) & Int4(0xF), { 8, 4, 0, 12 })) & UShort(mask));
 		}
 		break;
 	case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT:
 		if(writeRGBA)
 		{
-			*Pointer<UShort>(element) = UShort(RoundInt(Float(c.x)) & Int(0xF)) |
-			                            UShort((RoundInt(Float(c.y)) & Int(0xF)) << 4) |
-			                            UShort((RoundInt(Float(c.z)) & Int(0xF)) << 8) |
-			                            UShort((RoundInt(Float(c.w)) & Int(0xF)) << 12);
+			*Pointer<UShort>(element) = UShort(PackFields(RoundInt(c) & Int4(0xF), { 0, 4, 8, 12 }));
 		}
 		else
 		{
@@ -646,11 +636,7 @@
 			                      (writeA ? 0xF000 : 0x0000);
 			unsigned short unmask = ~mask;
 			*Pointer<UShort>(element) = (*Pointer<UShort>(element) & UShort(unmask)) |
-			                            ((UShort(RoundInt(Float(c.x)) & Int(0xF)) |
-			                              UShort((RoundInt(Float(c.y)) & Int(0xF)) << 4) |
-			                              UShort((RoundInt(Float(c.z)) & Int(0xF)) << 8) |
-			                              UShort((RoundInt(Float(c.w)) & Int(0xF)) << 12)) &
-			                             UShort(mask));
+			                            (UShort(PackFields(RoundInt(c) & Int4(0xF), { 0, 4, 8, 12 })) & UShort(mask));
 		}
 		break;
 	case VK_FORMAT_B8G8R8A8_SRGB:
@@ -1484,6 +1470,12 @@
 		                          state.destFormat.isUnsignedComponent(2) ? 0.0f : -scale.z,
 		                          state.destFormat.isUnsignedComponent(3) ? 0.0f : -scale.w));
 	}
+
+	// TODO(b/203068380): create proper functions to check for signedness
+	if(!state.sourceFormat.isUnsignedComponent(0) && state.destFormat.isUnsignedComponent(0))
+	{
+		value = Max(value, Float4(0.0f));
+	}
 }
 
 Int Blitter::ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes)
@@ -1895,7 +1887,7 @@
 	    (src->getSampleCountFlagBits() > 1) ||
 	    (srcFormat.isSRGBformat() != dstFormat.isSRGBformat());
 
-	State state(src->getFormat(srcAspect), dst->getFormat(dstAspect), src->getSampleCountFlagBits(), dst->getSampleCountFlagBits(),
+	State state(srcFormat, dstFormat, src->getSampleCountFlagBits(), dst->getSampleCountFlagBits(),
 	            Options{ doFilter, allowSRGBConversion });
 	state.clampToEdge = (region.srcOffsets[0].x < 0) ||
 	                    (region.srcOffsets[0].y < 0) ||