From fbdd6fedb4af31db2f4dc0333751f8fd7779a841 Mon Sep 17 00:00:00 2001
From: Xaver Hugl <xaver.hugl@kde.org>
Date: Tue, 5 Nov 2024 19:17:28 +0100
Subject: [PATCH 3/4] vulkan/wsi: implement support for VK_EXT_hdr_metadata on
 Wayland

Signed-off-by: Xaver Hugl <xaver.hugl@kde.org>
Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Sebastian Wick <sebastian.wick@redhat.com>
Acked-by: Daniel Stone <daniels@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32038>
---
 src/amd/vulkan/radv_physical_device.c       |   1 +
 src/asahi/vulkan/hk_physical_device.c       |   1 +
 src/freedreno/vulkan/tu_device.cc           |   1 +
 src/gallium/frontends/lavapipe/lvp_device.c |   1 +
 src/intel/vulkan/anv_physical_device.c      |   1 +
 src/nouveau/vulkan/nvk_physical_device.c    |   1 +
 src/panfrost/vulkan/panvk_physical_device.c |   1 +
 src/vulkan/wsi/wsi_common.c                 |  12 ++
 src/vulkan/wsi/wsi_common_private.h         |   2 +
 src/vulkan/wsi/wsi_common_wayland.c         | 151 ++++++++++++++++----
 10 files changed, 146 insertions(+), 26 deletions(-)

diff --git a/src/amd/vulkan/radv_physical_device.c b/src/amd/vulkan/radv_physical_device.c
index 0d3660e7064..4dc4f647593 100644
--- a/src/amd/vulkan/radv_physical_device.c
+++ b/src/amd/vulkan/radv_physical_device.c
@@ -630,6 +630,7 @@ radv_physical_device_get_supported_extensions(const struct radv_physical_device
       .EXT_global_priority = true,
       .EXT_global_priority_query = true,
       .EXT_graphics_pipeline_library = !pdev->use_llvm && !(instance->debug_flags & RADV_DEBUG_NO_GPL),
+      .EXT_hdr_metadata = true,
       .EXT_host_query_reset = true,
       .EXT_image_2d_view_of_3d = true,
       .EXT_image_compression_control = true,
diff --git a/src/asahi/vulkan/hk_physical_device.c b/src/asahi/vulkan/hk_physical_device.c
index 8dcbd15c2b7..d916d749a0d 100644
--- a/src/asahi/vulkan/hk_physical_device.c
+++ b/src/asahi/vulkan/hk_physical_device.c
@@ -153,6 +153,7 @@ hk_get_device_extensions(const struct hk_instance *instance,
       .EXT_global_priority = true,
       .EXT_global_priority_query = true,
       .EXT_graphics_pipeline_library = true,
+      .EXT_hdr_metadata = true,
       .EXT_host_query_reset = true,
       .EXT_host_image_copy = true,
       .EXT_image_2d_view_of_3d = true,
diff --git a/src/freedreno/vulkan/tu_device.cc b/src/freedreno/vulkan/tu_device.cc
index 7b18dcf24f9..41d15d64733 100644
--- a/src/freedreno/vulkan/tu_device.cc
+++ b/src/freedreno/vulkan/tu_device.cc
@@ -274,6 +274,7 @@ get_device_extensions(const struct tu_physical_device *device,
       .EXT_global_priority = true,
       .EXT_global_priority_query = true,
       .EXT_graphics_pipeline_library = true,
+      .EXT_hdr_metadata = true,
       .EXT_host_image_copy = true,
       .EXT_host_query_reset = true,
       .EXT_image_2d_view_of_3d = true,
diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c
index 934c501e231..260200e7d1c 100644
--- a/src/gallium/frontends/lavapipe/lvp_device.c
+++ b/src/gallium/frontends/lavapipe/lvp_device.c
@@ -211,6 +211,7 @@ static const struct vk_device_extension_table lvp_device_extensions_supported =
    .EXT_extended_dynamic_state3           = true,
    .EXT_external_memory_host              = true,
    .EXT_graphics_pipeline_library         = true,
+   .EXT_hdr_metadata = true,
    .EXT_host_image_copy                   = true,
    .EXT_host_query_reset                  = true,
    .EXT_image_2d_view_of_3d               = true,
diff --git a/src/intel/vulkan/anv_physical_device.c b/src/intel/vulkan/anv_physical_device.c
index b2eda469415..8506790cd72 100644
--- a/src/intel/vulkan/anv_physical_device.c
+++ b/src/intel/vulkan/anv_physical_device.c
@@ -282,6 +282,7 @@ get_device_extensions(const struct anv_physical_device *device,
       .EXT_global_priority_query             = device->max_context_priority >=
                                                VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR,
       .EXT_graphics_pipeline_library         = !debug_get_bool_option("ANV_NO_GPL", false),
+      .EXT_hdr_metadata = true,
       .EXT_host_image_copy                   = !device->emu_astc_ldr,
       .EXT_host_query_reset                  = true,
       .EXT_image_2d_view_of_3d               = true,
diff --git a/src/nouveau/vulkan/nvk_physical_device.c b/src/nouveau/vulkan/nvk_physical_device.c
index 9b05c1968aa..10ab3b6e488 100644
--- a/src/nouveau/vulkan/nvk_physical_device.c
+++ b/src/nouveau/vulkan/nvk_physical_device.c
@@ -229,6 +229,7 @@ nvk_get_device_extensions(const struct nvk_instance *instance,
       .EXT_global_priority = true,
       .EXT_global_priority_query = true,
       .EXT_graphics_pipeline_library = true,
+      .EXT_hdr_metadata = true,
       .EXT_host_query_reset = true,
       .EXT_host_image_copy = info->cls_eng3d >= TURING_A,
       .EXT_image_2d_view_of_3d = true,
diff --git a/src/panfrost/vulkan/panvk_physical_device.c b/src/panfrost/vulkan/panvk_physical_device.c
index dc3b371c3b0..4250d66bbb9 100644
--- a/src/panfrost/vulkan/panvk_physical_device.c
+++ b/src/panfrost/vulkan/panvk_physical_device.c
@@ -231,6 +231,7 @@ get_device_extensions(const struct panvk_physical_device *device,
       .EXT_global_priority = true,
       .EXT_global_priority_query = true,
       .EXT_graphics_pipeline_library = true,
+      .EXT_hdr_metadata = true,
       .EXT_host_query_reset = true,
       .EXT_image_drm_format_modifier = true,
       .EXT_image_robustness = true,
diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c
index d18ca4d9ebd..7f41e61639f 100644
--- a/src/vulkan/wsi/wsi_common.c
+++ b/src/vulkan/wsi/wsi_common.c
@@ -2253,3 +2253,15 @@ wsi_device_supports_explicit_sync(struct wsi_device *device)
       (device->timeline_semaphore_export_handle_types &
        VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT);
 }
+
+VKAPI_ATTR void VKAPI_CALL
+wsi_SetHdrMetadataEXT(VkDevice device, uint32_t swapchainCount,
+                      const VkSwapchainKHR* pSwapchains,
+                      const VkHdrMetadataEXT* pMetadata)
+{
+   for (uint32_t i = 0; i < swapchainCount; i++) {
+      VK_FROM_HANDLE(wsi_swapchain, swapchain, pSwapchains[i]);
+      if (swapchain->set_hdr_metadata)
+         swapchain->set_hdr_metadata(swapchain, pMetadata);
+   }
+}
diff --git a/src/vulkan/wsi/wsi_common_private.h b/src/vulkan/wsi/wsi_common_private.h
index 849bdc6715f..40db1a7c176 100644
--- a/src/vulkan/wsi/wsi_common_private.h
+++ b/src/vulkan/wsi/wsi_common_private.h
@@ -223,6 +223,8 @@ struct wsi_swapchain {
                               const uint32_t *indices);
    void (*set_present_mode)(struct wsi_swapchain *swap_chain,
                             VkPresentModeKHR mode);
+   void (*set_hdr_metadata)(struct wsi_swapchain *swap_chain,
+                            const VkHdrMetadataEXT* pMetadata);
 };
 
 bool
diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
index d4b47c1f1b8..de12f524891 100644
--- a/src/vulkan/wsi/wsi_common_wayland.c
+++ b/src/vulkan/wsi/wsi_common_wayland.c
@@ -140,6 +140,11 @@ struct wsi_wl_display {
    bool same_gpu;
 
    clockid_t presentation_clock_id;
+
+   struct {
+      bool mastering_display_primaries;
+      bool extended_target_volume;
+   } color_features;
 };
 
 struct wsi_wayland {
@@ -191,9 +196,14 @@ struct wsi_wl_surface {
    struct wp_linux_drm_syncobj_surface_v1 *wl_syncobj_surface;
 
    struct vk_instance *instance;
-   struct wp_color_management_surface_v1 *color_surface;
-   int color_surface_refcount;
-   VkColorSpaceKHR colorspace;
+
+   struct {
+      struct wp_color_management_surface_v1 *color_surface;
+      int color_surface_refcount;
+      VkColorSpaceKHR colorspace;
+      VkHdrMetadataEXT hdr_metadata;
+      bool has_hdr_metadata;
+   } color;
 };
 
 struct wsi_wl_swapchain {
@@ -244,7 +254,11 @@ struct wsi_wl_swapchain {
       unsigned int refresh_nsec;
    } present_ids;
 
-   VkColorSpaceKHR colorspace;
+   struct {
+      VkColorSpaceKHR colorspace;
+      VkHdrMetadataEXT hdr_metadata;
+      bool has_hdr_metadata;
+   } color;
 
    struct wsi_wl_image images[0];
 };
@@ -917,58 +931,69 @@ struct Colorspace {
    VkColorSpaceKHR colorspace;
    enum wp_color_manager_v1_primaries primaries;
    enum wp_color_manager_v1_transfer_function tf;
+   bool should_use_hdr_metadata;
 };
 struct Colorspace colorspace_mapping[] = {
    {
       .colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
       .primaries = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB,
       .tf = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB,
+      .should_use_hdr_metadata = false,
    },
    {
       .colorspace = VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT,
       .primaries = WP_COLOR_MANAGER_V1_PRIMARIES_DISPLAY_P3,
       .tf = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB,
+      .should_use_hdr_metadata = false,
    },
    {
       .colorspace = VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT,
       .primaries = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB,
       .tf = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR,
+      .should_use_hdr_metadata = true,
    },
    {
       .colorspace = VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT,
       .primaries = WP_COLOR_MANAGER_V1_PRIMARIES_DISPLAY_P3,
       .tf = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR,
+      .should_use_hdr_metadata = false,
    },
    {
       .colorspace = VK_COLOR_SPACE_BT709_LINEAR_EXT,
       .primaries = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB,
       .tf = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR,
+      .should_use_hdr_metadata = false,
    },
    {
       .colorspace = VK_COLOR_SPACE_BT709_NONLINEAR_EXT,
       .primaries = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB,
       .tf = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_BT1886,
+      .should_use_hdr_metadata = false,
    },
    {
       .colorspace = VK_COLOR_SPACE_BT2020_LINEAR_EXT,
       .primaries = WP_COLOR_MANAGER_V1_PRIMARIES_BT2020,
       .tf = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR,
+      .should_use_hdr_metadata = false,
    },
    {
       .colorspace = VK_COLOR_SPACE_HDR10_ST2084_EXT,
       .primaries = WP_COLOR_MANAGER_V1_PRIMARIES_BT2020,
       .tf = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ,
+      .should_use_hdr_metadata = true,
    },
    /* VK_COLOR_SPACE_DOLBYVISION_EXT is left out because it's deprecated */
    {
       .colorspace = VK_COLOR_SPACE_HDR10_HLG_EXT,
       .primaries = WP_COLOR_MANAGER_V1_PRIMARIES_BT2020,
       .tf = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_HLG,
+      .should_use_hdr_metadata = true,
    },
    {
       .colorspace = VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT,
       .primaries = WP_COLOR_MANAGER_V1_PRIMARIES_ADOBE_RGB,
       .tf = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR,
+      .should_use_hdr_metadata = false,
    },
    /* VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT is left out because there's no
     * exactly matching transfer function in the Wayland protocol */
@@ -977,6 +1002,7 @@ struct Colorspace colorspace_mapping[] = {
       .colorspace = VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT,
       .primaries = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB,
       .tf = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_SRGB,
+      .should_use_hdr_metadata = true,
    },
    /* VK_COLOR_SPACE_DISPLAY_NATIVE_AMD isn't supported */
    /* VK_COLORSPACE_SRGB_NONLINEAR_KHR is just an alias */
@@ -1033,7 +1059,17 @@ color_management_handle_supported_features(void *data,
                                            struct wp_color_manager_v1 *color_manager,
                                            unsigned int feature)
 {
-   /* We don't use any non-default features yet. */
+   struct wsi_wl_display *display = data;
+   switch (feature) {
+   case WP_COLOR_MANAGER_V1_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES:
+      display->color_features.mastering_display_primaries = true;
+      break;
+   case WP_COLOR_MANAGER_V1_FEATURE_EXTENDED_TARGET_VOLUME:
+      display->color_features.extended_target_volume = true;
+      break;
+   default:
+      break;
+   }
 }
 
 static void
@@ -1111,9 +1147,9 @@ needs_color_surface(VkColorSpaceKHR colorspace)
 static void
 wsi_wl_surface_add_color_refcount(struct wsi_wl_surface *wsi_surface)
 {
-   wsi_surface->color_surface_refcount++;
-   if (wsi_surface->color_surface_refcount == 1) {
-      wsi_surface->color_surface =
+   wsi_surface->color.color_surface_refcount++;
+   if (wsi_surface->color.color_surface_refcount == 1) {
+      wsi_surface->color.color_surface =
          wp_color_manager_v1_get_surface(wsi_surface->display->color_manager, wsi_surface->surface);
    }
 }
@@ -1121,13 +1157,30 @@ wsi_wl_surface_add_color_refcount(struct wsi_wl_surface *wsi_surface)
 static void
 wsi_wl_surface_remove_color_refcount(struct wsi_wl_surface *wsi_surface)
 {
-   wsi_surface->color_surface_refcount--;
-   if (wsi_surface->color_surface_refcount == 0) {
-      wp_color_management_surface_v1_destroy(wsi_surface->color_surface);
-      wsi_surface->color_surface = NULL;
+   wsi_surface->color.color_surface_refcount--;
+   if (wsi_surface->color.color_surface_refcount == 0) {
+      wp_color_management_surface_v1_destroy(wsi_surface->color.color_surface);
+      wsi_surface->color.color_surface = NULL;
    }
 }
 
+static bool
+compare_hdr_metadata(struct VkHdrMetadataEXT *l, struct VkHdrMetadataEXT *r)
+{
+   return l->displayPrimaryRed.x == r->displayPrimaryRed.x
+       && l->displayPrimaryRed.y == r->displayPrimaryRed.y
+       && l->displayPrimaryGreen.x == r->displayPrimaryGreen.x
+       && l->displayPrimaryGreen.y == r->displayPrimaryGreen.y
+       && l->displayPrimaryBlue.x == r->displayPrimaryBlue.x
+       && l->displayPrimaryBlue.y == r->displayPrimaryBlue.y
+       && l->whitePoint.x == r->whitePoint.x
+       && l->whitePoint.y == r->whitePoint.y
+       && l->maxLuminance == r->maxLuminance
+       && l->minLuminance == r->minLuminance
+       && l->maxContentLightLevel == r->maxContentLightLevel
+       && l->maxFrameAverageLightLevel == r->maxFrameAverageLightLevel;
+}
+
 static VkResult
 wsi_wl_swapchain_update_colorspace(struct wsi_wl_swapchain *chain)
 {
@@ -1137,29 +1190,43 @@ wsi_wl_swapchain_update_colorspace(struct wsi_wl_swapchain *chain)
    /* we need the color management extension for
     * everything except sRGB and PASS_THROUGH */
    if (!display->color_manager) {
-      if (chain->colorspace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR ||
-          chain->colorspace == VK_COLOR_SPACE_PASS_THROUGH_EXT) {
+      if (chain->color.colorspace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR ||
+          chain->color.colorspace == VK_COLOR_SPACE_PASS_THROUGH_EXT) {
          return VK_SUCCESS;
       } else {
          return VK_ERROR_SURFACE_LOST_KHR;
       }
    }
 
-   bool new_color_surface = !surface->color_surface;
-   bool needs_color_surface_new = needs_color_surface(chain->colorspace);
-   bool needs_color_surface_old = needs_color_surface(surface->colorspace);
+   bool new_color_surface = !surface->color.color_surface;
+   bool needs_color_surface_new = needs_color_surface(chain->color.colorspace);
+   bool needs_color_surface_old = needs_color_surface(surface->color.colorspace);
    if ((new_color_surface || !needs_color_surface_old) && needs_color_surface_new) {
       wsi_wl_surface_add_color_refcount(surface);
    } else if (needs_color_surface_old && !needs_color_surface_new) {
       wsi_wl_surface_remove_color_refcount(surface);
    }
 
-   if (!new_color_surface && surface->colorspace == chain->colorspace)
+   bool should_use_hdr_metadata = chain->color.has_hdr_metadata;
+   for (int i = 0; i < ARRAY_SIZE(colorspace_mapping); i++) {
+      if (colorspace_mapping[i].colorspace == chain->color.colorspace) {
+         should_use_hdr_metadata &= colorspace_mapping[i].should_use_hdr_metadata;
+         break;
+      }
+   }
+
+   if (!new_color_surface &&
+       surface->color.colorspace == chain->color.colorspace &&
+       surface->color.has_hdr_metadata == should_use_hdr_metadata &&
+       compare_hdr_metadata(&surface->color.hdr_metadata, &chain->color.hdr_metadata)) {
       return VK_SUCCESS;
+   }
 
    /* failure is fatal, so this potentially being wrong
       in that case doesn't matter */
-   surface->colorspace = chain->colorspace;
+   surface->color.colorspace = chain->color.colorspace;
+   surface->color.hdr_metadata = chain->color.hdr_metadata;
+   surface->color.has_hdr_metadata = should_use_hdr_metadata;
    if (!needs_color_surface_new)
       return VK_SUCCESS;
 
@@ -1172,7 +1239,7 @@ wsi_wl_swapchain_update_colorspace(struct wsi_wl_swapchain *chain)
    unsigned int primaries = 0;
    unsigned int tf = 0;
    for (int i = 0; i < ARRAY_SIZE(colorspace_mapping); i++) {
-      if (colorspace_mapping[i].colorspace == chain->colorspace) {
+      if (colorspace_mapping[i].colorspace == chain->color.colorspace) {
          primaries = colorspace_mapping[i].primaries;
          tf = colorspace_mapping[i].tf;
       }
@@ -1183,6 +1250,29 @@ wsi_wl_swapchain_update_colorspace(struct wsi_wl_swapchain *chain)
 
    wp_image_description_creator_params_v1_set_primaries_named(creator, primaries);
    wp_image_description_creator_params_v1_set_tf_named(creator, tf);
+   if (should_use_hdr_metadata && display->color_features.extended_target_volume) {
+      uint32_t max_cll = round(chain->color.hdr_metadata.maxContentLightLevel);
+      uint32_t max_fall = round(chain->color.hdr_metadata.maxFrameAverageLightLevel);
+      wp_image_description_creator_params_v1_set_max_cll(creator, max_cll);
+      wp_image_description_creator_params_v1_set_max_fall(creator, max_fall);
+      if (display->color_features.mastering_display_primaries) {
+         uint32_t red_x = round(chain->color.hdr_metadata.displayPrimaryRed.x * 1000000);
+         uint32_t red_y = round(chain->color.hdr_metadata.displayPrimaryRed.y * 1000000);
+         uint32_t green_x = round(chain->color.hdr_metadata.displayPrimaryGreen.x * 1000000);
+         uint32_t green_y = round(chain->color.hdr_metadata.displayPrimaryGreen.y * 1000000);
+         uint32_t blue_x = round(chain->color.hdr_metadata.displayPrimaryBlue.x * 1000000);
+         uint32_t blue_y = round(chain->color.hdr_metadata.displayPrimaryBlue.y * 1000000);
+         uint32_t white_x = round(chain->color.hdr_metadata.whitePoint.x * 1000000);
+         uint32_t white_y = round(chain->color.hdr_metadata.whitePoint.y * 1000000);
+         wp_image_description_creator_params_v1_set_mastering_display_primaries(creator, red_x, red_y,
+                                                                                green_x, green_y,
+                                                                                blue_x, blue_y,
+                                                                                white_x, white_y);
+         uint32_t min_lum = round(chain->color.hdr_metadata.minLuminance * 10000);
+         uint32_t max_lum = round(chain->color.hdr_metadata.maxLuminance);
+         wp_image_description_creator_params_v1_set_mastering_luminance(creator, min_lum, max_lum);
+      }
+   }
 
    wl_proxy_set_queue((struct wl_proxy *) creator, display->queue);
 
@@ -1202,7 +1292,7 @@ wsi_wl_swapchain_update_colorspace(struct wsi_wl_swapchain *chain)
    if (status == failed)
       return VK_ERROR_SURFACE_LOST_KHR;
 
-   wp_color_management_surface_v1_set_image_description(chain->wsi_wl_surface->color_surface,
+   wp_color_management_surface_v1_set_image_description(chain->wsi_wl_surface->color.color_surface,
                                                         image_desc,
                                                         WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
    wp_image_description_v1_destroy(image_desc);
@@ -1210,6 +1300,14 @@ wsi_wl_swapchain_update_colorspace(struct wsi_wl_swapchain *chain)
    return VK_SUCCESS;
 }
 
+static void
+wsi_wl_swapchain_set_hdr_metadata(struct wsi_swapchain *wsi_chain,
+                                  const VkHdrMetadataEXT* pMetadata)
+{
+   struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain;
+   chain->color.hdr_metadata = *pMetadata;
+   chain->color.has_hdr_metadata = true;
+}
 
 static void
 presentation_handle_clock_id(void* data, struct wp_presentation *wp_presentation, uint32_t clk_id)
@@ -1875,8 +1973,8 @@ wsi_wl_surface_destroy(VkIcdSurfaceBase *icd_surface, VkInstance _instance,
       dmabuf_feedback_fini(&wsi_wl_surface->pending_dmabuf_feedback);
    }
 
-   if (wsi_wl_surface->color_surface)
-      wp_color_management_surface_v1_destroy(wsi_wl_surface->color_surface);
+   if (wsi_wl_surface->color.color_surface)
+      wp_color_management_surface_v1_destroy(wsi_wl_surface->color.color_surface);
 
    if (wsi_wl_surface->surface)
       wl_proxy_wrapper_destroy(wsi_wl_surface->surface);
@@ -2201,7 +2299,7 @@ wsi_CreateWaylandSurfaceKHR(VkInstance _instance,
    surface->surface = pCreateInfo->surface;
 
    wsi_wl_surface->instance = instance;
-   wsi_wl_surface->colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
+   wsi_wl_surface->color.colorspace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
 
    *pSurface = VkIcdSurfaceBase_to_handle(&surface->base);
 
@@ -3185,7 +3283,7 @@ wsi_wl_swapchain_chain_free(struct wsi_wl_swapchain *chain,
       wl_callback_destroy(chain->frame);
    if (chain->tearing_control)
       wp_tearing_control_v1_destroy(chain->tearing_control);
-   if (needs_color_surface(chain->colorspace) && wsi_wl_surface->color_surface) {
+   if (needs_color_surface(chain->color.colorspace) && wsi_wl_surface->color.color_surface) {
       wsi_wl_surface_remove_color_refcount(wsi_wl_surface);
    }
 
@@ -3352,7 +3450,7 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
                                                           WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC);
    }
 
-   chain->colorspace = pCreateInfo->imageColorSpace;
+   chain->color.colorspace = pCreateInfo->imageColorSpace;
 
    enum wsi_wl_buffer_type buffer_type;
    struct wsi_base_image_params *image_params = NULL;
@@ -3426,6 +3524,7 @@ wsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
    chain->base.wait_for_present = wsi_wl_swapchain_wait_for_present;
    chain->base.present_mode = present_mode;
    chain->base.image_count = num_images;
+   chain->base.set_hdr_metadata = wsi_wl_swapchain_set_hdr_metadata;
    chain->extent = pCreateInfo->imageExtent;
    chain->vk_format = pCreateInfo->imageFormat;
    chain->buffer_type = buffer_type;
-- 
2.49.0

