wsi/metal: add support for color spaces

Reviewed-by: Lucas Fryzek <lfryzek@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33779>
This commit is contained in:
Aleksi Sapon 2025-09-26 14:21:45 -04:00 committed by Marge Bot
parent f022754647
commit fd045ac99c
3 changed files with 78 additions and 6 deletions

View file

@ -156,6 +156,19 @@ static const VkFormat available_surface_formats[] = {
VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_FORMAT_A2B10G10R10_UNORM_PACK32,
}; };
static const VkColorSpaceKHR available_surface_color_spaces[] = {
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT,
VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT,
VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT,
VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT,
VK_COLOR_SPACE_BT709_NONLINEAR_EXT,
VK_COLOR_SPACE_BT2020_LINEAR_EXT,
VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT,
VK_COLOR_SPACE_PASS_THROUGH_EXT,
VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT,
};
static void static void
get_sorted_vk_formats(bool force_bgra8_unorm_first, VkFormat *sorted_formats) get_sorted_vk_formats(bool force_bgra8_unorm_first, VkFormat *sorted_formats)
{ {
@ -185,9 +198,11 @@ wsi_metal_surface_get_formats(VkIcdSurfaceBase *icd_surface,
get_sorted_vk_formats(wsi_device->force_bgra8_unorm_first, sorted_formats); get_sorted_vk_formats(wsi_device->force_bgra8_unorm_first, sorted_formats);
for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) { for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) {
vk_outarray_append_typed(VkSurfaceFormatKHR, &out, f) { for (unsigned j = 0; j < ARRAY_SIZE(available_surface_color_spaces); j++) {
f->format = sorted_formats[i]; vk_outarray_append_typed(VkSurfaceFormatKHR, &out, f) {
f->colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; f->format = sorted_formats[i];
f->colorSpace = available_surface_color_spaces[j];
}
} }
} }
@ -388,7 +403,7 @@ wsi_metal_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
VkResult result = wsi_metal_layer_configure(metal_surface->pLayer, VkResult result = wsi_metal_layer_configure(metal_surface->pLayer,
pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
num_images, pCreateInfo->imageFormat, num_images, pCreateInfo->imageFormat, pCreateInfo->imageColorSpace,
opaque_composition, immediate_mode); opaque_composition, immediate_mode);
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
return result; return result;

View file

@ -22,7 +22,7 @@ wsi_metal_layer_size(const CAMetalLayer *metal_layer,
VkResult VkResult
wsi_metal_layer_configure(const CAMetalLayer *metal_layer, wsi_metal_layer_configure(const CAMetalLayer *metal_layer,
uint32_t width, uint32_t height, uint32_t image_count, uint32_t width, uint32_t height, uint32_t image_count,
VkFormat format, VkFormat format, VkColorSpaceKHR color_space,
bool enable_opaque, bool enable_immediate); bool enable_opaque, bool enable_immediate);
CAMetalDrawableBridged * CAMetalDrawableBridged *

View file

@ -48,10 +48,58 @@ get_mtl_pixel_format(VkFormat format, MTLPixelFormat *metal_format)
return VK_SUCCESS; return VK_SUCCESS;
} }
static VkResult
get_cg_color_space(VkColorSpaceKHR color_space, CGColorSpaceRef *cg_color_space)
{
CFStringRef color_space_name;
switch (color_space) {
case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR:
color_space_name = kCGColorSpaceSRGB;
break;
case VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT:
color_space_name = kCGColorSpaceDisplayP3;
break;
case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT:
color_space_name = kCGColorSpaceExtendedLinearSRGB;
break;
case VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT:
color_space_name = kCGColorSpaceLinearDisplayP3;
break;
case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT:
color_space_name = kCGColorSpaceDCIP3;
break;
case VK_COLOR_SPACE_BT709_NONLINEAR_EXT:
color_space_name = kCGColorSpaceITUR_709;
break;
case VK_COLOR_SPACE_BT2020_LINEAR_EXT:
color_space_name = kCGColorSpaceLinearITUR_2020;
break;
case VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT:
color_space_name = kCGColorSpaceAdobeRGB1998;
break;
case VK_COLOR_SPACE_PASS_THROUGH_EXT:
color_space_name = nil;
break;
case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT:
color_space_name = kCGColorSpaceExtendedSRGB;
break;
default:
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
if (color_space_name) {
*cg_color_space = CGColorSpaceCreateWithName(color_space_name);
} else {
*cg_color_space = nil;
}
return VK_SUCCESS;
}
VkResult VkResult
wsi_metal_layer_configure(const CAMetalLayer *metal_layer, wsi_metal_layer_configure(const CAMetalLayer *metal_layer,
uint32_t width, uint32_t height, uint32_t image_count, uint32_t width, uint32_t height, uint32_t image_count,
VkFormat format, VkFormat format, VkColorSpaceKHR color_space,
bool enable_opaque, bool enable_immediate) bool enable_opaque, bool enable_immediate)
{ {
@autoreleasepool { @autoreleasepool {
@ -60,6 +108,11 @@ wsi_metal_layer_configure(const CAMetalLayer *metal_layer,
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
return result; return result;
CGColorSpaceRef cg_color_space;
result = get_cg_color_space(color_space, &cg_color_space);
if (result != VK_SUCCESS)
return result;
if (metal_layer.device == nil) if (metal_layer.device == nil)
metal_layer.device = metal_layer.preferredDevice; metal_layer.device = metal_layer.preferredDevice;
@ -73,6 +126,10 @@ wsi_metal_layer_configure(const CAMetalLayer *metal_layer,
metal_layer.opaque = enable_opaque; metal_layer.opaque = enable_opaque;
metal_layer.displaySyncEnabled = !enable_immediate; metal_layer.displaySyncEnabled = !enable_immediate;
metal_layer.pixelFormat = metal_format; metal_layer.pixelFormat = metal_format;
metal_layer.colorspace = cg_color_space;
/* Needs release: https://github.com/KhronosGroup/MoltenVK/issues/940 */
CGColorSpaceRelease(cg_color_space);
} }
return VK_SUCCESS; return VK_SUCCESS;