SDL: Use the texture colorspace instead of the buffer parameters on Android

From 7a0356155a2131ca7dcf67f12afcd88a8c241e2d Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 11 Sep 2026 22:25:02 -0700
Subject: [PATCH] Use the texture colorspace instead of the buffer parameters
 on Android

The buffer parameters aren't necessarily correct, due to bugs or missing metadata, so we'll use the texture colorspace as a guide for YUV conversion unless it's specifically set to SDL_COLORSPACE_UNKNOWN.
---
 src/render/vulkan/SDL_render_vulkan.c | 45 +++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/src/render/vulkan/SDL_render_vulkan.c b/src/render/vulkan/SDL_render_vulkan.c
index ded4db231c328..392a31d45c23a 100644
--- a/src/render/vulkan/SDL_render_vulkan.c
+++ b/src/render/vulkan/SDL_render_vulkan.c
@@ -3012,6 +3012,51 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
             samplerYcbcrConversionCreateInfo->yChromaOffset = formatProperties->suggestedYChromaOffset;
             samplerYcbcrConversionCreateInfo->chromaFilter = chromaFilter;
 
+            if (texture->colorspace != SDL_COLORSPACE_UNKNOWN) {
+                switch (SDL_COLORSPACEMATRIX(texture->colorspace)) {
+                case SDL_MATRIX_COEFFICIENTS_BT470BG:
+                case SDL_MATRIX_COEFFICIENTS_BT601:
+                    samplerYcbcrConversionCreateInfo->ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR;
+                    break;
+                case SDL_MATRIX_COEFFICIENTS_BT709:
+                    samplerYcbcrConversionCreateInfo->ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR;
+                    break;
+                case SDL_MATRIX_COEFFICIENTS_BT2020_NCL:
+                    samplerYcbcrConversionCreateInfo->ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR;
+                    break;
+                default:
+                    break;
+                }
+
+                switch (SDL_COLORSPACERANGE(texture->colorspace)) {
+                case SDL_COLOR_RANGE_LIMITED:
+                    samplerYcbcrConversionCreateInfo->ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR;
+                    break;
+                case SDL_COLOR_RANGE_FULL:
+                    samplerYcbcrConversionCreateInfo->ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR;
+                    break;
+                default:
+                    break;
+                }
+
+                switch (SDL_COLORSPACECHROMA(texture->colorspace)) {
+                case SDL_CHROMA_LOCATION_LEFT:
+                    samplerYcbcrConversionCreateInfo->xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN_KHR;
+                    samplerYcbcrConversionCreateInfo->yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT_KHR;
+                    break;
+                case SDL_CHROMA_LOCATION_TOPLEFT:
+                    samplerYcbcrConversionCreateInfo->xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN_KHR;
+                    samplerYcbcrConversionCreateInfo->yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN_KHR;
+                    break;
+                case SDL_CHROMA_LOCATION_CENTER:
+                    samplerYcbcrConversionCreateInfo->xChromaOffset = VK_CHROMA_LOCATION_MIDPOINT_KHR;
+                    samplerYcbcrConversionCreateInfo->yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT_KHR;
+                    break;
+                default:
+                    break;
+                }
+            }
+
             textureData->yuvPipeline = VULKAN_GetYUVPipeline(rendererData, &createInfo);
             if (!textureData->yuvPipeline) {
                 return false;