Vulkan: Support AHARDWAREBUFFER_FORMAT_YCbCr_P210 plane pitch and offset

Add AHARDWAREBUFFER_FORMAT_YCbCr_P210 format cases in external android
memory offset and row pitch queries to prevent Plane 1 luma aliasing.

Bug: 525088727
Test: atest MctsMediaV2TestCases && atest CtsGraphicsTestCases
Flag: com.google.cf.config.gralloc_p010_p210_updates
TAG=agy

Change-Id: I624c5dfae09008a4fee80f92797bb4b0cab8d4d0
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/77468
Reviewed-by: Jason Macnak <natsu@google.com>
Tested-by: Jason Macnak <natsu@google.com>
Commit-Queue: Jason Macnak <natsu@google.com>
Reviewed-by: Shahbaz Youssefi <syoussefi@google.com>
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index 855ac22..6c22366 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -693,6 +693,7 @@
 			chromaBits = 8;
 			break;
 		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 			lumaBits = 10;
 			chromaBits = 10;
 			break;
@@ -2001,6 +2002,7 @@
 		}
 		break;
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 		{
 			Y = Insert(Y, Pointer<UShort>(lumaBuffer)[index[0]], 0);
 			Y = Insert(Y, Pointer<UShort>(lumaBuffer)[index[1]], 1);
@@ -2056,6 +2058,7 @@
 		}
 		break;
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 		{
 			UInt4 UV;
 			UV = Insert(UV, Pointer<UInt>(bufferU)[index[0]], 0);
@@ -2761,6 +2764,7 @@
 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 		return sw::float4(0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF);
 	default:
 		break;
diff --git a/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp b/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp
index b7cdd0d..01813c6 100644
--- a/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp
+++ b/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp
@@ -57,6 +57,8 @@
 		return AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
 		return AHARDWAREBUFFER_FORMAT_YCbCr_P010;
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
+		return AHARDWAREBUFFER_FORMAT_YCbCr_P210;
 	case VK_FORMAT_B8G8R8A8_UNORM:
 		return AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM;
 	default:
@@ -390,6 +392,8 @@
 		return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
 	case AHARDWAREBUFFER_FORMAT_YCbCr_P010:
 		return VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
+	case AHARDWAREBUFFER_FORMAT_YCbCr_P210:
+		return VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16;
 	case AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM:
 		return VK_FORMAT_B8G8R8A8_UNORM;
 	default:
@@ -414,7 +418,8 @@
 	// YUV formats are not listed in the AHardwareBuffer Format Equivalence table in the Vulkan spec.
 	// Clients must use VkExternalFormatANDROID.
 	if(pFormat->format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM ||
-	   pFormat->format == VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16)
+	   pFormat->format == VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 ||
+	   pFormat->format == VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16)
 	{
 		pFormat->format = VK_FORMAT_UNDEFINED;
 	}
@@ -486,6 +491,7 @@
 	case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
 	case AHARDWAREBUFFER_FORMAT_YV12:
 	case AHARDWAREBUFFER_FORMAT_YCbCr_P010:
+	case AHARDWAREBUFFER_FORMAT_YCbCr_P210:
 		switch(aspect)
 		{
 		case VK_IMAGE_ASPECT_PLANE_0_BIT:
@@ -515,6 +521,7 @@
 	case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
 	case AHARDWAREBUFFER_FORMAT_YV12:
 	case AHARDWAREBUFFER_FORMAT_YCbCr_P010:
+	case AHARDWAREBUFFER_FORMAT_YCbCr_P210:
 		switch(aspect)
 		{
 		case VK_IMAGE_ASPECT_PLANE_0_BIT:
diff --git a/src/Vulkan/VkFormat.cpp b/src/Vulkan/VkFormat.cpp
index 61a1667..c89f9ff 100644
--- a/src/Vulkan/VkFormat.cpp
+++ b/src/Vulkan/VkFormat.cpp
@@ -48,6 +48,7 @@
 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 		return true;
 	default:
 		// sRGB encoded formats are also unsigned normalized.
@@ -159,6 +160,7 @@
 		break;
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 		aspects = VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT;
 		break;
 	default:
@@ -221,6 +223,7 @@
 		case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 			return VK_FORMAT_R8_UNORM;
 		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 			return VK_FORMAT_R10X6_UNORM_PACK16;
 		// 8-bit compatibility class
 		// Compatible format for VK_FORMAT_R8_UNORM
@@ -250,6 +253,7 @@
 		case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 			return VK_FORMAT_R8G8_UNORM;
 		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 			return VK_FORMAT_R10X6G10X6_UNORM_2PACK16;
 		// 8-bit compatibility class
 		// Compatible format for VK_FORMAT_R8_UNORM
@@ -532,6 +536,7 @@
 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 		return false;
 	case VK_FORMAT_R16_SFLOAT:
 	case VK_FORMAT_R16G16_SFLOAT:
@@ -564,6 +569,7 @@
 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 		return true;
 	default:
 		return false;
@@ -1663,6 +1669,7 @@
 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 	case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
 	case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
 	case VK_FORMAT_BC6H_UFLOAT_BLOCK:
@@ -1929,6 +1936,7 @@
 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 		return false;
 	case VK_FORMAT_R8_SNORM:
 	case VK_FORMAT_R8_USCALED:
@@ -2180,6 +2188,7 @@
 		// TODO: ASSERT to ensure this is only called per-aspect?
 		return 1;  // Y plane only
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 		// TODO: ASSERT to ensure this is only called per-aspect?
 		return 2;  // Y plane only
 	default:
@@ -2260,6 +2269,7 @@
 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 		return sw::align<16>(width);  // Y plane only  // TODO: ASSERT to ensure this is only called per-aspect?
 	default:
 		return bytes() * width;
@@ -2334,6 +2344,8 @@
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
 		// "Images in this format must be defined with a width and height that is a multiple of two."
 		return pitchB(width, border) * (height + height / 2);  // U and V planes are 1/4 size of Y plane.
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
+		return pitchB(width, border) * height * 2;
 	default:
 		return pitchB(width, border) * height;  // Pitch computed per row
 	}
@@ -2752,6 +2764,7 @@
 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
 	case VK_FORMAT_A2B10G10R10_UINT_PACK32:
 	case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
@@ -2817,6 +2830,7 @@
 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
 	case VK_FORMAT_A2B10G10R10_UINT_PACK32:
 	case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
@@ -2908,6 +2922,7 @@
 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 	case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
 	case VK_FORMAT_A2B10G10R10_UINT_PACK32:
 	case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
@@ -2997,6 +3012,7 @@
 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 	case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
 	case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
 		return component < 3;
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index 6e0a0e5..b18f8ee 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -819,6 +819,10 @@
 			mipLevelExtent.width /= 2;
 			mipLevelExtent.height /= 2;
 			break;
+		case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
+			ASSERT(mipLevelExtent.width % 2 == 0);
+			mipLevelExtent.width /= 2;
+			break;
 		default:
 			UNSUPPORTED("format %d", int(format));
 		}
@@ -920,6 +924,7 @@
 		// Fall through to 2PLANE case:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 		if(aspect == VK_IMAGE_ASPECT_PLANE_1_BIT)
 		{
 			return getStorageSize(VK_IMAGE_ASPECT_PLANE_0_BIT);
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index acd5909..21dbcb1 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -2189,6 +2189,7 @@
 	case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
 	case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
 	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+	case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
 		pFormatProperties->optimalTilingFeatures |=
 		    VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
 		    VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |