瀏覽代碼

wayland: Add color manager protocol support

Support the official wp_color_manager_v1 protocol.
Frank Praznik 6 月之前
父節點
當前提交
fadb261b66

+ 224 - 0
src/video/wayland/SDL_waylandcolor.c

@@ -0,0 +1,224 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_internal.h"
+
+#ifdef SDL_VIDEO_DRIVER_WAYLAND
+
+#include "SDL_waylandcolor.h"
+#include "SDL_waylandvideo.h"
+#include "SDL_waylandwindow.h"
+#include "color-management-v1-client-protocol.h"
+
+typedef struct Wayland_ColorInfoState
+{
+    struct wp_image_description_v1 *wp_image_description;
+    struct wp_image_description_info_v1 *wp_image_description_info;
+    Wayland_ColorInfo *info;
+
+    bool result;
+} Wayland_ColorInfoState;
+
+static void image_description_info_handle_done(void *data,
+                                               struct wp_image_description_info_v1 *wp_image_description_info_v1)
+{
+    Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
+
+    if (state->wp_image_description_info) {
+        wp_image_description_info_v1_destroy(state->wp_image_description_info);
+        state->wp_image_description_info = NULL;
+    }
+    if (state->wp_image_description) {
+        wp_image_description_v1_destroy(state->wp_image_description);
+        state->wp_image_description = NULL;
+    }
+
+    state->result = true;
+}
+
+static void image_description_info_handle_icc_file(void *data,
+                                                   struct wp_image_description_info_v1 *wp_image_description_info_v1,
+                                                   int32_t icc, uint32_t icc_size)
+{
+    Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
+
+    state->info->icc_fd = icc;
+    state->info->icc_size = icc_size;
+}
+
+static void image_description_info_handle_primaries(void *data,
+                                                    struct wp_image_description_info_v1 *wp_image_description_info_v1,
+                                                    int32_t r_x, int32_t r_y,
+                                                    int32_t g_x, int32_t g_y,
+                                                    int32_t b_x, int32_t b_y,
+                                                    int32_t w_x, int32_t w_y)
+{
+    // NOP
+}
+
+static void image_description_info_handle_primaries_named(void *data,
+                                                          struct wp_image_description_info_v1 *wp_image_description_info_v1,
+                                                          uint32_t primaries)
+{
+    // NOP
+}
+
+static void image_description_info_handle_tf_power(void *data,
+                                                   struct wp_image_description_info_v1 *wp_image_description_info_v1,
+                                                   uint32_t eexp)
+{
+    // NOP
+}
+
+static void image_description_info_handle_tf_named(void *data,
+                                                   struct wp_image_description_info_v1 *wp_image_description_info_v1,
+                                                   uint32_t tf)
+{
+    // NOP
+}
+
+static void image_description_info_handle_luminances(void *data,
+                                                     struct wp_image_description_info_v1 *wp_image_description_info_v1,
+                                                     uint32_t min_lum,
+                                                     uint32_t max_lum,
+                                                     uint32_t reference_lum)
+{
+    Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
+    state->info->HDR.HDR_headroom = (float)max_lum / (float)reference_lum;
+}
+
+static void image_description_info_handle_target_primaries(void *data,
+                                                           struct wp_image_description_info_v1 *wp_image_description_info_v1,
+                                                           int32_t r_x, int32_t r_y,
+                                                           int32_t g_x, int32_t g_y,
+                                                           int32_t b_x, int32_t b_y,
+                                                           int32_t w_x, int32_t w_y)
+{
+    // NOP
+}
+
+static void image_description_info_handle_target_luminance(void *data,
+                                                           struct wp_image_description_info_v1 *wp_image_description_info_v1,
+                                                           uint32_t min_lum,
+                                                           uint32_t max_lum)
+{
+    // NOP
+}
+
+static void image_description_info_handle_target_max_cll(void *data,
+                                                         struct wp_image_description_info_v1 *wp_image_description_info_v1,
+                                                         uint32_t max_cll)
+{
+    // NOP
+}
+
+static void image_description_info_handle_target_max_fall(void *data,
+                                                          struct wp_image_description_info_v1 *wp_image_description_info_v1,
+                                                          uint32_t max_fall)
+{
+    // NOP
+}
+
+static const struct wp_image_description_info_v1_listener image_description_info_listener = {
+    image_description_info_handle_done,
+    image_description_info_handle_icc_file,
+    image_description_info_handle_primaries,
+    image_description_info_handle_primaries_named,
+    image_description_info_handle_tf_power,
+    image_description_info_handle_tf_named,
+    image_description_info_handle_luminances,
+    image_description_info_handle_target_primaries,
+    image_description_info_handle_target_luminance,
+    image_description_info_handle_target_max_cll,
+    image_description_info_handle_target_max_fall
+};
+
+static void PumpColorspaceEvents(Wayland_ColorInfoState *state)
+{
+    SDL_VideoData *vid = SDL_GetVideoDevice()->internal;
+
+    // Run the image description sequence to completion in its own queue.
+    struct wl_event_queue *queue = WAYLAND_wl_display_create_queue(vid->display);
+    WAYLAND_wl_proxy_set_queue((struct wl_proxy *)state->wp_image_description, queue);
+
+    while (state->wp_image_description) {
+        WAYLAND_wl_display_dispatch_queue(vid->display, queue);
+    }
+
+    WAYLAND_wl_event_queue_destroy(queue);
+}
+
+static void image_description_handle_failed(void *data,
+                                            struct wp_image_description_v1 *wp_image_description_v1,
+                                            uint32_t cause,
+                                            const char *msg)
+{
+    Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
+
+    wp_image_description_v1_destroy(state->wp_image_description);
+    state->wp_image_description = NULL;
+}
+
+static void image_description_handle_ready(void *data,
+                                           struct wp_image_description_v1 *wp_image_description_v1,
+                                           uint32_t identity)
+{
+    Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
+
+    // This will inherit the queue of the factory image description object.
+    state->wp_image_description_info = wp_image_description_v1_get_information(state->wp_image_description);
+    wp_image_description_info_v1_add_listener(state->wp_image_description_info, &image_description_info_listener, data);
+}
+
+static const struct wp_image_description_v1_listener image_description_listener = {
+    image_description_handle_failed,
+    image_description_handle_ready
+};
+
+bool Wayland_GetColorInfoForWindow(SDL_WindowData *window_data, Wayland_ColorInfo *info)
+{
+    Wayland_ColorInfoState state;
+    SDL_zero(state);
+    state.info = info;
+
+    state.wp_image_description = wp_color_management_surface_feedback_v1_get_preferred(window_data->wp_color_management_surface_feedback);
+    wp_image_description_v1_add_listener(state.wp_image_description, &image_description_listener, &state);
+
+    PumpColorspaceEvents(&state);
+
+    return state.result;
+}
+
+bool Wayland_GetColorInfoForOutput(SDL_DisplayData *display_data, Wayland_ColorInfo *info)
+{
+    Wayland_ColorInfoState state;
+    SDL_zero(state);
+    state.info = info;
+
+    state.wp_image_description = wp_color_management_output_v1_get_image_description(display_data->wp_color_management_output);
+    wp_image_description_v1_add_listener(state.wp_image_description, &image_description_listener, &state);
+
+    PumpColorspaceEvents(&state);
+
+    return state.result;
+}
+
+#endif // SDL_VIDEO_DRIVER_WAYLAND

+ 41 - 0
src/video/wayland/SDL_waylandcolor.h

@@ -0,0 +1,41 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_internal.h"
+
+#ifndef SDL_waylandcolor_h_
+#define SDL_waylandcolor_h_
+
+#include "../SDL_sysvideo.h"
+
+typedef struct Wayland_ColorInfo
+{
+    SDL_HDROutputProperties HDR;
+
+    // The ICC fd is only valid if the size is non-zero.
+    int icc_fd;
+    Uint32 icc_size;
+} Wayland_ColorInfo;
+
+extern bool Wayland_GetColorInfoForWindow(SDL_WindowData *window_data, Wayland_ColorInfo *info);
+extern bool Wayland_GetColorInfoForOutput(SDL_DisplayData *display_data, Wayland_ColorInfo *info);
+
+#endif // SDL_waylandcolor_h_

+ 64 - 5
src/video/wayland/SDL_waylandvideo.c

@@ -27,6 +27,7 @@
 #include "../../events/SDL_events_c.h"
 
 #include "SDL_waylandclipboard.h"
+#include "SDL_waylandcolor.h"
 #include "SDL_waylandevents_c.h"
 #include "SDL_waylandkeyboard.h"
 #include "SDL_waylandmessagebox.h"
@@ -63,6 +64,7 @@
 #include "xdg-output-unstable-v1-client-protocol.h"
 #include "xdg-shell-client-protocol.h"
 #include "xdg-toplevel-icon-v1-client-protocol.h"
+#include "color-management-v1-client-protocol.h"
 
 #ifdef HAVE_LIBDECOR_H
 #include <libdecor.h>
@@ -249,7 +251,7 @@ static int SDLCALL Wayland_DisplayPositionCompare(const void *a, const void *b)
  * The primary is determined by the following criteria, in order:
  * - Landscape is preferred over portrait
  * - The highest native resolution
- * - TODO: A higher HDR range is preferred
+ * - A higher HDR range is preferred
  * - Higher refresh is preferred (ignoring small differences)
  * - Lower scale values are preferred (larger display)
  */
@@ -271,6 +273,7 @@ static int Wayland_GetPrimaryDisplay(SDL_VideoData *vid)
     int best_width = 0;
     int best_height = 0;
     double best_scale = 0.0;
+    float best_headroom = 0.0f;
     int best_refresh = 0;
     bool best_is_landscape = false;
     int best_index = 0;
@@ -286,11 +289,15 @@ static int Wayland_GetPrimaryDisplay(SDL_VideoData *vid)
             if (d->pixel_width > best_width || d->pixel_height > best_height) {
                 have_new_best = true;
             } else if (d->pixel_width == best_width && d->pixel_height == best_height) {
-                if (d->refresh - best_refresh > REFRESH_DELTA) { // Favor a higher refresh rate, but ignore small differences (e.g. 59.97 vs 60.1)
-                    have_new_best = true;
-                } else if (d->scale_factor < best_scale && SDL_abs(d->refresh - best_refresh) <= REFRESH_DELTA) {
-                    // Prefer a lower scale display if the difference in refresh rate is small.
+                if (d->HDR.HDR_headroom > best_headroom) { // Favor a higher HDR luminance range
                     have_new_best = true;
+                } else if (d->HDR.HDR_headroom == best_headroom) {
+                    if (d->refresh - best_refresh > REFRESH_DELTA) { // Favor a higher refresh rate, but ignore small differences (e.g. 59.97 vs 60.1)
+                        have_new_best = true;
+                    } else if (d->scale_factor < best_scale && SDL_abs(d->refresh - best_refresh) <= REFRESH_DELTA) {
+                        // Prefer a lower scale display if the difference in refresh rate is small.
+                        have_new_best = true;
+                    }
                 }
             }
         }
@@ -299,6 +306,7 @@ static int Wayland_GetPrimaryDisplay(SDL_VideoData *vid)
             best_width = d->pixel_width;
             best_height = d->pixel_height;
             best_scale = d->scale_factor;
+            best_headroom = d->HDR.HDR_headroom;
             best_refresh = d->refresh;
             best_is_landscape = is_landscape;
             best_index = i;
@@ -630,6 +638,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(bool require_preferred_protocols)
     device->SetWindowIcon = Wayland_SetWindowIcon;
     device->GetWindowSizeInPixels = Wayland_GetWindowSizeInPixels;
     device->GetWindowContentScale = Wayland_GetWindowContentScale;
+    device->GetWindowICCProfile = Wayland_GetWindowICCProfile;
     device->GetDisplayForWindow = Wayland_GetDisplayForWindow;
     device->DestroyWindow = Wayland_DestroyWindow;
     device->SetWindowHitTest = Wayland_SetWindowHitTest;
@@ -1050,6 +1059,8 @@ static void display_handle_done(void *data,
         AddEmulatedModes(internal, native_mode.w, native_mode.h);
     }
 
+    SDL_SetDisplayHDRProperties(dpy, &internal->HDR);
+
     if (internal->display == 0) {
         // First time getting display info, initialize the VideoDisplay
         if (internal->physical_width_mm >= internal->physical_height_mm) {
@@ -1107,6 +1118,27 @@ static const struct wl_output_listener output_listener = {
     display_handle_description // Version 4
 };
 
+static void Wayland_GetOutputColorInfo(SDL_DisplayData *display)
+{
+    Wayland_ColorInfo info;
+    SDL_zero(info);
+
+    if (Wayland_GetColorInfoForOutput(display, &info)) {
+        SDL_copyp(&display->HDR, &info.HDR);
+    }
+}
+
+static void handle_output_image_description_changed(void *data,
+                                                    struct wp_color_management_output_v1 *wp_color_management_output_v1)
+{
+    // wl_display.done is called after this event, so the display HDR status will be updated there.
+    Wayland_GetOutputColorInfo(data);
+}
+
+static const struct wp_color_management_output_v1_listener wp_color_management_output_listener = {
+    handle_output_image_description_changed
+};
+
 static bool Wayland_add_display(SDL_VideoData *d, uint32_t id, uint32_t version)
 {
     struct wl_output *output;
@@ -1136,6 +1168,11 @@ static bool Wayland_add_display(SDL_VideoData *d, uint32_t id, uint32_t version)
         data->xdg_output = zxdg_output_manager_v1_get_xdg_output(data->videodata->xdg_output_manager, output);
         zxdg_output_v1_add_listener(data->xdg_output, &xdg_output_listener, data);
     }
+    if (data->videodata->wp_color_manager_v1) {
+        data->wp_color_management_output = wp_color_manager_v1_get_output(data->videodata->wp_color_manager_v1, output);
+        wp_color_management_output_v1_add_listener(data->wp_color_management_output, &wp_color_management_output_listener, data);
+        Wayland_GetOutputColorInfo(data);
+    }
     return true;
 }
 
@@ -1153,6 +1190,10 @@ static void Wayland_free_display(SDL_VideoDisplay *display, bool send_event)
 
         SDL_free(display_data->wl_output_name);
 
+        if (display_data->wp_color_management_output) {
+            wp_color_management_output_v1_destroy(display_data->wp_color_management_output);
+        }
+
         if (display_data->xdg_output) {
             zxdg_output_v1_destroy(display_data->xdg_output);
         }
@@ -1187,6 +1228,16 @@ static void Wayland_init_xdg_output(SDL_VideoData *d)
     }
 }
 
+static void Wayland_InitColorManager(SDL_VideoData *d)
+{
+    for (int i = 0; i < d->output_count; ++i) {
+        SDL_DisplayData *disp = d->output_list[i];
+        disp->wp_color_management_output = wp_color_manager_v1_get_output(disp->videodata->wp_color_manager_v1, disp->output);
+        wp_color_management_output_v1_add_listener(disp->wp_color_management_output, &wp_color_management_output_listener, disp);
+        Wayland_GetOutputColorInfo(disp);
+    }
+}
+
 static void handle_ping_xdg_wm_base(void *data, struct xdg_wm_base *xdg, uint32_t serial)
 {
     xdg_wm_base_pong(xdg, serial);
@@ -1280,6 +1331,9 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
         d->xdg_toplevel_icon_manager_v1 = wl_registry_bind(d->registry, id, &xdg_toplevel_icon_manager_v1_interface, 1);
     } else if (SDL_strcmp(interface, "frog_color_management_factory_v1") == 0) {
         d->frog_color_management_factory_v1 = wl_registry_bind(d->registry, id, &frog_color_management_factory_v1_interface, 1);
+    } else if (SDL_strcmp(interface, "xx_color_manager_v4") == 0) {
+        d->wp_color_manager_v1 = wl_registry_bind(d->registry, id, &wp_color_manager_v1_interface, 1);
+        Wayland_InitColorManager(d);
     }
 }
 
@@ -1567,6 +1621,11 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)
         data->frog_color_management_factory_v1 = NULL;
     }
 
+    if (data->wp_color_manager_v1) {
+        wp_color_manager_v1_destroy(data->wp_color_manager_v1);
+        data->wp_color_manager_v1 = NULL;
+    }
+
     if (data->compositor) {
         wl_compositor_destroy(data->compositor);
         data->compositor = NULL;

+ 4 - 0
src/video/wayland/SDL_waylandvideo.h

@@ -83,6 +83,7 @@ struct SDL_VideoData
     struct wp_alpha_modifier_v1 *wp_alpha_modifier_v1;
     struct xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager_v1;
     struct frog_color_management_factory_v1 *frog_color_management_factory_v1;
+    struct wp_color_manager_v1 *wp_color_manager_v1;
     struct zwp_tablet_manager_v2 *tablet_manager;
 
     struct xkb_context *xkb_context;
@@ -102,6 +103,7 @@ struct SDL_DisplayData
     SDL_VideoData *videodata;
     struct wl_output *output;
     struct zxdg_output_v1 *xdg_output;
+    struct wp_color_management_output_v1 *wp_color_management_output;
     char *wl_output_name;
     double scale_factor;
     uint32_t registry_id;
@@ -111,6 +113,8 @@ struct SDL_DisplayData
     SDL_DisplayOrientation orientation;
     int physical_width_mm, physical_height_mm;
     bool has_logical_position, has_logical_size;
+    bool running_colorspace_event_queue;
+    SDL_HDROutputProperties HDR;
     SDL_DisplayID display;
     SDL_VideoDisplay placeholder;
     int wl_output_done_count;

+ 54 - 1
src/video/wayland/SDL_waylandwindow.c

@@ -23,6 +23,8 @@
 
 #ifdef SDL_VIDEO_DRIVER_WAYLAND
 
+#include <sys/mman.h>
+
 #include "../SDL_sysvideo.h"
 #include "../../events/SDL_events_c.h"
 #include "../../core/unix/SDL_appid.h"
@@ -31,6 +33,7 @@
 #include "SDL_waylandwindow.h"
 #include "SDL_waylandvideo.h"
 #include "../../SDL_hints_c.h"
+#include "SDL_waylandcolor.h"
 
 #include "alpha-modifier-v1-client-protocol.h"
 #include "xdg-shell-client-protocol.h"
@@ -43,6 +46,7 @@
 #include "xdg-dialog-v1-client-protocol.h"
 #include "frog-color-management-v1-client-protocol.h"
 #include "xdg-toplevel-icon-v1-client-protocol.h"
+#include "color-management-v1-client-protocol.h"
 
 #ifdef HAVE_LIBDECOR_H
 #include <libdecor.h>
@@ -1647,6 +1651,28 @@ static const struct frog_color_managed_surface_listener frog_surface_listener =
     frog_preferred_metadata_handler
 };
 
+static void feedback_surface_preferred_changed(void *data,
+                                               struct wp_color_management_surface_feedback_v1 *wp_color_management_surface_feedback_v1,
+                                               uint32_t identity)
+{
+    SDL_WindowData *wind = (SDL_WindowData *)data;
+    Wayland_ColorInfo info;
+    SDL_zero(info);
+
+    if (Wayland_GetColorInfoForWindow(wind, &info)) {
+        SDL_SetWindowHDRProperties(wind->sdlwindow, &info.HDR, true);
+        if (info.icc_size) {
+            wind->icc_fd = info.icc_fd;
+            wind->icc_size = info.icc_size;
+            SDL_SendWindowEvent(wind->sdlwindow, SDL_EVENT_WINDOW_ICCPROF_CHANGED, 0, 0);
+        }
+    }
+}
+
+static const struct wp_color_management_surface_feedback_v1_listener color_management_surface_feedback_listener = {
+    feedback_surface_preferred_changed
+};
+
 static void SetKeyboardFocus(SDL_Window *window, bool set_focus)
 {
     SDL_Window *toplevel = window;
@@ -2593,7 +2619,10 @@ bool Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Proper
     }
 
     if (!custom_surface_role) {
-        if (c->frog_color_management_factory_v1) {
+        if (c->wp_color_manager_v1) {
+            data->wp_color_management_surface_feedback = wp_color_manager_v1_get_surface_feedback(c->wp_color_manager_v1, data->surface);
+            wp_color_management_surface_feedback_v1_add_listener(data->wp_color_management_surface_feedback, &color_management_surface_feedback_listener, data);
+        } else if (c->frog_color_management_factory_v1) {
             data->frog_color_managed_surface = frog_color_management_factory_v1_get_color_managed_surface(c->frog_color_management_factory_v1, data->surface);
             frog_color_managed_surface_add_listener(data->frog_color_managed_surface, &frog_surface_listener, data);
         }
@@ -2875,6 +2904,26 @@ bool Wayland_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surfa
     return true;
 }
 
+void *Wayland_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size)
+{
+    SDL_WindowData *wind = window->internal;
+    void *ret = NULL;
+
+    if (wind->icc_size > 0) {
+        void *icc_map = mmap(NULL, wind->icc_size, PROT_READ, MAP_PRIVATE, wind->icc_fd, 0);
+        if (icc_map != MAP_FAILED) {
+            ret = SDL_malloc(wind->icc_size);
+            if (ret) {
+                *size = wind->icc_size;
+                SDL_memcpy(ret, icc_map, *size);
+            }
+            munmap(icc_map, wind->icc_size);
+        }
+    }
+
+    return ret;
+}
+
 bool Wayland_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window)
 {
     SDL_WindowData *wind = window->internal;
@@ -2994,6 +3043,10 @@ void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
             frog_color_managed_surface_destroy(wind->frog_color_managed_surface);
         }
 
+        if (wind->wp_color_management_surface_feedback) {
+            wp_color_management_surface_feedback_v1_destroy(wind->wp_color_management_surface_feedback);
+        }
+
         SDL_free(wind->outputs);
         SDL_free(wind->app_id);
 

+ 4 - 0
src/video/wayland/SDL_waylandwindow.h

@@ -116,6 +116,7 @@ struct SDL_WindowData
     struct wp_alpha_modifier_surface_v1 *wp_alpha_modifier_surface_v1;
     struct xdg_toplevel_icon_v1 *xdg_toplevel_icon_v1;
     struct frog_color_managed_surface *frog_color_managed_surface;
+    struct wp_color_management_surface_feedback_v1 *wp_color_management_surface_feedback;
 
     SDL_AtomicInt swap_interval_ready;
 
@@ -184,6 +185,8 @@ struct SDL_WindowData
     int fullscreen_deadline_count;
     int maximized_restored_deadline_count;
     Uint64 last_focus_event_time_ns;
+    int icc_fd;
+    Uint32 icc_size;
     bool floating;
     bool suspended;
     bool resizing;
@@ -231,6 +234,7 @@ extern void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
 extern bool Wayland_SuspendScreenSaver(SDL_VideoDevice *_this);
 extern bool Wayland_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon);
 extern float Wayland_GetWindowContentScale(SDL_VideoDevice *_this, SDL_Window *window);
+extern void *Wayland_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size);
 
 extern bool Wayland_SetWindowHitTest(SDL_Window *window, bool enabled);
 extern bool Wayland_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation);

+ 1631 - 0
wayland-protocols/color-management-v1.xml

@@ -0,0 +1,1631 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="color_management_v1">
+  <copyright>
+    Copyright 2019 Sebastian Wick
+    Copyright 2019 Erwin Burema
+    Copyright 2020 AMD
+    Copyright 2020-2024 Collabora, Ltd.
+    Copyright 2024 Xaver Hugl
+    Copyright 2022-2025 Red Hat, Inc.
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice (including the next
+    paragraph) shall be included in all copies or substantial portions of the
+    Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+  </copyright>
+
+  <description summary="color management protocol">
+    The aim of the color management extension is to allow clients to know
+    the color properties of outputs, and to tell the compositor about the color
+    properties of their content on surfaces. Doing this enables a compositor
+    to perform automatic color management of content for different outputs
+    according to how content is intended to look like.
+
+    The color properties are represented as an image description object which
+    is immutable after it has been created. A wl_output always has an
+    associated image description that clients can observe. A wl_surface
+    always has an associated preferred image description as a hint chosen by
+    the compositor that clients can also observe. Clients can set an image
+    description on a wl_surface to denote the color characteristics of the
+    surface contents.
+
+    An image description includes SDR and HDR colorimetry and encoding, HDR
+    metadata, and viewing environment parameters. An image description does
+    not include the properties set through color-representation extension.
+    It is expected that the color-representation extension is used in
+    conjunction with the color management extension when necessary,
+    particularly with the YUV family of pixel formats.
+
+    Recommendation ITU-T H.273
+    "Coding-independent code points for video signal type identification"
+    shall be referred to as simply H.273 here.
+
+    The color-and-hdr repository
+    (https://gitlab.freedesktop.org/pq/color-and-hdr) contains
+    background information on the protocol design and legacy color management.
+    It also contains a glossary, learning resources for digital color, tools,
+    samples and more.
+
+    The terminology used in this protocol is based on common color science and
+    color encoding terminology where possible. The glossary in the color-and-hdr
+    repository shall be the authority on the definition of terms in this
+    protocol.
+
+    Warning! The protocol described in this file is currently in the testing
+    phase. Backward compatible changes may be added together with the
+    corresponding interface version bump. Backward incompatible changes can
+    only be done by creating a new major version of the extension.
+  </description>
+
+  <interface name="wp_color_manager_v1" version="1">
+    <description summary="color manager singleton">
+      A singleton global interface used for getting color management extensions
+      for wl_surface and wl_output objects, and for creating client defined
+      image description objects. The extension interfaces allow
+      getting the image description of outputs and setting the image
+      description of surfaces.
+
+      Compositors should never remove this global.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy the color manager">
+        Destroy the wp_color_manager_v1 object. This does not affect any other
+        objects in any way.
+      </description>
+    </request>
+
+    <enum name="error">
+      <entry name="unsupported_feature" value="0"
+             summary="request not supported"/>
+      <entry name="surface_exists" value="1"
+             summary="color management surface exists already"/>
+    </enum>
+
+    <enum name="render_intent">
+      <description summary="rendering intents">
+        See the ICC.1:2022 specification from the International Color Consortium
+        for more details about rendering intents.
+
+        The principles of ICC defined rendering intents apply with all types of
+        image descriptions, not only those with ICC file profiles.
+
+        Compositors must support the perceptual rendering intent. Other
+        rendering intents are optional.
+      </description>
+
+      <entry name="perceptual" value="0"
+             summary="perceptual"/>
+      <entry name="relative" value="1"
+             summary="media-relative colorimetric"/>
+      <entry name="saturation" value="2"
+             summary="saturation"/>
+      <entry name="absolute" value="3"
+             summary="ICC-absolute colorimetric"/>
+      <entry name="relative_bpc" value="4"
+             summary="media-relative colorimetric + black point compensation"/>
+    </enum>
+
+    <enum name="feature">
+      <description summary="compositor supported features"/>
+
+      <entry name="icc_v2_v4" value="0"
+             summary="create_icc_creator request"/>
+      <entry name="parametric" value="1"
+             summary="create_parametric_creator request"/>
+      <entry name="set_primaries" value="2"
+             summary="parametric set_primaries request"/>
+      <entry name="set_tf_power" value="3"
+             summary="parametric set_tf_power request"/>
+      <entry name="set_luminances" value="4"
+             summary="parametric set_luminances request"/>
+      <entry name="set_mastering_display_primaries" value="5">
+        <description summary="parametric set_mastering_display_primaries request">
+          The compositor supports set_mastering_display_primaries request with a
+          target color volume fully contained inside the primary color volume.
+        </description>
+      </entry>
+      <entry name="extended_target_volume" value="6">
+        <description summary="parametric target exceeds primary color volume">
+          The compositor additionally supports target color volumes that
+          extend outside of the primary color volume.
+
+          This can only be advertised if feature set_mastering_display_primaries
+          is supported as well.
+        </description>
+      </entry>
+      <entry name="windows_scrgb" value="7"
+             summary="get_windows_scrgb request"/>
+    </enum>
+
+    <enum name="primaries">
+      <description summary="named color primaries">
+        Named color primaries used to encode well-known sets of primaries. H.273
+        is the authority, when it comes to the exact values of primaries and
+        authoritative specifications, where an equivalent code point exists.
+
+        A value of 0 is invalid and will never be present in the list of enums.
+
+        Descriptions do list the specifications for convenience.
+      </description>
+
+      <entry name="srgb" value="1">
+        <description summary="Color primaries for the sRGB color space as defined by the BT.709 standard">
+          Color primaries as defined by
+          - Rec. ITU-R BT.709-6
+          - Rec. ITU-R BT.1361-0 conventional colour gamut system and extended
+            colour gamut system (historical)
+          - IEC 61966-2-1 sRGB or sYCC
+          - IEC 61966-2-4
+          - Society of Motion Picture and Television Engineers (SMPTE) RP 177
+            (1993) Annex B
+          Equivalent to H.273 ColourPrimaries code point 1.
+        </description>
+      </entry>
+      <entry name="pal_m" value="2">
+        <description summary="Color primaries for PAL-M as defined by the BT.470 standard">
+          Color primaries as defined by
+          - Rec. ITU-R BT.470-6 System M (historical)
+          - United States National Television System Committee 1953
+            Recommendation for transmission standards for color television
+          - United States Federal Communications Commission (2003) Title 47 Code
+            of Federal Regulations 73.682 (a)(20)
+          Equivalent to H.273 ColourPrimaries code point 4.
+        </description>
+      </entry>
+      <entry name="pal" value="3">
+        <description summary="Color primaries for PAL as defined by the BT.601 standard">
+          Color primaries as defined by
+          - Rec. ITU-R BT.470-6 System B, G (historical)
+          - Rec. ITU-R BT.601-7 625
+          - Rec. ITU-R BT.1358-0 625 (historical)
+          - Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM
+          Equivalent to H.273 ColourPrimaries code point 5.
+        </description>
+      </entry>
+      <entry name="ntsc" value="4">
+        <description summary="Color primaries for NTSC as defined by the BT.601 standard">
+          Color primaries as defined by
+          - Rec. ITU-R BT.601-7 525
+          - Rec. ITU-R BT.1358-1 525 or 625 (historical)
+          - Rec. ITU-R BT.1700-0 NTSC
+          - SMPTE 170M (2004)
+          - SMPTE 240M (1999) (historical)
+          Equivalent to H.273 ColourPrimaries code point 6 and 7.
+        </description>
+      </entry>
+      <entry name="generic_film" value="5">
+        <description summary="Generic film with colour filters using Illuminant C">
+          Color primaries as defined by H.273 for generic film.
+          Equivalent to H.273 ColourPrimaries code point 8.
+        </description>
+      </entry>
+      <entry name="bt2020" value="6">
+        <description summary="Color primaries as defined by the BT.2020 and BT.2100 standard">
+          Color primaries as defined by
+          - Rec. ITU-R BT.2020-2
+          - Rec. ITU-R BT.2100-0
+          Equivalent to H.273 ColourPrimaries code point 9.
+        </description>
+      </entry>
+      <entry name="cie1931_xyz" value="7">
+        <description summary="Color primaries of the full CIE 1931 XYZ color space">
+          Color primaries as defined as the maximum of the CIE 1931 XYZ color
+          space by
+          - SMPTE ST 428-1
+          - (CIE 1931 XYZ as in ISO 11664-1)
+          Equivalent to H.273 ColourPrimaries code point 10.
+        </description>
+      </entry>
+      <entry name="dci_p3" value="8">
+        <description summary="Color primaries of the DCI P3 color space as defined by the SMPTE RP 431 standard">
+          Color primaries as defined by Digital Cinema System and published in
+          SMPTE RP 431-2 (2011). Equivalent to H.273 ColourPrimaries code point
+          11.
+        </description>
+      </entry>
+      <entry name="display_p3" value="9">
+        <description summary="Color primaries of Display P3 variant of the DCI-P3 color space as defined by the SMPTE EG 432 standard">
+          Color primaries as defined by Digital Cinema System and published in
+          SMPTE EG 432-1 (2010).
+          Equivalent to H.273 ColourPrimaries code point 12.
+        </description>
+      </entry>
+      <entry name="adobe_rgb" value="10">
+        <description summary="Color primaries of the Adobe RGB color space as defined by the ISO 12640 standard">
+          Color primaries as defined by Adobe as "Adobe RGB" and later published
+          by ISO 12640-4 (2011).
+        </description>
+      </entry>
+    </enum>
+
+    <enum name="transfer_function">
+      <description summary="named transfer functions">
+        Named transfer functions used to represent well-known transfer
+        characteristics. H.273 is the authority, when it comes to the exact
+        formulas and authoritative specifications, where an equivalent code
+        point exists.
+
+        A value of 0 is invalid and will never be present in the list of enums.
+
+        Descriptions do list the specifications for convenience.
+      </description>
+
+      <entry name="bt1886" value="1">
+        <description summary="BT.1886 display transfer characteristic">
+          Rec. ITU-R BT.1886 is the display transfer characteristic assumed by
+          - Rec. ITU-R BT.601-7 525 and 625
+          - Rec. ITU-R BT.709-6
+          - Rec. ITU-R BT.2020-2
+          These recommendations are referred to by H.273 TransferCharacteristics
+          code points 1, 6, 14, and 15, which are all equivalent.
+
+          This TF implies these default luminances from Rec. ITU-R BT.2035:
+          - primary color volume minimum: 0.01 cd/m²
+          - primary color volume maximum: 100 cd/m²
+          - reference white: 100 cd/m²
+        </description>
+      </entry>
+      <entry name="gamma22" value="2">
+        <description summary="Assumed display gamma 2.2 transfer function">
+          Transfer characteristics as defined by
+          - Rec. ITU-R BT.470-6 System M (historical)
+          - United States National Television System Committee 1953
+            Recommendation for transmission standards for color television
+          - United States Federal Communications Commission (2003) Title 47 Code
+            of Federal Regulations 73.682 (a) (20)
+          - Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM
+          Equivalent to H.273 TransferCharacteristics code point 4.
+        </description>
+      </entry>
+      <entry name="gamma28" value="3">
+        <description summary="Assumed display gamma 2.8 transfer function">
+          Transfer characteristics as defined by
+          - Rec. ITU-R BT.470-6 System B, G (historical)
+          Equivalent to H.273 TransferCharacteristics code point 5.
+        </description>
+      </entry>
+      <entry name="st240" value="4">
+        <description summary="SMPTE ST 240 transfer function">
+          Transfer characteristics as defined by
+          - SMPTE ST 240 (1999)
+          Equivalent to H.273 TransferCharacteristics code point 7.
+        </description>
+      </entry>
+      <entry name="ext_linear" value="5">
+        <description summary="extended linear transfer function">
+          Linear transfer function defined over all real numbers.
+          Normalised electrical values are equal the normalised optical values.
+
+          The differences to H.273 TransferCharacteristics code point 8 are
+          the definition over all real numbers.
+        </description>
+      </entry>
+      <entry name="log_100" value="6">
+        <description summary="logarithmic 100:1 transfer function">
+          Logarithmic transfer characteristic (100:1 range).
+          Equivalent to H.273 TransferCharacteristics code point 9.
+        </description>
+      </entry>
+      <entry name="log_316" value="7">
+        <description summary="logarithmic (100*Sqrt(10) : 1) transfer function">
+          Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range).
+          Equivalent to H.273 TransferCharacteristics code point 10.
+        </description>
+      </entry>
+      <entry name="xvycc" value="8">
+        <description summary="IEC 61966-2-4 transfer function">
+          Transfer characteristics as defined by
+          - IEC 61966-2-4
+          Equivalent to H.273 TransferCharacteristics code point 11.
+        </description>
+      </entry>
+      <entry name="srgb" value="9">
+        <description summary="sRGB piece-wise transfer function">
+          Transfer characteristics as defined by
+          - IEC 61966-2-1 sRGB
+          Equivalent to H.273 TransferCharacteristics code point 13 with
+          MatrixCoefficients set to 0.
+        </description>
+      </entry>
+      <entry name="ext_srgb" value="10">
+        <description summary="Extended sRGB piece-wise transfer function">
+          Transfer characteristics as defined by
+          - IEC 61966-2-1 sYCC
+          Equivalent to H.273 TransferCharacteristics code point 13 with
+          MatrixCoefficients set to anything but 0.
+        </description>
+      </entry>
+      <entry name="st2084_pq" value="11">
+        <description summary="perceptual quantizer transfer function">
+          Transfer characteristics as defined by
+          - SMPTE ST 2084 (2014) for 10-, 12-, 14- and 16-bit systems
+          - Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system
+          Equivalent to H.273 TransferCharacteristics code point 16.
+
+          This TF implies these default luminances
+          - primary color volume minimum: 0.005 cd/m²
+          - primary color volume maximum: 10000 cd/m²
+          - reference white: 203 cd/m²
+
+          The difference between the primary color volume minimum and maximum
+          must be approximately 10000 cd/m² as that is the swing of the EOTF
+          defined by ST 2084 and BT.2100. The default value for the
+          reference white is a protocol addition: it is suggested by
+          Report ITU-R BT.2408-7 and is not part of ST 2084 or BT.2100.
+        </description>
+      </entry>
+      <entry name="st428" value="12">
+        <description summary="SMPTE ST 428 transfer function">
+          Transfer characteristics as defined by
+          - SMPTE ST 428-1 (2019)
+          Equivalent to H.273 TransferCharacteristics code point 17.
+        </description>
+      </entry>
+      <entry name="hlg" value="13">
+        <description summary="hybrid log-gamma transfer function">
+          Transfer characteristics as defined by
+          - ARIB STD-B67 (2015)
+          - Rec. ITU-R BT.2100-2 hybrid log-gamma (HLG) system
+          Equivalent to H.273 TransferCharacteristics code point 18.
+
+          This TF implies these default luminances
+          - primary color volume minimum: 0.005 cd/m²
+          - primary color volume maximum: 1000 cd/m²
+          - reference white: 203 cd/m²
+
+          HLG is a relative display-referred signal with a specified
+          non-linear mapping to the display peak luminance (the HLG OOTF).
+          All absolute luminance values used here for HLG assume a 1000 cd/m²
+          peak display.
+
+          The default value for the reference white is a protocol addition:
+          it is suggested by Report ITU-R BT.2408-7 and is not part of
+          ARIB STD-B67 or BT.2100.
+        </description>
+      </entry>
+    </enum>
+
+    <request name="get_output">
+      <description summary="create a color management interface for a wl_output">
+        This creates a new wp_color_management_output_v1 object for the
+        given wl_output.
+
+        See the wp_color_management_output_v1 interface for more details.
+      </description>
+
+      <arg name="id" type="new_id" interface="wp_color_management_output_v1"/>
+      <arg name="output" type="object" interface="wl_output"/>
+    </request>
+
+    <request name="get_surface">
+      <description summary="create a color management interface for a wl_surface">
+        If a wp_color_management_surface_v1 object already exists for the given
+        wl_surface, the protocol error surface_exists is raised.
+
+        This creates a new color wp_color_management_surface_v1 object for the
+        given wl_surface.
+
+        See the wp_color_management_surface_v1 interface for more details.
+      </description>
+
+      <arg name="id" type="new_id" interface="wp_color_management_surface_v1"/>
+      <arg name="surface" type="object" interface="wl_surface"/>
+    </request>
+
+    <request name="get_surface_feedback">
+      <description summary="create a color management feedback interface">
+        This creates a new color wp_color_management_surface_feedback_v1 object
+        for the given wl_surface.
+
+        See the wp_color_management_surface_feedback_v1 interface for more
+        details.
+      </description>
+
+      <arg name="id" type="new_id"
+           interface="wp_color_management_surface_feedback_v1"/>
+      <arg name="surface" type="object" interface="wl_surface"/>
+    </request>
+
+    <request name="create_icc_creator">
+      <description summary="make a new ICC-based image description creator object">
+        Makes a new ICC-based image description creator object with all
+        properties initially unset. The client can then use the object's
+        interface to define all the required properties for an image description
+        and finally create a wp_image_description_v1 object.
+
+        This request can be used when the compositor advertises
+        wp_color_manager_v1.feature.icc_v2_v4.
+        Otherwise this request raises the protocol error unsupported_feature.
+      </description>
+
+      <arg name="obj"
+           type="new_id" interface="wp_image_description_creator_icc_v1"
+           summary="the new creator object"/>
+    </request>
+
+    <request name="create_parametric_creator">
+      <description summary="make a new parametric image description creator object">
+        Makes a new parametric image description creator object with all
+        properties initially unset. The client can then use the object's
+        interface to define all the required properties for an image description
+        and finally create a wp_image_description_v1 object.
+
+        This request can be used when the compositor advertises
+        wp_color_manager_v1.feature.parametric.
+        Otherwise this request raises the protocol error unsupported_feature.
+      </description>
+
+      <arg name="obj"
+           type="new_id" interface="wp_image_description_creator_params_v1"
+           summary="the new creator object"/>
+    </request>
+
+    <request name="create_windows_scrgb">
+      <description summary="create Windows-scRGB image description object">
+        This creates a pre-defined image description for the so-called
+        Windows-scRGB stimulus encoding. This comes from the Windows 10 handling
+        of its own definition of an scRGB color space for an HDR screen
+        driven in BT.2100/PQ signalling mode.
+
+        Windows-scRGB uses sRGB (BT.709) color primaries and white point.
+        The transfer characteristic is extended linear.
+
+        The nominal color channel value range is extended, meaning it includes
+        negative and greater than 1.0 values. Negative values are used to
+        escape the sRGB color gamut boundaries. To make use of the extended
+        range, the client needs to use a pixel format that can represent those
+        values, e.g. floating-point 16 bits per channel.
+
+        Nominal color value R=G=B=0.0 corresponds to BT.2100/PQ system
+        0 cd/m², and R=G=B=1.0 corresponds to BT.2100/PQ system 80 cd/m².
+        The maximum is R=G=B=125.0 corresponding to 10k cd/m².
+
+        Windows-scRGB is displayed by Windows 10 by converting it to
+        BT.2100/PQ, maintaining the CIE 1931 chromaticity and mapping the
+        luminance as above. No adjustment is made to the signal to account
+        for the viewing conditions.
+
+        The reference white level of Windows-scRGB is unknown. If a
+        reference white level must be assumed for compositor processing, it
+        should be R=G=B=2.5375 corresponding to 203 cd/m² of Report ITU-R
+        BT.2408-7.
+
+        The target color volume of Windows-scRGB is unknown. The color gamut
+        may be anything between sRGB and BT.2100.
+
+        Note: EGL_EXT_gl_colorspace_scrgb_linear definition differs from
+        Windows-scRGB by using R=G=B=1.0 as the reference white level, while
+        Windows-scRGB reference white level is unknown or varies. However,
+        it seems probable that Windows implements both
+        EGL_EXT_gl_colorspace_scrgb_linear and Vulkan
+        VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT as Windows-scRGB.
+
+        This request can be used when the compositor advertises
+        wp_color_manager_v1.feature.windows_scrgb.
+        Otherwise this request raises the protocol error unsupported_feature.
+
+        The resulting image description object does not allow get_information
+        request. The wp_image_description_v1.ready event shall be sent.
+      </description>
+
+      <arg name="image_description"
+           type="new_id" interface="wp_image_description_v1"/>
+    </request>
+
+    <event name="supported_intent">
+      <description summary="supported rendering intent">
+        When this object is created, it shall immediately send this event once
+        for each rendering intent the compositor supports.
+      </description>
+
+      <arg name="render_intent" type="uint" enum="render_intent"
+           summary="rendering intent"/>
+    </event>
+
+    <event name="supported_feature">
+      <description summary="supported features">
+        When this object is created, it shall immediately send this event once
+        for each compositor supported feature listed in the enumeration.
+      </description>
+
+      <arg name="feature" type="uint" enum="feature"
+           summary="supported feature"/>
+    </event>
+
+    <event name="supported_tf_named">
+      <description summary="supported named transfer characteristic">
+        When this object is created, it shall immediately send this event once
+        for each named transfer function the compositor supports with the
+        parametric image description creator.
+      </description>
+
+      <arg name="tf" type="uint" enum="transfer_function"
+           summary="Named transfer function"/>
+    </event>
+
+    <event name="supported_primaries_named">
+      <description summary="supported named primaries">
+        When this object is created, it shall immediately send this event once
+        for each named set of primaries the compositor supports with the
+        parametric image description creator.
+      </description>
+
+      <arg name="primaries" type="uint" enum="primaries"
+           summary="Named color primaries"/>
+    </event>
+
+    <event name="done">
+      <description summary="all features have been sent">
+        This event is sent when all supported rendering intents, features,
+        transfer functions and named primaries have been sent.
+      </description>
+    </event>
+  </interface>
+
+  <interface name="wp_color_management_output_v1" version="1">
+    <description summary="output color properties">
+      A wp_color_management_output_v1 describes the color properties of an
+      output.
+
+      The wp_color_management_output_v1 is associated with the wl_output global
+      underlying the wl_output object. Therefore the client destroying the
+      wl_output object has no impact, but the compositor removing the output
+      global makes the wp_color_management_output_v1 object inert.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy the color management output">
+        Destroy the color wp_color_management_output_v1 object. This does not
+        affect any remaining protocol objects.
+      </description>
+    </request>
+
+    <event name="image_description_changed">
+      <description summary="image description changed">
+        This event is sent whenever the image description of the output changed,
+        followed by one wl_output.done event common to output events across all
+        extensions.
+
+        If the client wants to use the updated image description, it needs to do
+        get_image_description again, because image description objects are
+        immutable.
+      </description>
+    </event>
+
+    <request name="get_image_description">
+      <description summary="get the image description of the output">
+        This creates a new wp_image_description_v1 object for the current image
+        description of the output. There always is exactly one image description
+        active for an output so the client should destroy the image description
+        created by earlier invocations of this request. This request is usually
+        sent as a reaction to the image_description_changed event or when
+        creating a wp_color_management_output_v1 object.
+
+        The image description of an output represents the color encoding the
+        output expects. There might be performance and power advantages, as well
+        as improved color reproduction, if a content update matches the image
+        description of the output it is being shown on. If a content update is
+        shown on any other output than the one it matches the image description
+        of, then the color reproduction on those outputs might be considerably
+        worse.
+
+        The created wp_image_description_v1 object preserves the image
+        description of the output from the time the object was created.
+
+        The resulting image description object allows get_information request.
+
+        If this protocol object is inert, the resulting image description object
+        shall immediately deliver the wp_image_description_v1.failed event with
+        the no_output cause.
+
+        If the interface version is inadequate for the output's image
+        description, meaning that the client does not support all the events
+        needed to deliver the crucial information, the resulting image
+        description object shall immediately deliver the
+        wp_image_description_v1.failed event with the low_version cause.
+
+        Otherwise the object shall immediately deliver the ready event.
+      </description>
+
+      <arg name="image_description"
+           type="new_id" interface="wp_image_description_v1"/>
+    </request>
+  </interface>
+
+  <interface name="wp_color_management_surface_v1" version="1">
+    <description summary="color management extension to a surface">
+        A wp_color_management_surface_v1 allows the client to set the color
+        space and HDR properties of a surface.
+
+        If the wl_surface associated with the wp_color_management_surface_v1 is
+        destroyed, the wp_color_management_surface_v1 object becomes inert.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy the color management interface for a surface">
+        Destroy the wp_color_management_surface_v1 object and do the same as
+        unset_image_description.
+      </description>
+    </request>
+
+    <enum name="error">
+      <description summary="protocol errors"/>
+      <entry name="render_intent" value="0"
+             summary="unsupported rendering intent"/>
+      <entry name="image_description" value="1"
+             summary="invalid image description"/>
+      <entry name="inert" value="2"
+             summary="forbidden request on inert object"/>
+    </enum>
+
+    <request name="set_image_description">
+      <description summary="set the surface image description">
+        If this protocol object is inert, the protocol error inert is raised.
+
+        Set the image description of the underlying surface. The image
+        description and rendering intent are double-buffered state, see
+        wl_surface.commit.
+
+        It is the client's responsibility to understand the image description
+        it sets on a surface, and to provide content that matches that image
+        description. Compositors might convert images to match their own or any
+        other image descriptions.
+
+        Image descriptions which are not ready (see wp_image_description_v1)
+        are forbidden in this request, and in such case the protocol error
+        image_description is raised.
+
+        All image descriptions which are ready (see wp_image_description_v1)
+        are allowed and must always be accepted by the compositor.
+
+        A rendering intent provides the client's preference on how content
+        colors should be mapped to each output. The render_intent value must
+        be one advertised by the compositor with
+        wp_color_manager_v1.render_intent event, otherwise the protocol error
+        render_intent is raised.
+
+        When an image description is set on a surface, the Transfer
+        Characteristics of the image description defines the valid range of
+        the nominal (real-valued) color channel values. The processing of
+        out-of-range color channel values is undefined, but compositors are
+        recommended to clamp the values to the valid range when possible.
+
+        By default, a surface does not have an associated image description
+        nor a rendering intent. The handling of color on such surfaces is
+        compositor implementation defined. Compositors should handle such
+        surfaces as sRGB, but may handle them differently if they have specific
+        requirements.
+
+        Setting the image description has copy semantics; after this request,
+        the image description can be immediately destroyed without affecting
+        the pending state of the surface.
+      </description>
+
+      <arg name="image_description"
+           type="object" interface="wp_image_description_v1"/>
+      <arg name="render_intent"
+           type="uint" enum="wp_color_manager_v1.render_intent"
+           summary="rendering intent"/>
+    </request>
+
+    <request name="unset_image_description">
+      <description summary="remove the surface image description">
+        If this protocol object is inert, the protocol error inert is raised.
+
+        This request removes any image description from the surface. See
+        set_image_description for how a compositor handles a surface without
+        an image description. This is double-buffered state, see
+        wl_surface.commit.
+      </description>
+    </request>
+  </interface>
+
+  <interface name="wp_color_management_surface_feedback_v1" version="1">
+    <description summary="color management extension to a surface">
+        A wp_color_management_surface_feedback_v1 allows the client to get the
+        preferred image description of a surface.
+
+        If the wl_surface associated with this object is destroyed, the
+        wp_color_management_surface_feedback_v1 object becomes inert.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy the color management interface for a surface">
+        Destroy the wp_color_management_surface_feedback_v1 object.
+      </description>
+    </request>
+
+    <enum name="error">
+      <description summary="protocol errors"/>
+      <entry name="inert" value="0"
+             summary="forbidden request on inert object"/>
+      <entry name="unsupported_feature" value="1"
+             summary="attempted to use an unsupported feature"/>
+    </enum>
+
+    <event name="preferred_changed">
+      <description summary="the preferred image description changed">
+        The preferred image description is the one which likely has the most
+        performance and/or quality benefits for the compositor if used by the
+        client for its wl_surface contents. This event is sent whenever the
+        compositor changes the wl_surface's preferred image description.
+
+        This event sends the identity of the new preferred state as the argument,
+        so clients who are aware of the image description already can reuse it.
+        Otherwise, if the client client wants to know what the preferred image
+        description is, it shall use the get_preferred request.
+
+        The preferred image description is not automatically used for anything.
+        It is only a hint, and clients may set any valid image description with
+        set_image_description, but there might be performance and color accuracy
+        improvements by providing the wl_surface contents in the preferred
+        image description. Therefore clients that can, should render according
+        to the preferred image description
+      </description>
+
+      <arg name="identity" type="uint" summary="image description id number"/>
+    </event>
+
+    <request name="get_preferred">
+      <description summary="get the preferred image description">
+        If this protocol object is inert, the protocol error inert is raised.
+
+        The preferred image description represents the compositor's preferred
+        color encoding for this wl_surface at the current time. There might be
+        performance and power advantages, as well as improved color
+        reproduction, if the image description of a content update matches the
+        preferred image description.
+
+        This creates a new wp_image_description_v1 object for the currently
+        preferred image description for the wl_surface. The client should
+        stop using and destroy the image descriptions created by earlier
+        invocations of this request for the associated wl_surface.
+        This request is usually sent as a reaction to the preferred_changed
+        event or when creating a wp_color_management_surface_feedback_v1 object
+        if the client is capable of adapting to image descriptions.
+
+        The created wp_image_description_v1 object preserves the preferred image
+        description of the wl_surface from the time the object was created.
+
+        The resulting image description object allows get_information request.
+
+        If the image description is parametric, the client should set it on its
+        wl_surface only if the image description is an exact match with the
+        client content. Particularly if everything else matches, but the target
+        color volume is greater than what the client needs, the client should
+        create its own parameric image description with its exact parameters.
+
+        If the interface version is inadequate for the preferred image
+        description, meaning that the client does not support all the
+        events needed to deliver the crucial information, the resulting image
+        description object shall immediately deliver the
+        wp_image_description_v1.failed event with the low_version cause,
+        otherwise the object shall immediately deliver the ready event.
+      </description>
+
+      <arg name="image_description"
+           type="new_id" interface="wp_image_description_v1"/>
+    </request>
+
+    <request name="get_preferred_parametric">
+      <description summary="get the preferred image description">
+        The same description as for get_preferred applies, except the returned
+        image description is guaranteed to be parametric. This is meant for
+        clients that can only deal with parametric image descriptions.
+
+        If the compositor doesn't support parametric image descriptions, the
+        unsupported_feature error is emitted.
+      </description>
+
+      <arg name="image_description"
+           type="new_id" interface="wp_image_description_v1"/>
+    </request>
+  </interface>
+
+  <interface name="wp_image_description_creator_icc_v1" version="1">
+    <description summary="holder of image description ICC information">
+      This type of object is used for collecting all the information required
+      to create a wp_image_description_v1 object from an ICC file. A complete
+      set of required parameters consists of these properties:
+      - ICC file
+
+      Each required property must be set exactly once if the client is to create
+      an image description. The set requests verify that a property was not
+      already set. The create request verifies that all required properties are
+      set. There may be several alternative requests for setting each property,
+      and in that case the client must choose one of them.
+
+      Once all properties have been set, the create request must be used to
+      create the image description object, destroying the creator in the
+      process.
+    </description>
+
+    <enum name="error">
+      <description summary="protocol errors"/>
+
+      <entry name="incomplete_set" value="0"
+             summary="incomplete parameter set"/>
+      <entry name="already_set" value="1"
+             summary="property already set"/>
+      <entry name="bad_fd" value="2"
+             summary="fd not seekable and readable"/>
+      <entry name="bad_size" value="3"
+             summary="no or too much data"/>
+      <entry name="out_of_file" value="4"
+             summary="offset + length exceeds file size"/>
+    </enum>
+
+    <request name="create" type="destructor">
+      <description summary="Create the image description object from ICC data">
+        Create an image description object based on the ICC information
+        previously set on this object. A compositor must parse the ICC data in
+        some undefined but finite amount of time.
+
+        The completeness of the parameter set is verified. If the set is not
+        complete, the protocol error incomplete_set is raised. For the
+        definition of a complete set, see the description of this interface.
+
+        If the particular combination of the information is not supported
+        by the compositor, the resulting image description object shall
+        immediately deliver the wp_image_description_v1.failed event with the
+        'unsupported' cause. If a valid image description was created from the
+        information, the wp_image_description_v1.ready event will eventually
+        be sent instead.
+
+        This request destroys the wp_image_description_creator_icc_v1 object.
+
+        The resulting image description object does not allow get_information
+        request.
+      </description>
+
+      <arg name="image_description"
+           type="new_id" interface="wp_image_description_v1"/>
+    </request>
+
+    <request name="set_icc_file">
+      <description summary="set the ICC profile file">
+        Sets the ICC profile file to be used as the basis of the image
+        description.
+
+        The data shall be found through the given fd at the given offset, having
+        the given length. The fd must be seekable and readable. Violating these
+        requirements raises the bad_fd protocol error.
+
+        If reading the data fails due to an error independent of the client, the
+        compositor shall send the wp_image_description_v1.failed event on the
+        created wp_image_description_v1 with the 'operating_system' cause.
+
+        The maximum size of the ICC profile is 32 MB. If length is greater than
+        that or zero, the protocol error bad_size is raised. If offset + length
+        exceeds the file size, the protocol error out_of_file is raised.
+
+        A compositor may read the file at any time starting from this request
+        and only until whichever happens first:
+        - If create request was issued, the wp_image_description_v1 object
+          delivers either failed or ready event; or
+        - if create request was not issued, this
+          wp_image_description_creator_icc_v1 object is destroyed.
+
+        A compositor shall not modify the contents of the file, and the fd may
+        be sealed for writes and size changes. The client must ensure to its
+        best ability that the data does not change while the compositor is
+        reading it.
+
+        The data must represent a valid ICC profile. The ICC profile version
+        must be 2 or 4, it must be a 3 channel profile and the class must be
+        Display or ColorSpace. Violating these requirements will not result in a
+        protocol error, but will eventually send the
+        wp_image_description_v1.failed event on the created
+        wp_image_description_v1 with the 'unsupported' cause.
+
+        See the International Color Consortium specification ICC.1:2022 for more
+        details about ICC profiles.
+
+        If ICC file has already been set on this object, the protocol error
+        already_set is raised.
+      </description>
+
+      <arg name="icc_profile" type="fd"
+           summary="ICC profile"/>
+      <arg name="offset" type="uint"
+           summary="byte offset in fd to start of ICC data"/>
+      <arg name="length" type="uint"
+           summary="length of ICC data in bytes"/>
+    </request>
+  </interface>
+
+  <interface name="wp_image_description_creator_params_v1" version="1">
+    <description summary="holder of image description parameters">
+      This type of object is used for collecting all the parameters required
+      to create a wp_image_description_v1 object. A complete set of required
+      parameters consists of these properties:
+      - transfer characteristic function (tf)
+      - chromaticities of primaries and white point (primary color volume)
+
+      The following properties are optional and have a well-defined default
+      if not explicitly set:
+      - primary color volume luminance range
+      - reference white luminance level
+      - mastering display primaries and white point (target color volume)
+      - mastering luminance range
+
+      The following properties are optional and will be ignored
+      if not explicitly set:
+      - maximum content light level
+      - maximum frame-average light level
+
+      Each required property must be set exactly once if the client is to create
+      an image description. The set requests verify that a property was not
+      already set. The create request verifies that all required properties are
+      set. There may be several alternative requests for setting each property,
+      and in that case the client must choose one of them.
+
+      Once all properties have been set, the create request must be used to
+      create the image description object, destroying the creator in the
+      process.
+    </description>
+
+    <enum name="error">
+      <description summary="protocol errors"/>
+
+      <entry name="incomplete_set" value="0"
+             summary="incomplete parameter set"/>
+      <entry name="already_set" value="1"
+             summary="property already set"/>
+      <entry name="unsupported_feature" value="2"
+             summary="request not supported"/>
+      <entry name="invalid_tf" value="3"
+             summary="invalid transfer characteristic"/>
+      <entry name="invalid_primaries_named" value="4"
+             summary="invalid primaries named"/>
+      <entry name="invalid_luminance" value="5"
+             summary="invalid luminance value or range"/>
+    </enum>
+
+    <request name="create" type="destructor">
+      <description summary="Create the image description object using params">
+        Create an image description object based on the parameters previously
+        set on this object.
+
+        The completeness of the parameter set is verified. If the set is not
+        complete, the protocol error incomplete_set is raised. For the
+        definition of a complete set, see the description of this interface.
+
+        The protocol error invalid_luminance is raised if any of the following
+        requirements is not met:
+        - When max_cll is set, it must be greater than min L and less or equal
+          to max L of the mastering luminance range.
+        - When max_fall is set, it must be greater than min L and less or equal
+          to max L of the mastering luminance range.
+        - When both max_cll and max_fall are set, max_fall must be less or equal
+          to max_cll.
+
+        If the particular combination of the parameter set is not supported
+        by the compositor, the resulting image description object shall
+        immediately deliver the wp_image_description_v1.failed event with the
+        'unsupported' cause. If a valid image description was created from the
+        parameter set, the wp_image_description_v1.ready event will eventually
+        be sent instead.
+
+        This request destroys the wp_image_description_creator_params_v1
+        object.
+
+        The resulting image description object does not allow get_information
+        request.
+      </description>
+
+      <arg name="image_description"
+           type="new_id" interface="wp_image_description_v1"/>
+    </request>
+
+    <request name="set_tf_named">
+      <description summary="named transfer characteristic">
+        Sets the transfer characteristic using explicitly enumerated named
+        functions.
+
+        When the resulting image description is attached to an image, the
+        content should be encoded and decoded according to the industry standard
+        practices for the transfer characteristic.
+
+        Only names advertised with wp_color_manager_v1 event supported_tf_named
+        are allowed. Other values shall raise the protocol error invalid_tf.
+
+        If transfer characteristic has already been set on this object, the
+        protocol error already_set is raised.
+      </description>
+
+      <arg name="tf" type="uint" enum="wp_color_manager_v1.transfer_function"
+           summary="named transfer function"/>
+    </request>
+
+    <request name="set_tf_power">
+      <description summary="transfer characteristic as a power curve">
+        Sets the color component transfer characteristic to a power curve with
+        the given exponent. Negative values are handled by mirroring the
+        positive half of the curve through the origin. The valid domain and
+        range of the curve are all finite real numbers. This curve represents
+        the conversion from electrical to optical color channel values.
+
+        When the resulting image description is attached to an image, the
+        content should be encoded with the inverse of the power curve.
+
+        The curve exponent shall be multiplied by 10000 to get the argument eexp
+        value to carry the precision of 4 decimals.
+
+        The curve exponent must be at least 1.0 and at most 10.0. Otherwise the
+        protocol error invalid_tf is raised.
+
+        If transfer characteristic has already been set on this object, the
+        protocol error already_set is raised.
+
+        This request can be used when the compositor advertises
+        wp_color_manager_v1.feature.set_tf_power. Otherwise this request raises
+        the protocol error unsupported_feature.
+      </description>
+
+      <arg name="eexp" type="uint" summary="the exponent * 10000"/>
+    </request>
+
+    <request name="set_primaries_named">
+      <description summary="named primaries">
+        Sets the color primaries and white point using explicitly named sets.
+        This describes the primary color volume which is the basis for color
+        value encoding.
+
+        Only names advertised with wp_color_manager_v1 event
+        supported_primaries_named are allowed. Other values shall raise the
+        protocol error invalid_primaries_named.
+
+        If primaries have already been set on this object, the protocol error
+        already_set is raised.
+      </description>
+
+      <arg name="primaries" type="uint" enum="wp_color_manager_v1.primaries"
+           summary="named primaries"/>
+    </request>
+
+    <request name="set_primaries">
+      <description summary="primaries as chromaticity coordinates">
+        Sets the color primaries and white point using CIE 1931 xy chromaticity
+        coordinates. This describes the primary color volume which is the basis
+        for color value encoding.
+
+        Each coordinate value is multiplied by 1 million to get the argument
+        value to carry precision of 6 decimals.
+
+        If primaries have already been set on this object, the protocol error
+        already_set is raised.
+
+        This request can be used if the compositor advertises
+        wp_color_manager_v1.feature.set_primaries. Otherwise this request raises
+        the protocol error unsupported_feature.
+      </description>
+
+      <arg name="r_x" type="int" summary="Red x * 1M"/>
+      <arg name="r_y" type="int" summary="Red y * 1M"/>
+      <arg name="g_x" type="int" summary="Green x * 1M"/>
+      <arg name="g_y" type="int" summary="Green y * 1M"/>
+      <arg name="b_x" type="int" summary="Blue x * 1M"/>
+      <arg name="b_y" type="int" summary="Blue y * 1M"/>
+      <arg name="w_x" type="int" summary="White x * 1M"/>
+      <arg name="w_y" type="int" summary="White y * 1M"/>
+    </request>
+
+    <request name="set_luminances">
+      <description summary="primary color volume luminance range and reference white">
+        Sets the primary color volume luminance range and the reference white
+        luminance level. These values include the minimum display emission
+        and ambient flare luminances, assumed to be optically additive and have
+        the chromaticity of the primary color volume white point.
+
+        The default luminances from
+        https://www.color.org/chardata/rgb/srgb.xalter are
+        - primary color volume minimum: 0.2 cd/m²
+        - primary color volume maximum: 80 cd/m²
+        - reference white: 80 cd/m²
+
+        Setting a named transfer characteristic can imply other default
+        luminances.
+
+        The default luminances get overwritten when this request is used.
+        With transfer_function.st2084_pq the given 'max_lum' value is ignored,
+        and 'max_lum' is taken as 'min_lum' + 10000 cd/m².
+
+        'min_lum' and 'max_lum' specify the minimum and maximum luminances of
+        the primary color volume as reproduced by the targeted display.
+
+        'reference_lum' specifies the luminance of the reference white as
+        reproduced by the targeted display, and reflects the targeted viewing
+        environment.
+
+        Compositors should make sure that all content is anchored, meaning that
+        an input signal level of 'reference_lum' on one image description and
+        another input signal level of 'reference_lum' on another image
+        description should produce the same output level, even though the
+        'reference_lum' on both image representations can be different.
+
+        'reference_lum' may be higher than 'max_lum'. In that case reaching
+        the reference white output level in image content requires the
+        'extended_target_volume' feature support.
+
+        If 'max_lum' or 'reference_lum' are less than or equal to 'min_lum',
+        the protocol error invalid_luminance is raised.
+
+        The minimum luminance is multiplied by 10000 to get the argument
+        'min_lum' value and carries precision of 4 decimals. The maximum
+        luminance and reference white luminance values are unscaled.
+
+        If the primary color volume luminance range and the reference white
+        luminance level have already been set on this object, the protocol error
+        already_set is raised.
+
+        This request can be used if the compositor advertises
+        wp_color_manager_v1.feature.set_luminances. Otherwise this request
+        raises the protocol error unsupported_feature.
+      </description>
+
+      <arg name="min_lum" type="uint"
+           summary="minimum luminance (cd/m²) * 10000"/>
+      <arg name="max_lum" type="uint"
+           summary="maximum luminance (cd/m²)"/>
+      <arg name="reference_lum" type="uint"
+           summary="reference white luminance (cd/m²)"/>
+    </request>
+
+    <request name="set_mastering_display_primaries">
+      <description summary="mastering display primaries as chromaticity coordinates">
+        Provides the color primaries and white point of the mastering display
+        using CIE 1931 xy chromaticity coordinates. This is compatible with the
+        SMPTE ST 2086 definition of HDR static metadata.
+
+        The mastering display primaries and mastering display luminances define
+        the target color volume.
+
+        If mastering display primaries are not explicitly set, the target color
+        volume is assumed to have the same primaries as the primary color volume.
+
+        The target color volume is defined by all tristimulus values between 0.0
+        and 1.0 (inclusive) of the color space defined by the given mastering
+        display primaries and white point. The colorimetry is identical between
+        the container color space and the mastering display color space,
+        including that no chromatic adaptation is applied even if the white
+        points differ.
+
+        The target color volume can exceed the primary color volume to allow for
+        a greater color volume with an existing color space definition (for
+        example scRGB). It can be smaller than the primary color volume to
+        minimize gamut and tone mapping distances for big color spaces (HDR
+        metadata).
+
+        To make use of the entire target color volume a suitable pixel format
+        has to be chosen (e.g. floating point to exceed the primary color
+        volume, or abusing limited quantization range as with xvYCC).
+
+        Each coordinate value is multiplied by 1 million to get the argument
+        value to carry precision of 6 decimals.
+
+        If mastering display primaries have already been set on this object, the
+        protocol error already_set is raised.
+
+        This request can be used if the compositor advertises
+        wp_color_manager_v1.feature.set_mastering_display_primaries. Otherwise
+        this request raises the protocol error unsupported_feature. The
+        advertisement implies support only for target color volumes fully
+        contained within the primary color volume.
+
+        If a compositor additionally supports target color volume exceeding the
+        primary color volume, it must advertise
+        wp_color_manager_v1.feature.extended_target_volume. If a client uses
+        target color volume exceeding the primary color volume and the
+        compositor does not support it, the result is implementation defined.
+        Compositors are recommended to detect this case and fail the image
+        description gracefully, but it may as well result in color artifacts.
+      </description>
+
+      <arg name="r_x" type="int" summary="Red x * 1M"/>
+      <arg name="r_y" type="int" summary="Red y * 1M"/>
+      <arg name="g_x" type="int" summary="Green x * 1M"/>
+      <arg name="g_y" type="int" summary="Green y * 1M"/>
+      <arg name="b_x" type="int" summary="Blue x * 1M"/>
+      <arg name="b_y" type="int" summary="Blue y * 1M"/>
+      <arg name="w_x" type="int" summary="White x * 1M"/>
+      <arg name="w_y" type="int" summary="White y * 1M"/>
+    </request>
+
+    <request name="set_mastering_luminance">
+      <description summary="display mastering luminance range">
+        Sets the luminance range that was used during the content mastering
+        process as the minimum and maximum absolute luminance L. These values
+        include the minimum display emission and ambient flare luminances,
+        assumed to be optically additive and have the chromaticity of the
+        primary color volume white point. This should be
+        compatible with the SMPTE ST 2086 definition of HDR static metadata.
+
+        The mastering display primaries and mastering display luminances define
+        the target color volume.
+
+        If mastering luminances are not explicitly set, the target color volume
+        is assumed to have the same min and max luminances as the primary color
+        volume.
+
+        If max L is less than or equal to min L, the protocol error
+        invalid_luminance is raised.
+
+        Min L value is multiplied by 10000 to get the argument min_lum value
+        and carry precision of 4 decimals. Max L value is unscaled for max_lum.
+
+        This request can be used if the compositor advertises
+        wp_color_manager_v1.feature.set_mastering_display_primaries. Otherwise
+        this request raises the protocol error unsupported_feature. The
+        advertisement implies support only for target color volumes fully
+        contained within the primary color volume.
+
+        If a compositor additionally supports target color volume exceeding the
+        primary color volume, it must advertise
+        wp_color_manager_v1.feature.extended_target_volume. If a client uses
+        target color volume exceeding the primary color volume and the
+        compositor does not support it, the result is implementation defined.
+        Compositors are recommended to detect this case and fail the image
+        description gracefully, but it may as well result in color artifacts.
+      </description>
+
+      <arg name="min_lum" type="uint" summary="min L (cd/m²) * 10000"/>
+      <arg name="max_lum" type="uint" summary="max L (cd/m²)"/>
+    </request>
+
+    <request name="set_max_cll">
+      <description summary="maximum content light level">
+        Sets the maximum content light level (max_cll) as defined by CTA-861-H.
+
+        max_cll is undefined by default.
+      </description>
+
+      <arg name="max_cll" type="uint" summary="Maximum content light level (cd/m²)"/>
+    </request>
+
+    <request name="set_max_fall">
+      <description summary="maximum frame-average light level">
+        Sets the maximum frame-average light level (max_fall) as defined by
+        CTA-861-H.
+
+        max_fall is undefined by default.
+      </description>
+
+      <arg name="max_fall" type="uint" summary="Maximum frame-average light level (cd/m²)"/>
+    </request>
+  </interface>
+
+  <interface name="wp_image_description_v1" version="1">
+    <description summary="Colorimetric image description">
+      An image description carries information about the color encoding used on
+      a surface when attached to a wl_surface via
+      wp_color_management_surface_v1.set_image_description. A compositor can use
+      this information to decode pixel values into colorimetrically meaningful
+      quantities.
+
+      Note, that the wp_image_description_v1 object is not ready to be used
+      immediately after creation. The object eventually delivers either the
+      'ready' or the 'failed' event, specified in all requests creating it. The
+      object is deemed "ready" after receiving the 'ready' event.
+
+      An object which is not ready is illegal to use, it can only be destroyed.
+      Any other request in this interface shall result in the 'not_ready'
+      protocol error. Attempts to use an object which is not ready through other
+      interfaces shall raise protocol errors defined there.
+
+      Once created and regardless of how it was created, a
+      wp_image_description_v1 object always refers to one fixed image
+      description. It cannot change after creation.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy the image description">
+        Destroy this object. It is safe to destroy an object which is not ready.
+
+        Destroying a wp_image_description_v1 object has no side-effects, not
+        even if a wp_color_management_surface_v1.set_image_description has not
+        yet been followed by a wl_surface.commit.
+      </description>
+    </request>
+
+    <enum name="error">
+      <description summary="protocol errors"/>
+
+      <entry name="not_ready" value="0"
+             summary="attempted to use an object which is not ready"/>
+      <entry name="no_information" value="1"
+             summary="get_information not allowed"/>
+    </enum>
+
+    <enum name="cause">
+      <description summary="generic reason for failure"/>
+
+      <entry name="low_version" value="0"
+             summary="interface version too low"/>
+      <entry name="unsupported" value="1"
+             summary="unsupported image description data"/>
+      <entry name="operating_system" value="2"
+             summary="error independent of the client"/>
+      <entry name="no_output" value="3"
+             summary="the relevant output no longer exists"/>
+    </enum>
+
+    <event name="failed">
+      <description summary="graceful error on creating the image description">
+        If creating a wp_image_description_v1 object fails for a reason that is
+        not defined as a protocol error, this event is sent.
+
+        The requests that create image description objects define whether and
+        when this can occur. Only such creation requests can trigger this event.
+        This event cannot be triggered after the image description was
+        successfully formed.
+
+        Once this event has been sent, the wp_image_description_v1 object will
+        never become ready and it can only be destroyed.
+      </description>
+
+      <arg name="cause" type="uint" enum="cause"
+           summary="generic reason"/>
+      <arg name="msg" type="string"
+           summary="ad hoc human-readable explanation"/>
+    </event>
+
+    <event name="ready">
+      <description summary="indication that the object is ready to be used">
+        Once this event has been sent, the wp_image_description_v1 object is
+        deemed "ready". Ready objects can be used to send requests and can be
+        used through other interfaces.
+
+        Every ready wp_image_description_v1 protocol object refers to an
+        underlying image description record in the compositor. Multiple protocol
+        objects may end up referring to the same record. Clients may identify
+        these "copies" by comparing their id numbers: if the numbers from two
+        protocol objects are identical, the protocol objects refer to the same
+        image description record. Two different image description records
+        cannot have the same id number simultaneously. The id number does not
+        change during the lifetime of the image description record.
+
+        The id number is valid only as long as the protocol object is alive. If
+        all protocol objects referring to the same image description record are
+        destroyed, the id number may be recycled for a different image
+        description record.
+
+        Image description id number is not a protocol object id. Zero is
+        reserved as an invalid id number. It shall not be possible for a client
+        to refer to an image description by its id number in protocol. The id
+        numbers might not be portable between Wayland connections. A compositor
+        shall not send an invalid id number.
+
+        This identity allows clients to de-duplicate image description records
+        and avoid get_information request if they already have the image
+        description information.
+      </description>
+
+      <arg name="identity" type="uint" summary="image description id number"/>
+    </event>
+
+    <request name="get_information">
+      <description summary="get information about the image description">
+        Creates a wp_image_description_info_v1 object which delivers the
+        information that makes up the image description.
+
+        Not all image description protocol objects allow get_information
+        request. Whether it is allowed or not is defined by the request that
+        created the object. If get_information is not allowed, the protocol
+        error no_information is raised.
+      </description>
+
+      <arg name="information"
+           type="new_id" interface="wp_image_description_info_v1"/>
+    </request>
+  </interface>
+
+  <interface name="wp_image_description_info_v1" version="1">
+    <description summary="Colorimetric image description information">
+      Sends all matching events describing an image description object exactly
+      once and finally sends the 'done' event.
+
+      This means
+      - if the image description is parametric, it must send
+        - primaries
+        - named_primaries, if applicable
+        - at least one of tf_power and tf_named, as applicable
+        - luminances
+        - target_primaries
+        - target_luminance
+      - if the image description is parametric, it may send, if applicable,
+        - target_max_cll
+        - target_max_fall
+      - if the image description contains an ICC profile, it must send the
+        icc_file event
+
+      Once a wp_image_description_info_v1 object has delivered a 'done' event it
+      is automatically destroyed.
+
+      Every wp_image_description_info_v1 created from the same
+      wp_image_description_v1 shall always return the exact same data.
+    </description>
+
+    <event name="done" type="destructor">
+      <description summary="end of information">
+        Signals the end of information events and destroys the object.
+      </description>
+    </event>
+
+    <event name="icc_file">
+      <description summary="ICC profile matching the image description">
+        The icc argument provides a file descriptor to the client which may be
+        memory-mapped to provide the ICC profile matching the image description.
+        The fd is read-only, and if mapped then it must be mapped with
+        MAP_PRIVATE by the client.
+
+        The ICC profile version and other details are determined by the
+        compositor. There is no provision for a client to ask for a specific
+        kind of a profile.
+      </description>
+
+      <arg name="icc" type="fd" summary="ICC profile file descriptor"/>
+      <arg name="icc_size" type="uint" summary="ICC profile size, in bytes"/>
+      <!-- Offset always 0, compositor must not expose unnecessary data. -->
+    </event>
+
+    <event name="primaries">
+      <description summary="primaries as chromaticity coordinates">
+        Delivers the primary color volume primaries and white point using CIE
+        1931 xy chromaticity coordinates.
+
+        Each coordinate value is multiplied by 1 million to get the argument
+        value to carry precision of 6 decimals.
+      </description>
+
+      <arg name="r_x" type="int" summary="Red x * 1M"/>
+      <arg name="r_y" type="int" summary="Red y * 1M"/>
+      <arg name="g_x" type="int" summary="Green x * 1M"/>
+      <arg name="g_y" type="int" summary="Green y * 1M"/>
+      <arg name="b_x" type="int" summary="Blue x * 1M"/>
+      <arg name="b_y" type="int" summary="Blue y * 1M"/>
+      <arg name="w_x" type="int" summary="White x * 1M"/>
+      <arg name="w_y" type="int" summary="White y * 1M"/>
+    </event>
+
+    <event name="primaries_named">
+      <description summary="named primaries">
+        Delivers the primary color volume primaries and white point using an
+        explicitly enumerated named set.
+      </description>
+
+      <arg name="primaries" type="uint" enum="wp_color_manager_v1.primaries"
+           summary="named primaries"/>
+    </event>
+
+    <event name="tf_power">
+      <description summary="transfer characteristic as a power curve">
+        The color component transfer characteristic of this image description is
+        a pure power curve. This event provides the exponent of the power
+        function. This curve represents the conversion from electrical to
+        optical pixel or color values.
+
+        The curve exponent has been multiplied by 10000 to get the argument eexp
+        value to carry the precision of 4 decimals.
+      </description>
+
+      <arg name="eexp" type="uint" summary="the exponent * 10000"/>
+    </event>
+
+    <event name="tf_named">
+      <description summary="named transfer characteristic">
+        Delivers the transfer characteristic using an explicitly enumerated
+        named function.
+      </description>
+
+      <arg name="tf" type="uint" enum="wp_color_manager_v1.transfer_function"
+           summary="named transfer function"/>
+    </event>
+
+    <event name="luminances">
+      <description summary="primary color volume luminance range and reference white">
+        Delivers the primary color volume luminance range and the reference
+        white luminance level. These values include the minimum display emission
+        and ambient flare luminances, assumed to be optically additive and have
+        the chromaticity of the primary color volume white point.
+
+        The minimum luminance is multiplied by 10000 to get the argument
+        'min_lum' value and carries precision of 4 decimals. The maximum
+        luminance and reference white luminance values are unscaled.
+      </description>
+
+      <arg name="min_lum" type="uint"
+           summary="minimum luminance (cd/m²) * 10000"/>
+      <arg name="max_lum" type="uint"
+           summary="maximum luminance (cd/m²)"/>
+      <arg name="reference_lum" type="uint"
+           summary="reference white luminance (cd/m²)"/>
+    </event>
+
+    <event name="target_primaries">
+      <description summary="target primaries as chromaticity coordinates">
+        Provides the color primaries and white point of the target color volume
+        using CIE 1931 xy chromaticity coordinates. This is compatible with the
+        SMPTE ST 2086 definition of HDR static metadata for mastering displays.
+
+        While primary color volume is about how color is encoded, the target
+        color volume is the actually displayable color volume. If target color
+        volume is equal to the primary color volume, then this event is not
+        sent.
+
+        Each coordinate value is multiplied by 1 million to get the argument
+        value to carry precision of 6 decimals.
+      </description>
+
+      <arg name="r_x" type="int" summary="Red x * 1M"/>
+      <arg name="r_y" type="int" summary="Red y * 1M"/>
+      <arg name="g_x" type="int" summary="Green x * 1M"/>
+      <arg name="g_y" type="int" summary="Green y * 1M"/>
+      <arg name="b_x" type="int" summary="Blue x * 1M"/>
+      <arg name="b_y" type="int" summary="Blue y * 1M"/>
+      <arg name="w_x" type="int" summary="White x * 1M"/>
+      <arg name="w_y" type="int" summary="White y * 1M"/>
+    </event>
+
+    <event name="target_luminance">
+      <description summary="target luminance range">
+        Provides the luminance range that the image description is targeting as
+        the minimum and maximum absolute luminance L. These values include the
+        minimum display emission and ambient flare luminances, assumed to be
+        optically additive and have the chromaticity of the primary color
+        volume white point. This should be compatible with the SMPTE ST 2086
+        definition of HDR static metadata.
+
+        This luminance range is only theoretical and may not correspond to the
+        luminance of light emitted on an actual display.
+
+        Min L value is multiplied by 10000 to get the argument min_lum value and
+        carry precision of 4 decimals. Max L value is unscaled for max_lum.
+      </description>
+
+      <arg name="min_lum" type="uint" summary="min L (cd/m²) * 10000"/>
+      <arg name="max_lum" type="uint" summary="max L (cd/m²)"/>
+    </event>
+
+    <event name="target_max_cll">
+      <description summary="target maximum content light level">
+        Provides the targeted max_cll of the image description. max_cll is
+        defined by CTA-861-H.
+
+        This luminance is only theoretical and may not correspond to the
+        luminance of light emitted on an actual display.
+      </description>
+
+      <arg name="max_cll" type="uint"
+           summary="Maximum content light-level (cd/m²)"/>
+    </event>
+
+    <event name="target_max_fall">
+      <description summary="target maximum frame-average light level">
+        Provides the targeted max_fall of the image description. max_fall is
+        defined by CTA-861-H.
+
+        This luminance is only theoretical and may not correspond to the
+        luminance of light emitted on an actual display.
+      </description>
+
+      <arg name="max_fall" type="uint"
+           summary="Maximum frame-average light level (cd/m²)"/>
+    </event>
+  </interface>
+</protocol>