diff --git a/src/vulkan/wsi/wsi_common_metal.c b/src/vulkan/wsi/wsi_common_metal.c index 430fec0a891..4604c5b10d5 100644 --- a/src/vulkan/wsi/wsi_common_metal.c +++ b/src/vulkan/wsi/wsi_common_metal.c @@ -156,6 +156,19 @@ static const VkFormat available_surface_formats[] = { 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 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); for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) { - vk_outarray_append_typed(VkSurfaceFormatKHR, &out, f) { - f->format = sorted_formats[i]; - f->colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; + for (unsigned j = 0; j < ARRAY_SIZE(available_surface_color_spaces); j++) { + vk_outarray_append_typed(VkSurfaceFormatKHR, &out, f) { + 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, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, - num_images, pCreateInfo->imageFormat, + num_images, pCreateInfo->imageFormat, pCreateInfo->imageColorSpace, opaque_composition, immediate_mode); if (result != VK_SUCCESS) return result; diff --git a/src/vulkan/wsi/wsi_common_metal_layer.h b/src/vulkan/wsi/wsi_common_metal_layer.h index 16849486aa8..7586ea408cf 100644 --- a/src/vulkan/wsi/wsi_common_metal_layer.h +++ b/src/vulkan/wsi/wsi_common_metal_layer.h @@ -22,7 +22,7 @@ wsi_metal_layer_size(const CAMetalLayer *metal_layer, VkResult wsi_metal_layer_configure(const CAMetalLayer *metal_layer, uint32_t width, uint32_t height, uint32_t image_count, - VkFormat format, + VkFormat format, VkColorSpaceKHR color_space, bool enable_opaque, bool enable_immediate); CAMetalDrawableBridged * diff --git a/src/vulkan/wsi/wsi_common_metal_layer.m b/src/vulkan/wsi/wsi_common_metal_layer.m index 0cb9fd875a5..45fd7964f89 100644 --- a/src/vulkan/wsi/wsi_common_metal_layer.m +++ b/src/vulkan/wsi/wsi_common_metal_layer.m @@ -48,10 +48,58 @@ get_mtl_pixel_format(VkFormat format, MTLPixelFormat *metal_format) 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 wsi_metal_layer_configure(const CAMetalLayer *metal_layer, uint32_t width, uint32_t height, uint32_t image_count, - VkFormat format, + VkFormat format, VkColorSpaceKHR color_space, bool enable_opaque, bool enable_immediate) { @autoreleasepool { @@ -60,6 +108,11 @@ wsi_metal_layer_configure(const CAMetalLayer *metal_layer, if (result != VK_SUCCESS) 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) 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.displaySyncEnabled = !enable_immediate; 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;