mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-11-03 17:24:34 +00:00 
			
		
		
		
	video: Expose HDR metadata per-window
Moves the HDR properties from the display to be per-window, and adds the frog_color protocol to enable HDR under Wayland.
This commit is contained in:
		@@ -99,9 +99,8 @@ typedef enum SDL_EventType
 | 
			
		||||
    SDL_EVENT_DISPLAY_REMOVED,               /**< Display has been removed from the system */
 | 
			
		||||
    SDL_EVENT_DISPLAY_MOVED,                 /**< Display has changed position */
 | 
			
		||||
    SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, /**< Display has changed content scale */
 | 
			
		||||
    SDL_EVENT_DISPLAY_HDR_STATE_CHANGED,   /**< Display HDR properties have changed */
 | 
			
		||||
    SDL_EVENT_DISPLAY_FIRST = SDL_EVENT_DISPLAY_ORIENTATION,
 | 
			
		||||
    SDL_EVENT_DISPLAY_LAST = SDL_EVENT_DISPLAY_HDR_STATE_CHANGED,
 | 
			
		||||
    SDL_EVENT_DISPLAY_LAST = SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED,
 | 
			
		||||
 | 
			
		||||
    /* Window events */
 | 
			
		||||
    /* 0x200 was SDL_WINDOWEVENT, reserve the number for sdl2-compat */
 | 
			
		||||
@@ -134,6 +133,7 @@ typedef enum SDL_EventType
 | 
			
		||||
                                             associated with it are invalid */
 | 
			
		||||
    SDL_EVENT_WINDOW_PEN_ENTER,         /**< Window has gained focus of the pressure-sensitive pen with ID "data1" */
 | 
			
		||||
    SDL_EVENT_WINDOW_PEN_LEAVE,         /**< Window has lost focus of the pressure-sensitive pen with ID "data1" */
 | 
			
		||||
    SDL_EVENT_WINDOW_HDR_STATE_CHANGED, /**< Window HDR properties have changed */
 | 
			
		||||
    SDL_EVENT_WINDOW_FIRST = SDL_EVENT_WINDOW_SHOWN,
 | 
			
		||||
    SDL_EVENT_WINDOW_LAST = SDL_EVENT_WINDOW_PEN_LEAVE,
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -411,17 +411,9 @@ extern SDL_DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void);
 | 
			
		||||
 * The following read-only properties are provided by SDL:
 | 
			
		||||
 *
 | 
			
		||||
 * - `SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN`: true if the display has HDR
 | 
			
		||||
 *   headroom above the SDR white point. This property can change dynamically
 | 
			
		||||
 *   when SDL_EVENT_DISPLAY_HDR_STATE_CHANGED is sent.
 | 
			
		||||
 * - `SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT`: the value of SDR white in the
 | 
			
		||||
 *   SDL_COLORSPACE_SRGB_LINEAR colorspace. On Windows this corresponds to the
 | 
			
		||||
 *   SDR white level in scRGB colorspace, and on Apple platforms this is
 | 
			
		||||
 *   always 1.0 for EDR content. This property can change dynamically when
 | 
			
		||||
 *   SDL_EVENT_DISPLAY_HDR_STATE_CHANGED is sent.
 | 
			
		||||
 * - `SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT`: the additional high dynamic range
 | 
			
		||||
 *   that can be displayed, in terms of the SDR white point. When HDR is not
 | 
			
		||||
 *   enabled, this will be 1.0. This property can change dynamically when
 | 
			
		||||
 *   SDL_EVENT_DISPLAY_HDR_STATE_CHANGED is sent.
 | 
			
		||||
 *   headroom above the SDR white point. This is for informational and diagnostic
 | 
			
		||||
 *   purposes only, as not all platforms provide this information at the display
 | 
			
		||||
 *   level.
 | 
			
		||||
 *
 | 
			
		||||
 * On KMS/DRM:
 | 
			
		||||
 *
 | 
			
		||||
@@ -443,8 +435,6 @@ extern SDL_DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void);
 | 
			
		||||
extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetDisplayProperties(SDL_DisplayID displayID);
 | 
			
		||||
 | 
			
		||||
#define SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN             "SDL.display.HDR_enabled"
 | 
			
		||||
#define SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT           "SDL.display.SDR_white_point"
 | 
			
		||||
#define SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT              "SDL.display.HDR_headroom"
 | 
			
		||||
#define SDL_PROP_DISPLAY_KMSDRM_PANEL_ORIENTATION_NUMBER "SDL.display.KMSDRM.panel_orientation"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -1113,6 +1103,18 @@ extern SDL_DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window);
 | 
			
		||||
 *
 | 
			
		||||
 * - `SDL_PROP_WINDOW_SHAPE_POINTER`: the surface associated with a shaped
 | 
			
		||||
 *   window
 | 
			
		||||
 *  - `SDL_PROP_WINDOW_HDR_ENABLED_BOOLEAN`: true if the window has HDR
 | 
			
		||||
 *   headroom above the SDR white point. This property can change dynamically
 | 
			
		||||
 *   when SDL_EVENT_WINDOW_HDR_STATE_CHANGED is sent.
 | 
			
		||||
 * - `SDL_PROP_WINDOW_SDR_WHITE_LEVEL_FLOAT`: the value of SDR white in the
 | 
			
		||||
 *   SDL_COLORSPACE_SRGB_LINEAR colorspace. On Windows this corresponds to the
 | 
			
		||||
 *   SDR white level in scRGB colorspace, and on Apple platforms this is
 | 
			
		||||
 *   always 1.0 for EDR content. This property can change dynamically when
 | 
			
		||||
 *   SDL_EVENT_WINDOW_HDR_STATE_CHANGED is sent.
 | 
			
		||||
 * - `SDL_PROP_WINDOW_HDR_HEADROOM_FLOAT`: the additional high dynamic range
 | 
			
		||||
 *   that can be displayed, in terms of the SDR white point. When HDR is not
 | 
			
		||||
 *   enabled, this will be 1.0. This property can change dynamically when
 | 
			
		||||
 *   SDL_EVENT_WINDOW_HDR_STATE_CHANGED is sent.
 | 
			
		||||
 *
 | 
			
		||||
 * On Android:
 | 
			
		||||
 *
 | 
			
		||||
@@ -1216,6 +1218,9 @@ extern SDL_DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window);
 | 
			
		||||
extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window *window);
 | 
			
		||||
 | 
			
		||||
#define SDL_PROP_WINDOW_SHAPE_POINTER                               "SDL.window.shape"
 | 
			
		||||
#define SDL_PROP_WINDOW_HDR_ENABLED_BOOLEAN                         "SDL.window.HDR_enabled"
 | 
			
		||||
#define SDL_PROP_WINDOW_SDR_WHITE_LEVEL_FLOAT                       "SDL.window.SDR_white_level"
 | 
			
		||||
#define SDL_PROP_WINDOW_HDR_HEADROOM_FLOAT                          "SDL.window.HDR_headroom"
 | 
			
		||||
#define SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER                      "SDL.window.android.window"
 | 
			
		||||
#define SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER                     "SDL.window.android.surface"
 | 
			
		||||
#define SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER                        "SDL.window.uikit.window"
 | 
			
		||||
 
 | 
			
		||||
@@ -285,7 +285,6 @@ static void SDL_LogEvent(const SDL_Event *event)
 | 
			
		||||
        SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_REMOVED);
 | 
			
		||||
        SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_MOVED);
 | 
			
		||||
        SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED);
 | 
			
		||||
        SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_HDR_STATE_CHANGED);
 | 
			
		||||
#undef SDL_DISPLAYEVENT_CASE
 | 
			
		||||
 | 
			
		||||
#define SDL_WINDOWEVENT_CASE(x)                \
 | 
			
		||||
@@ -319,6 +318,7 @@ static void SDL_LogEvent(const SDL_Event *event)
 | 
			
		||||
        SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_ENTER_FULLSCREEN);
 | 
			
		||||
        SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_LEAVE_FULLSCREEN);
 | 
			
		||||
        SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DESTROYED);
 | 
			
		||||
        SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_HDR_STATE_CHANGED);
 | 
			
		||||
#undef SDL_WINDOWEVENT_CASE
 | 
			
		||||
 | 
			
		||||
#define PRINT_KEYDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u)", (uint)event->kdevice.timestamp, (uint)event->kdevice.which)
 | 
			
		||||
 
 | 
			
		||||
@@ -737,16 +737,11 @@ static void UpdateMainViewDimensions(SDL_Renderer *renderer)
 | 
			
		||||
 | 
			
		||||
static void UpdateHDRProperties(SDL_Renderer *renderer)
 | 
			
		||||
{
 | 
			
		||||
    SDL_DisplayID displayID = SDL_GetDisplayForWindow(renderer->window);
 | 
			
		||||
    SDL_PropertiesID display_props;
 | 
			
		||||
    SDL_PropertiesID window_props;
 | 
			
		||||
    SDL_PropertiesID renderer_props;
 | 
			
		||||
 | 
			
		||||
    if (!displayID) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    display_props = SDL_GetDisplayProperties(displayID);
 | 
			
		||||
    if (!display_props) {
 | 
			
		||||
    window_props = SDL_GetWindowProperties(renderer->window);
 | 
			
		||||
    if (!window_props) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -758,8 +753,8 @@ static void UpdateHDRProperties(SDL_Renderer *renderer)
 | 
			
		||||
    renderer->color_scale /= renderer->SDR_white_point;
 | 
			
		||||
 | 
			
		||||
    if (renderer->output_colorspace == SDL_COLORSPACE_SRGB_LINEAR) {
 | 
			
		||||
        renderer->SDR_white_point = SDL_GetFloatProperty(display_props, SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT, 1.0f);
 | 
			
		||||
        renderer->HDR_headroom = SDL_GetFloatProperty(display_props, SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT, 1.0f);
 | 
			
		||||
        renderer->SDR_white_point = SDL_GetFloatProperty(window_props, SDL_PROP_WINDOW_SDR_WHITE_LEVEL_FLOAT, 1.0f);
 | 
			
		||||
        renderer->HDR_headroom = SDL_GetFloatProperty(window_props, SDL_PROP_WINDOW_HDR_HEADROOM_FLOAT, 1.0f);
 | 
			
		||||
    } else {
 | 
			
		||||
        renderer->SDR_white_point = 1.0f;
 | 
			
		||||
        renderer->HDR_headroom = 1.0f;
 | 
			
		||||
@@ -836,7 +831,7 @@ static int SDLCALL SDL_RendererEventWatch(void *userdata, SDL_Event *event)
 | 
			
		||||
                UpdateHDRProperties(renderer);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else if (event->type == SDL_EVENT_DISPLAY_HDR_STATE_CHANGED) {
 | 
			
		||||
    } else if (event->type == SDL_EVENT_WINDOW_HDR_STATE_CHANGED) {
 | 
			
		||||
        UpdateHDRProperties(renderer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1576,12 +1576,6 @@ static void SDLTest_PrintEvent(const SDL_Event *event)
 | 
			
		||||
                    event->display.displayID, (int)(scale * 100.0f));
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case SDL_EVENT_DISPLAY_HDR_STATE_CHANGED:
 | 
			
		||||
        {
 | 
			
		||||
            SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " HDR %s",
 | 
			
		||||
                    event->display.displayID, event->display.data1 ? "enabled" : "disabled");
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case SDL_EVENT_DISPLAY_MOVED:
 | 
			
		||||
        SDL_Log("SDL EVENT: Display %" SDL_PRIu32 " changed position",
 | 
			
		||||
                event->display.displayID);
 | 
			
		||||
@@ -1668,6 +1662,9 @@ static void SDLTest_PrintEvent(const SDL_Event *event)
 | 
			
		||||
    case SDL_EVENT_WINDOW_DESTROYED:
 | 
			
		||||
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " destroyed", event->window.windowID);
 | 
			
		||||
        break;
 | 
			
		||||
    case SDL_EVENT_WINDOW_HDR_STATE_CHANGED:
 | 
			
		||||
        SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " HDR %s", event->window.windowID, event->window.data1 ? "enabled" : "disabled");
 | 
			
		||||
        break;
 | 
			
		||||
    case SDL_EVENT_KEYBOARD_ADDED:
 | 
			
		||||
        SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " attached",
 | 
			
		||||
                event->kdevice.which);
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,12 @@ typedef struct SDL_DisplayData SDL_DisplayData;
 | 
			
		||||
typedef struct SDL_DisplayModeData SDL_DisplayModeData;
 | 
			
		||||
typedef struct SDL_WindowData SDL_WindowData;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    float SDR_white_level;
 | 
			
		||||
    float HDR_headroom;
 | 
			
		||||
} SDL_HDROutputProperties;
 | 
			
		||||
 | 
			
		||||
/* Define the SDL window structure, corresponding to toplevel windows */
 | 
			
		||||
struct SDL_Window
 | 
			
		||||
{
 | 
			
		||||
@@ -82,6 +88,7 @@ struct SDL_Window
 | 
			
		||||
 | 
			
		||||
    SDL_DisplayMode requested_fullscreen_mode;
 | 
			
		||||
    SDL_DisplayMode current_fullscreen_mode;
 | 
			
		||||
    SDL_HDROutputProperties HDR;
 | 
			
		||||
 | 
			
		||||
    float opacity;
 | 
			
		||||
 | 
			
		||||
@@ -119,12 +126,6 @@ struct SDL_Window
 | 
			
		||||
#define SDL_WINDOW_IS_POPUP(W) \
 | 
			
		||||
    (((W)->flags & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU)) != 0)
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
    float SDR_white_point;
 | 
			
		||||
    float HDR_headroom;
 | 
			
		||||
} SDL_HDRDisplayProperties;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Define the SDL display structure.
 | 
			
		||||
 * This corresponds to physical monitors attached to the system.
 | 
			
		||||
@@ -141,7 +142,7 @@ struct SDL_VideoDisplay
 | 
			
		||||
    SDL_DisplayOrientation natural_orientation;
 | 
			
		||||
    SDL_DisplayOrientation current_orientation;
 | 
			
		||||
    float content_scale;
 | 
			
		||||
    SDL_HDRDisplayProperties HDR;
 | 
			
		||||
    SDL_HDROutputProperties HDR;
 | 
			
		||||
 | 
			
		||||
    SDL_Window *fullscreen_window;
 | 
			
		||||
 | 
			
		||||
@@ -160,7 +161,8 @@ typedef enum
 | 
			
		||||
    VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS = 0x04,
 | 
			
		||||
    VIDEO_DEVICE_CAPS_FULLSCREEN_ONLY = 0x08,
 | 
			
		||||
    VIDEO_DEVICE_CAPS_SENDS_DISPLAY_CHANGES = 0x10,
 | 
			
		||||
    VIDEO_DEVICE_CAPS_DISABLE_MOUSE_WARP_ON_FULLSCREEN_TRANSITIONS = 0x20
 | 
			
		||||
    VIDEO_DEVICE_CAPS_DISABLE_MOUSE_WARP_ON_FULLSCREEN_TRANSITIONS = 0x20,
 | 
			
		||||
    VIDEO_DEVICE_CAPS_SENDS_HDR_CHANGES = 0x40
 | 
			
		||||
} DeviceCaps;
 | 
			
		||||
 | 
			
		||||
/* Fullscreen operations */
 | 
			
		||||
@@ -511,7 +513,7 @@ extern void SDL_ResetFullscreenDisplayModes(SDL_VideoDisplay *display);
 | 
			
		||||
extern void SDL_SetDesktopDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode);
 | 
			
		||||
extern void SDL_SetCurrentDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode);
 | 
			
		||||
extern void SDL_SetDisplayContentScale(SDL_VideoDisplay *display, float scale);
 | 
			
		||||
extern void SDL_SetDisplayHDRProperties(SDL_VideoDisplay *display, const SDL_HDRDisplayProperties *HDR);
 | 
			
		||||
extern void SDL_SetDisplayHDRProperties(SDL_VideoDisplay *display, const SDL_HDROutputProperties *HDR);
 | 
			
		||||
extern int SDL_SetDisplayModeForDisplay(SDL_VideoDisplay *display, SDL_DisplayMode *mode);
 | 
			
		||||
extern SDL_VideoDisplay *SDL_GetVideoDisplay(SDL_DisplayID display);
 | 
			
		||||
extern SDL_DisplayID SDL_GetDisplayForWindowPosition(SDL_Window *window);
 | 
			
		||||
@@ -521,6 +523,7 @@ extern int SDL_GetDisplayIndex(SDL_DisplayID displayID);
 | 
			
		||||
extern SDL_DisplayData *SDL_GetDisplayDriverData(SDL_DisplayID display);
 | 
			
		||||
extern SDL_DisplayData *SDL_GetDisplayDriverDataForWindow(SDL_Window *window);
 | 
			
		||||
extern int SDL_GetMessageBoxCount(void);
 | 
			
		||||
extern void SDL_SetWindowHDRProperties(SDL_Window *window, const SDL_HDROutputProperties *HDR, SDL_bool send_event);
 | 
			
		||||
 | 
			
		||||
extern void SDL_GL_DeduceMaxSupportedESProfile(int *major, int *minor);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -195,6 +195,11 @@ static SDL_bool SDL_DisableMouseWarpOnFullscreenTransitions(SDL_VideoDevice *_th
 | 
			
		||||
    return !!(_this->device_caps & VIDEO_DEVICE_CAPS_DISABLE_MOUSE_WARP_ON_FULLSCREEN_TRANSITIONS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static SDL_bool SDL_DriverSendsHDRChanges(SDL_VideoDevice *_this)
 | 
			
		||||
{
 | 
			
		||||
    return !!(_this->device_caps & VIDEO_DEVICE_CAPS_SENDS_HDR_CHANGES);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Hint to treat all window ops as synchronous */
 | 
			
		||||
static SDL_bool syncHint;
 | 
			
		||||
 | 
			
		||||
@@ -763,23 +768,11 @@ SDL_DisplayID SDL_AddVideoDisplay(const SDL_VideoDisplay *display, SDL_bool send
 | 
			
		||||
        new_display->fullscreen_modes[i].displayID = id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    props = SDL_GetDisplayProperties(id);
 | 
			
		||||
    new_display->HDR.HDR_headroom = SDL_max(display->HDR.HDR_headroom, 1.0f);
 | 
			
		||||
    new_display->HDR.SDR_white_level = SDL_max(display->HDR.SDR_white_level, 1.0f);
 | 
			
		||||
 | 
			
		||||
    if (display->HDR.HDR_headroom > 1.0f) {
 | 
			
		||||
        SDL_SetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_TRUE);
 | 
			
		||||
    } else {
 | 
			
		||||
        SDL_SetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE);
 | 
			
		||||
    }
 | 
			
		||||
    if (display->HDR.SDR_white_point <= 1.0f) {
 | 
			
		||||
        SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT, 1.0f);
 | 
			
		||||
    } else {
 | 
			
		||||
        SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT, display->HDR.SDR_white_point);
 | 
			
		||||
    }
 | 
			
		||||
    if (display->HDR.HDR_headroom <= 1.0f) {
 | 
			
		||||
        SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT, 1.0f);
 | 
			
		||||
    } else {
 | 
			
		||||
        SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT, display->HDR.HDR_headroom);
 | 
			
		||||
    }
 | 
			
		||||
    props = SDL_GetDisplayProperties(id);
 | 
			
		||||
    SDL_SetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, new_display->HDR.HDR_headroom > 1.0f);
 | 
			
		||||
 | 
			
		||||
    SDL_UpdateDesktopBounds();
 | 
			
		||||
 | 
			
		||||
@@ -1053,37 +1046,42 @@ float SDL_GetDisplayContentScale(SDL_DisplayID displayID)
 | 
			
		||||
    return display->content_scale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDL_SetDisplayHDRProperties(SDL_VideoDisplay *display, const SDL_HDRDisplayProperties *HDR)
 | 
			
		||||
void SDL_SetWindowHDRProperties(SDL_Window *window, const SDL_HDROutputProperties *HDR, SDL_bool send_event)
 | 
			
		||||
{
 | 
			
		||||
    if (window->HDR.HDR_headroom != HDR->HDR_headroom || window->HDR.SDR_white_level != window->HDR.SDR_white_level) {
 | 
			
		||||
        SDL_PropertiesID window_props = SDL_GetWindowProperties(window);
 | 
			
		||||
 | 
			
		||||
        SDL_SetFloatProperty(window_props, SDL_PROP_WINDOW_HDR_HEADROOM_FLOAT, SDL_max(HDR->HDR_headroom, 1.0f));
 | 
			
		||||
        SDL_SetFloatProperty(window_props, SDL_PROP_WINDOW_SDR_WHITE_LEVEL_FLOAT, SDL_max(HDR->SDR_white_level, 1.0f));
 | 
			
		||||
        SDL_SetBooleanProperty(window_props, SDL_PROP_WINDOW_HDR_ENABLED_BOOLEAN, HDR->HDR_headroom > 1.0f);
 | 
			
		||||
        SDL_copyp(&window->HDR, HDR);
 | 
			
		||||
 | 
			
		||||
        if (send_event) {
 | 
			
		||||
            SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_HDR_STATE_CHANGED, HDR->HDR_headroom > 1.0f, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDL_SetDisplayHDRProperties(SDL_VideoDisplay *display, const SDL_HDROutputProperties *HDR)
 | 
			
		||||
{
 | 
			
		||||
    SDL_PropertiesID props = SDL_GetDisplayProperties(display->id);
 | 
			
		||||
    SDL_bool changed = SDL_FALSE;
 | 
			
		||||
 | 
			
		||||
    if (HDR->SDR_white_point != display->HDR.SDR_white_point) {
 | 
			
		||||
        if (HDR->SDR_white_point <= 1.0f) {
 | 
			
		||||
            SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT, 1.0f);
 | 
			
		||||
        } else {
 | 
			
		||||
            SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT, HDR->SDR_white_point);
 | 
			
		||||
        }
 | 
			
		||||
    if (HDR->SDR_white_level != display->HDR.SDR_white_level) {
 | 
			
		||||
        display->HDR.SDR_white_level = SDL_max(HDR->SDR_white_level, 1.0f);
 | 
			
		||||
        changed = SDL_TRUE;
 | 
			
		||||
    }
 | 
			
		||||
    if (HDR->HDR_headroom != display->HDR.HDR_headroom) {
 | 
			
		||||
        if (HDR->HDR_headroom > 1.0f) {
 | 
			
		||||
            SDL_SetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_TRUE);
 | 
			
		||||
        } else {
 | 
			
		||||
            SDL_SetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE);
 | 
			
		||||
        }
 | 
			
		||||
        if (HDR->HDR_headroom <= 1.0f) {
 | 
			
		||||
            SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT, 1.0f);
 | 
			
		||||
        } else {
 | 
			
		||||
            SDL_SetFloatProperty(props, SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT, HDR->HDR_headroom);
 | 
			
		||||
        }
 | 
			
		||||
        display->HDR.HDR_headroom = SDL_max(HDR->HDR_headroom, 1.0f);
 | 
			
		||||
        changed = SDL_TRUE;
 | 
			
		||||
    }
 | 
			
		||||
    SDL_copyp(&display->HDR, HDR);
 | 
			
		||||
 | 
			
		||||
    if (changed) {
 | 
			
		||||
        SDL_bool enabled = SDL_GetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE);
 | 
			
		||||
        SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_HDR_STATE_CHANGED, enabled);
 | 
			
		||||
    if (changed && !SDL_DriverSendsHDRChanges(_this)) {
 | 
			
		||||
        for (SDL_Window *w = display->device->windows; w; w = w->next) {
 | 
			
		||||
            if (SDL_GetDisplayForWindow(w) == display->id) {
 | 
			
		||||
                SDL_SetWindowHDRProperties(w, &display->HDR, SDL_TRUE);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2247,8 +2245,10 @@ SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props)
 | 
			
		||||
    window->undefined_x = undefined_x;
 | 
			
		||||
    window->undefined_y = undefined_y;
 | 
			
		||||
 | 
			
		||||
    if (flags & SDL_WINDOW_FULLSCREEN || IsFullscreenOnly(_this)) {
 | 
			
		||||
    SDL_VideoDisplay *display = SDL_GetVideoDisplayForWindow(window);
 | 
			
		||||
    SDL_SetWindowHDRProperties(window, &display->HDR, SDL_FALSE);
 | 
			
		||||
 | 
			
		||||
    if (flags & SDL_WINDOW_FULLSCREEN || IsFullscreenOnly(_this)) {
 | 
			
		||||
        SDL_Rect bounds;
 | 
			
		||||
 | 
			
		||||
        SDL_GetDisplayBounds(display->id, &bounds);
 | 
			
		||||
 
 | 
			
		||||
@@ -290,9 +290,9 @@ static char *Cocoa_GetDisplayName(CGDirectDisplayID displayID)
 | 
			
		||||
    return displayName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Cocoa_GetHDRProperties(CGDirectDisplayID displayID, SDL_HDRDisplayProperties *HDR)
 | 
			
		||||
static void Cocoa_GetHDRProperties(CGDirectDisplayID displayID, SDL_HDROutputProperties *HDR)
 | 
			
		||||
{
 | 
			
		||||
    HDR->SDR_white_point = 1.0f;
 | 
			
		||||
    HDR->SDR_white_level = 1.0f;
 | 
			
		||||
    HDR->HDR_headroom = 1.0f;
 | 
			
		||||
 | 
			
		||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500 /* Added in the 10.15 SDK */
 | 
			
		||||
@@ -397,7 +397,7 @@ void Cocoa_InitModes(SDL_VideoDevice *_this)
 | 
			
		||||
 | 
			
		||||
void Cocoa_UpdateDisplays(SDL_VideoDevice *_this)
 | 
			
		||||
{
 | 
			
		||||
    SDL_HDRDisplayProperties HDR;
 | 
			
		||||
    SDL_HDROutputProperties HDR;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < _this->num_displays; ++i) {
 | 
			
		||||
 
 | 
			
		||||
@@ -242,7 +242,7 @@ int UIKit_AddDisplay(UIScreen *uiscreen, SDL_bool send_event)
 | 
			
		||||
    }
 | 
			
		||||
    display.desktop_mode = mode;
 | 
			
		||||
 | 
			
		||||
    display.HDR.SDR_white_point = 1.0f;
 | 
			
		||||
    display.HDR.SDR_white_level = 1.0f;
 | 
			
		||||
    display.HDR.HDR_headroom = 1.0f;
 | 
			
		||||
 | 
			
		||||
#ifndef SDL_PLATFORM_TVOS
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,7 @@
 | 
			
		||||
#include "alpha-modifier-v1-client-protocol.h"
 | 
			
		||||
#include "cursor-shape-v1-client-protocol.h"
 | 
			
		||||
#include "fractional-scale-v1-client-protocol.h"
 | 
			
		||||
#include "frog-color-management-v1-client-protocol.h"
 | 
			
		||||
#include "idle-inhibit-unstable-v1-client-protocol.h"
 | 
			
		||||
#include "input-timestamps-unstable-v1-client-protocol.h"
 | 
			
		||||
#include "kde-output-order-v1-client-protocol.h"
 | 
			
		||||
@@ -526,7 +527,8 @@ static SDL_VideoDevice *Wayland_CreateDevice(void)
 | 
			
		||||
                          VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT |
 | 
			
		||||
                          VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS |
 | 
			
		||||
                          VIDEO_DEVICE_CAPS_SENDS_DISPLAY_CHANGES |
 | 
			
		||||
                          VIDEO_DEVICE_CAPS_DISABLE_MOUSE_WARP_ON_FULLSCREEN_TRANSITIONS;
 | 
			
		||||
                          VIDEO_DEVICE_CAPS_DISABLE_MOUSE_WARP_ON_FULLSCREEN_TRANSITIONS |
 | 
			
		||||
                          VIDEO_DEVICE_CAPS_SENDS_HDR_CHANGES;
 | 
			
		||||
 | 
			
		||||
    return device;
 | 
			
		||||
}
 | 
			
		||||
@@ -1114,6 +1116,8 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
 | 
			
		||||
    } else if (SDL_strcmp(interface, "kde_output_order_v1") == 0) {
 | 
			
		||||
        d->kde_output_order = wl_registry_bind(d->registry, id, &kde_output_order_v1_interface, 1);
 | 
			
		||||
        kde_output_order_v1_add_listener(d->kde_output_order, &kde_output_order_listener, d);
 | 
			
		||||
    } 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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1384,6 +1388,11 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)
 | 
			
		||||
        data->kde_output_order = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (data->frog_color_management_factory_v1) {
 | 
			
		||||
        frog_color_management_factory_v1_destroy(data->frog_color_management_factory_v1);
 | 
			
		||||
        data->frog_color_management_factory_v1 = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (data->compositor) {
 | 
			
		||||
        wl_compositor_destroy(data->compositor);
 | 
			
		||||
        data->compositor = NULL;
 | 
			
		||||
 
 | 
			
		||||
@@ -83,6 +83,7 @@ struct SDL_VideoData
 | 
			
		||||
    struct xdg_wm_dialog_v1 *xdg_wm_dialog_v1;
 | 
			
		||||
    struct wp_alpha_modifier_v1 *wp_alpha_modifier_v1;
 | 
			
		||||
    struct kde_output_order_v1 *kde_output_order;
 | 
			
		||||
    struct frog_color_management_factory_v1 *frog_color_management_factory_v1;
 | 
			
		||||
 | 
			
		||||
    struct xkb_context *xkb_context;
 | 
			
		||||
    struct SDL_WaylandInput *input;
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,7 @@
 | 
			
		||||
#include "fractional-scale-v1-client-protocol.h"
 | 
			
		||||
#include "xdg-foreign-unstable-v2-client-protocol.h"
 | 
			
		||||
#include "xdg-dialog-v1-client-protocol.h"
 | 
			
		||||
#include "frog-color-management-v1-client-protocol.h"
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_LIBDECOR_H
 | 
			
		||||
#include <libdecor.h>
 | 
			
		||||
@@ -1486,6 +1487,47 @@ static const struct wp_fractional_scale_v1_listener fractional_scale_listener =
 | 
			
		||||
    handle_preferred_fractional_scale
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void frog_preferred_metadata_handler(void *data, struct frog_color_managed_surface *frog_color_managed_surface, uint32_t transfer_function,
 | 
			
		||||
                                            uint32_t output_display_primary_red_x, uint32_t output_display_primary_red_y,
 | 
			
		||||
                                            uint32_t output_display_primary_green_x, uint32_t output_display_primary_green_y,
 | 
			
		||||
                                            uint32_t output_display_primary_blue_x, uint32_t output_display_primary_blue_y,
 | 
			
		||||
                                            uint32_t output_white_point_x, uint32_t output_white_point_y,
 | 
			
		||||
                                            uint32_t max_luminance, uint32_t min_luminance,
 | 
			
		||||
                                            uint32_t max_full_frame_luminance)
 | 
			
		||||
{
 | 
			
		||||
    SDL_WindowData *wind = (SDL_WindowData *)data;
 | 
			
		||||
    SDL_HDROutputProperties HDR;
 | 
			
		||||
 | 
			
		||||
    SDL_zero(HDR);
 | 
			
		||||
 | 
			
		||||
    switch (transfer_function) {
 | 
			
		||||
    case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_ST2084_PQ:
 | 
			
		||||
        /* ITU-R BT.2408-7 (Sept 2023) has the reference PQ white level at 203 nits,
 | 
			
		||||
         * while older Dolby documentation claims a reference level of 100 nits.
 | 
			
		||||
         *
 | 
			
		||||
         * Use 203 nits for now.
 | 
			
		||||
         */
 | 
			
		||||
        HDR.HDR_headroom = max_luminance / 203.0f;
 | 
			
		||||
        break;
 | 
			
		||||
    case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_SCRGB_LINEAR:
 | 
			
		||||
        HDR.HDR_headroom = max_luminance / 80.0f;
 | 
			
		||||
        break;
 | 
			
		||||
    case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_UNDEFINED:
 | 
			
		||||
    case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_SRGB:
 | 
			
		||||
    case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_GAMMA_22:
 | 
			
		||||
    default:
 | 
			
		||||
        HDR.HDR_headroom = 1.0f;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    HDR.SDR_white_level = 1.0f;
 | 
			
		||||
    SDL_SetWindowHDRProperties(wind->sdlwindow, &HDR, SDL_TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct frog_color_managed_surface_listener frog_surface_listener = {
 | 
			
		||||
    frog_preferred_metadata_handler
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void SetKeyboardFocus(SDL_Window *window)
 | 
			
		||||
{
 | 
			
		||||
    SDL_Window *kb_focus = SDL_GetKeyboardFocus();
 | 
			
		||||
@@ -2366,10 +2408,17 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!custom_surface_role && c->wp_alpha_modifier_v1) {
 | 
			
		||||
    if (!custom_surface_role) {
 | 
			
		||||
        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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (c->wp_alpha_modifier_v1) {
 | 
			
		||||
            data->wp_alpha_modifier_surface_v1 = wp_alpha_modifier_v1_get_surface(c->wp_alpha_modifier_v1, data->surface);
 | 
			
		||||
            wp_alpha_modifier_surface_v1_set_multiplier(data->wp_alpha_modifier_surface_v1, SDL_MAX_UINT32);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Must be called before EGL configuration to set the drawable backbuffer size. */
 | 
			
		||||
    ConfigureWindowGeometry(window);
 | 
			
		||||
@@ -2701,6 +2750,10 @@ void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
 | 
			
		||||
            wp_alpha_modifier_surface_v1_destroy(wind->wp_alpha_modifier_surface_v1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (wind->frog_color_managed_surface) {
 | 
			
		||||
            frog_color_managed_surface_destroy(wind->frog_color_managed_surface);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SDL_free(wind->outputs);
 | 
			
		||||
        SDL_free(wind->app_id);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -98,6 +98,7 @@ struct SDL_WindowData
 | 
			
		||||
    struct zxdg_exported_v2 *exported;
 | 
			
		||||
    struct xdg_dialog_v1 *xdg_dialog_v1;
 | 
			
		||||
    struct wp_alpha_modifier_surface_v1 *wp_alpha_modifier_surface_v1;
 | 
			
		||||
    struct frog_color_managed_surface *frog_color_managed_surface;
 | 
			
		||||
 | 
			
		||||
    SDL_AtomicInt swap_interval_ready;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -443,7 +443,7 @@ static float WIN_GetSDRWhitePoint(SDL_VideoDevice *_this, HMONITOR hMonitor)
 | 
			
		||||
{
 | 
			
		||||
    DISPLAYCONFIG_PATH_INFO path_info;
 | 
			
		||||
    SDL_VideoData *videodata = _this->driverdata;
 | 
			
		||||
    float SDR_white_point = 1.0f;
 | 
			
		||||
    float SDR_white_level = 1.0f;
 | 
			
		||||
 | 
			
		||||
    if (WIN_GetMonitorPathInfo(videodata, hMonitor, &path_info)) {
 | 
			
		||||
        DISPLAYCONFIG_SDR_WHITE_LEVEL white_level;
 | 
			
		||||
@@ -456,13 +456,13 @@ static float WIN_GetSDRWhitePoint(SDL_VideoDevice *_this, HMONITOR hMonitor)
 | 
			
		||||
        /* WIN_GetMonitorPathInfo() succeeded: DisplayConfigGetDeviceInfo is not NULL */
 | 
			
		||||
        if (videodata->DisplayConfigGetDeviceInfo(&white_level.header) == ERROR_SUCCESS &&
 | 
			
		||||
            white_level.SDRWhiteLevel > 0) {
 | 
			
		||||
            SDR_white_point = (white_level.SDRWhiteLevel / 1000.0f);
 | 
			
		||||
            SDR_white_level = (white_level.SDRWhiteLevel / 1000.0f);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return SDR_white_point;
 | 
			
		||||
    return SDR_white_level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void WIN_GetHDRProperties(SDL_VideoDevice *_this, HMONITOR hMonitor, SDL_HDRDisplayProperties *HDR)
 | 
			
		||||
static void WIN_GetHDRProperties(SDL_VideoDevice *_this, HMONITOR hMonitor, SDL_HDROutputProperties *HDR)
 | 
			
		||||
{
 | 
			
		||||
    DXGI_OUTPUT_DESC1 desc;
 | 
			
		||||
 | 
			
		||||
@@ -470,8 +470,8 @@ static void WIN_GetHDRProperties(SDL_VideoDevice *_this, HMONITOR hMonitor, SDL_
 | 
			
		||||
 | 
			
		||||
    if (WIN_GetMonitorDESC1(hMonitor, &desc)) {
 | 
			
		||||
        if (desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
 | 
			
		||||
            HDR->SDR_white_point = WIN_GetSDRWhitePoint(_this, hMonitor);
 | 
			
		||||
            HDR->HDR_headroom = (desc.MaxLuminance / 80.0f) / HDR->SDR_white_point;
 | 
			
		||||
            HDR->SDR_white_level = WIN_GetSDRWhitePoint(_this, hMonitor);
 | 
			
		||||
            HDR->HDR_headroom = (desc.MaxLuminance / 80.0f) / HDR->SDR_white_level;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -529,7 +529,6 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI
 | 
			
		||||
            if (!_this->setting_display_mode) {
 | 
			
		||||
                SDL_VideoDisplay *existing_display = _this->displays[i];
 | 
			
		||||
                SDL_Rect bounds;
 | 
			
		||||
                SDL_HDRDisplayProperties HDR;
 | 
			
		||||
 | 
			
		||||
                SDL_ResetFullscreenDisplayModes(existing_display);
 | 
			
		||||
                SDL_SetDesktopDisplayMode(existing_display, &mode);
 | 
			
		||||
@@ -544,6 +543,7 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI
 | 
			
		||||
                SDL_SendDisplayEvent(existing_display, SDL_EVENT_DISPLAY_ORIENTATION, current_orientation);
 | 
			
		||||
                SDL_SetDisplayContentScale(existing_display, content_scale);
 | 
			
		||||
#ifdef HAVE_DXGI1_6_H
 | 
			
		||||
                SDL_HDROutputProperties HDR;
 | 
			
		||||
                WIN_GetHDRProperties(_this, hMonitor, &HDR);
 | 
			
		||||
                SDL_SetDisplayHDRProperties(existing_display, &HDR);
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -59,8 +59,8 @@ static void UpdateHDRState(void)
 | 
			
		||||
    SDL_PropertiesID props;
 | 
			
		||||
    SDL_bool HDR_enabled;
 | 
			
		||||
 | 
			
		||||
    props = SDL_GetDisplayProperties(SDL_GetDisplayForWindow(window));
 | 
			
		||||
    HDR_enabled = SDL_GetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE);
 | 
			
		||||
    props = SDL_GetWindowProperties(window);
 | 
			
		||||
    HDR_enabled = SDL_GetBooleanProperty(props, SDL_PROP_WINDOW_HDR_ENABLED_BOOLEAN, SDL_FALSE);
 | 
			
		||||
 | 
			
		||||
    SDL_Log("HDR %s\n", HDR_enabled ? "enabled" : "disabled");
 | 
			
		||||
 | 
			
		||||
@@ -523,7 +523,7 @@ static void loop(void)
 | 
			
		||||
            default:
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (event.type == SDL_EVENT_DISPLAY_HDR_STATE_CHANGED) {
 | 
			
		||||
        } else if (event.type == SDL_EVENT_WINDOW_HDR_STATE_CHANGED) {
 | 
			
		||||
            UpdateHDRState();
 | 
			
		||||
        } else if (event.type == SDL_EVENT_QUIT) {
 | 
			
		||||
            done = 1;
 | 
			
		||||
 
 | 
			
		||||
@@ -66,12 +66,14 @@ int main(int argc, char *argv[])
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < num_displays; i++) {
 | 
			
		||||
        SDL_DisplayID dpy = displays[i];
 | 
			
		||||
        SDL_PropertiesID props = SDL_GetDisplayProperties(dpy);
 | 
			
		||||
        SDL_Rect rect = { 0, 0, 0, 0 };
 | 
			
		||||
        int m, num_modes = 0;
 | 
			
		||||
        const SDL_bool has_HDR = SDL_GetBooleanProperty(props, SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE);
 | 
			
		||||
 | 
			
		||||
        SDL_GetDisplayBounds(dpy, &rect);
 | 
			
		||||
        modes = SDL_GetFullscreenDisplayModes(dpy, &num_modes);
 | 
			
		||||
        SDL_Log("%" SDL_PRIu32 ": \"%s\" (%dx%d at %d,%d), content scale %.2f, %d fullscreen modes.\n", dpy, SDL_GetDisplayName(dpy), rect.w, rect.h, rect.x, rect.y, SDL_GetDisplayContentScale(dpy), num_modes);
 | 
			
		||||
        SDL_Log("%" SDL_PRIu32 ": \"%s\" (%dx%d at %d,%d), content scale %.2f, %d fullscreen modes, HDR capable: %s.\n", dpy, SDL_GetDisplayName(dpy), rect.w, rect.h, rect.x, rect.y, SDL_GetDisplayContentScale(dpy), num_modes, has_HDR ? "yes" : "no");
 | 
			
		||||
 | 
			
		||||
        mode = SDL_GetCurrentDisplayMode(dpy);
 | 
			
		||||
        if (mode) {
 | 
			
		||||
 
 | 
			
		||||
@@ -155,7 +155,7 @@ static SDL_bool CreateWindowAndRenderer(SDL_WindowFlags window_flags, const char
 | 
			
		||||
    if (useVulkan) {
 | 
			
		||||
        SetupVulkanRenderProperties(vulkan_context, props);
 | 
			
		||||
    }
 | 
			
		||||
    if (SDL_GetBooleanProperty(SDL_GetDisplayProperties(SDL_GetDisplayForWindow(window)), SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE)) {
 | 
			
		||||
    if (SDL_GetBooleanProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_HDR_ENABLED_BOOLEAN, SDL_FALSE)) {
 | 
			
		||||
        /* Try to create an HDR capable renderer */
 | 
			
		||||
        SDL_SetNumberProperty(props, SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER, SDL_COLORSPACE_SRGB_LINEAR);
 | 
			
		||||
        renderer = SDL_CreateRendererWithProperties(props);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										356
									
								
								wayland-protocols/frog-color-management-v1.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										356
									
								
								wayland-protocols/frog-color-management-v1.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,356 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<protocol name="frog_color_management_v1">
 | 
			
		||||
 | 
			
		||||
  <copyright>
 | 
			
		||||
    Copyright © 2023 Joshua Ashton for Valve Software
 | 
			
		||||
    Copyright © 2023 Xaver Hugl
 | 
			
		||||
 | 
			
		||||
    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="experimental color management protocol">
 | 
			
		||||
    The aim of this color management extension is to get HDR games working quickly,
 | 
			
		||||
    and have an easy way to test implementations in the wild before the upstream
 | 
			
		||||
    protocol is ready to be merged.
 | 
			
		||||
    For that purpose it's intentionally limited and cut down and does not serve
 | 
			
		||||
    all uses cases.
 | 
			
		||||
  </description>
 | 
			
		||||
 | 
			
		||||
  <interface name="frog_color_management_factory_v1" version="1">
 | 
			
		||||
    <description summary="color management factory">
 | 
			
		||||
      The color management factory singleton creates color managed surface objects.
 | 
			
		||||
    </description>
 | 
			
		||||
 | 
			
		||||
    <request name="destroy" type="destructor"></request>
 | 
			
		||||
 | 
			
		||||
    <request name="get_color_managed_surface">
 | 
			
		||||
      <description summary="create color management interface for surface">
 | 
			
		||||
      </description>
 | 
			
		||||
 | 
			
		||||
      <arg name="surface" type="object" interface="wl_surface"
 | 
			
		||||
           summary="target surface"/>
 | 
			
		||||
      <arg name="callback" type="new_id" interface="frog_color_managed_surface"
 | 
			
		||||
           summary="new color managed surface object"/>
 | 
			
		||||
    </request>
 | 
			
		||||
  </interface>
 | 
			
		||||
 | 
			
		||||
  <interface name="frog_color_managed_surface" version="1">
 | 
			
		||||
    <description summary="color managed surface">
 | 
			
		||||
      Interface for changing surface color management and HDR state.
 | 
			
		||||
 | 
			
		||||
      An implementation must: support every part of the version
 | 
			
		||||
      of the frog_color_managed_surface interface it exposes.
 | 
			
		||||
      Including all known enums associated with a given version.
 | 
			
		||||
    </description>
 | 
			
		||||
 | 
			
		||||
    <request name="destroy" type="destructor">
 | 
			
		||||
      <description summary="destroy color managed surface">
 | 
			
		||||
        Destroying the color managed surface resets all known color
 | 
			
		||||
        state for the surface back to 'undefined' implementation-specific
 | 
			
		||||
        values.
 | 
			
		||||
      </description>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <enum name="transfer_function">
 | 
			
		||||
      <description summary="known transfer functions">
 | 
			
		||||
        Extended information on the transfer functions described
 | 
			
		||||
        here can be found in the Khronos Data Format specification:
 | 
			
		||||
 | 
			
		||||
        https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html
 | 
			
		||||
      </description>
 | 
			
		||||
      <entry name="undefined" value="0" summary="specifies undefined, implementation-specific handling of the surface's transfer function."/>
 | 
			
		||||
      <entry name="srgb" value="1" summary="specifies the sRGB non-linear EOTF. An implementation may: display this as Gamma 2.2 for the purposes of being consistent with content rendering across displays, rendering_intent and user expectations."/>
 | 
			
		||||
      <entry name="gamma_22" value="2" summary="specifies gamma 2.2 power curve as the EOTF"/>
 | 
			
		||||
      <entry name="st2084_pq" value="3" summary="specifies the SMPTE ST2084 Perceptual Quantizer (PQ) EOTF"/>
 | 
			
		||||
      <entry name="scrgb_linear" value="4" summary="specifies the scRGB (extended sRGB) linear EOTF. Note: Primaries outside the gamut triangle specified can be expressed with negative values for this transfer function."/>
 | 
			
		||||
    </enum>
 | 
			
		||||
 | 
			
		||||
    <request name="set_known_transfer_function">
 | 
			
		||||
      <description summary="sets a known transfer function for a surface"/>
 | 
			
		||||
      <arg name="transfer_function" type="uint" enum="transfer_function" summary="transfer function for the surface"/>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <enum name="primaries">
 | 
			
		||||
      <description summary="known primaries"/>
 | 
			
		||||
      <entry name="undefined" value="0" summary="specifies undefined, implementation-specific handling"/>
 | 
			
		||||
      <entry name="rec709" value="1" summary="specifies Rec.709/sRGB primaries with D65 white point"/>
 | 
			
		||||
      <entry name="rec2020" value="2" summary="specifies Rec.2020/HDR10 primaries with D65 white point"/>
 | 
			
		||||
    </enum>
 | 
			
		||||
 | 
			
		||||
    <request name="set_known_container_color_volume">
 | 
			
		||||
      <description summary="sets the container color volume (primaries) for a surface"/>
 | 
			
		||||
      <arg name="primaries" type="uint" enum="primaries" summary="primaries for the surface"/>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <enum name="render_intent">
 | 
			
		||||
      <description summary="known render intents">
 | 
			
		||||
        Extended information on render intents described
 | 
			
		||||
        here can be found in ICC.1:2022:
 | 
			
		||||
 | 
			
		||||
        https://www.color.org/specification/ICC.1-2022-05.pdf
 | 
			
		||||
      </description>
 | 
			
		||||
      <entry name="perceptual" value="0" summary="perceptual"/>
 | 
			
		||||
    </enum>
 | 
			
		||||
 | 
			
		||||
    <request name="set_render_intent">
 | 
			
		||||
      <description summary="sets the render intent for a surface">
 | 
			
		||||
        NOTE: On a surface with "perceptual" (default) render intent, handling of the container's color volume
 | 
			
		||||
        is implementation-specific, and may differ between different transfer functions it is paired with:
 | 
			
		||||
          ie. sRGB + 709 rendering may have it's primaries widened to more of the available display's gamut
 | 
			
		||||
              to be be more pleasing for the viewer.
 | 
			
		||||
              Compared to scRGB Linear + 709 being treated faithfully as 709
 | 
			
		||||
              (including utilizing negatives out of the 709 gamut triangle)
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="render_intent" type="uint" enum="render_intent" summary="render intent for the surface"/>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <request name="set_hdr_metadata">
 | 
			
		||||
      <description summary="set HDR metadata for a surface">
 | 
			
		||||
        Forwards HDR metadata from the client to the compositor.
 | 
			
		||||
 | 
			
		||||
        HDR Metadata Infoframe as per CTA 861.G spec.
 | 
			
		||||
 | 
			
		||||
        Usage of this HDR metadata is implementation specific and
 | 
			
		||||
        outside of the scope of this protocol.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="mastering_display_primary_red_x" type="uint">
 | 
			
		||||
        <description summary="red primary x coordinate">
 | 
			
		||||
          Mastering Red Color Primary X Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          Coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="mastering_display_primary_red_y" type="uint">
 | 
			
		||||
        <description summary="red primary y coordinate">
 | 
			
		||||
          Mastering Red Color Primary Y Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          Coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="mastering_display_primary_green_x" type="uint">
 | 
			
		||||
        <description summary="green primary x coordinate">
 | 
			
		||||
          Mastering Green Color Primary X Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          Coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="mastering_display_primary_green_y" type="uint">
 | 
			
		||||
        <description summary="green primary y coordinate">
 | 
			
		||||
          Mastering Green Color Primary Y Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          Coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="mastering_display_primary_blue_x" type="uint">
 | 
			
		||||
        <description summary="blue primary x coordinate">
 | 
			
		||||
          Mastering Blue Color Primary X Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          Coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="mastering_display_primary_blue_y" type="uint">
 | 
			
		||||
        <description summary="blue primary y coordinate">
 | 
			
		||||
          Mastering Blue Color Primary Y Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          Coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="mastering_white_point_x" type="uint">
 | 
			
		||||
        <description summary="white point x coordinate">
 | 
			
		||||
          Mastering White Point X Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          These are coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="mastering_white_point_y" type="uint">
 | 
			
		||||
        <description summary="white point y coordinate">
 | 
			
		||||
          Mastering White Point Y Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          These are coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="max_display_mastering_luminance" type="uint">
 | 
			
		||||
        <description summary="max display mastering luminance">
 | 
			
		||||
          Max Mastering Display Luminance.
 | 
			
		||||
          This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
 | 
			
		||||
          where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="min_display_mastering_luminance" type="uint">
 | 
			
		||||
        <description summary="min display mastering luminance">
 | 
			
		||||
          Min Mastering Display Luminance.
 | 
			
		||||
          This value is coded as an unsigned 16-bit value in units of
 | 
			
		||||
          0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF
 | 
			
		||||
          represents 6.5535 cd/m2.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="max_cll" type="uint">
 | 
			
		||||
        <description summary="max content light level">
 | 
			
		||||
          Max Content Light Level.
 | 
			
		||||
          This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
 | 
			
		||||
          where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="max_fall" type="uint">
 | 
			
		||||
        <description summary="max frame average light level">
 | 
			
		||||
          Max Frame Average Light Level.
 | 
			
		||||
          This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
 | 
			
		||||
          where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <event name="preferred_metadata">
 | 
			
		||||
      <description summary="preferred metadata for a surface">
 | 
			
		||||
        Current preferred metadata for a surface.
 | 
			
		||||
        The application should use this information to tone-map its buffers
 | 
			
		||||
        to this target before committing.
 | 
			
		||||
 | 
			
		||||
        This metadata does not necessarily correspond to any physical output, but
 | 
			
		||||
        rather what the compositor thinks would be best for a given surface.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="transfer_function" type="uint" enum="transfer_function">
 | 
			
		||||
        <description summary="output's current transfer function">
 | 
			
		||||
          Specifies a known transfer function that corresponds to the
 | 
			
		||||
          output the surface is targeting.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="output_display_primary_red_x" type="uint">
 | 
			
		||||
        <description summary="red primary x coordinate">
 | 
			
		||||
          Output Red Color Primary X Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          Coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="output_display_primary_red_y" type="uint">
 | 
			
		||||
        <description summary="red primary y coordinate">
 | 
			
		||||
          Output Red Color Primary Y Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          Coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="output_display_primary_green_x" type="uint">
 | 
			
		||||
        <description summary="green primary x coordinate">
 | 
			
		||||
          Output Green Color Primary X Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          Coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="output_display_primary_green_y" type="uint">
 | 
			
		||||
        <description summary="green primary y coordinate">
 | 
			
		||||
          Output Green Color Primary Y Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          Coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="output_display_primary_blue_x" type="uint">
 | 
			
		||||
        <description summary="blue primary x coordinate">
 | 
			
		||||
          Output Blue Color Primary X Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          Coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="output_display_primary_blue_y" type="uint">
 | 
			
		||||
        <description summary="blue primary y coordinate">
 | 
			
		||||
          Output Blue Color Primary Y Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          Coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="output_white_point_x" type="uint">
 | 
			
		||||
        <description summary="white point x coordinate">
 | 
			
		||||
          Output White Point X Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          These are coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="output_white_point_y" type="uint">
 | 
			
		||||
        <description summary="white point y coordinate">
 | 
			
		||||
          Output White Point Y Coordinate of the Data.
 | 
			
		||||
 | 
			
		||||
          These are coded as unsigned 16-bit values in units of
 | 
			
		||||
          0.00002, where 0x0000 represents zero and 0xC350
 | 
			
		||||
          represents 1.0000.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="max_luminance" type="uint">
 | 
			
		||||
        <description summary="maximum luminance">
 | 
			
		||||
          Max Output Luminance
 | 
			
		||||
          The max luminance in nits that the output is capable of rendering in small areas.
 | 
			
		||||
          Content should: not exceed this value to avoid clipping.
 | 
			
		||||
 | 
			
		||||
          This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
 | 
			
		||||
          where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="min_luminance" type="uint">
 | 
			
		||||
        <description summary="minimum luminance">
 | 
			
		||||
          Min Output Luminance
 | 
			
		||||
          The min luminance that the output is capable of rendering.
 | 
			
		||||
          Content should: not exceed this value to avoid clipping.
 | 
			
		||||
 | 
			
		||||
          This value is coded as an unsigned 16-bit value in units of
 | 
			
		||||
          0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF
 | 
			
		||||
          represents 6.5535 cd/m2.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
      <arg name="max_full_frame_luminance" type="uint">
 | 
			
		||||
        <description summary="maximum full frame luminance">
 | 
			
		||||
          Max Full Frame Luminance
 | 
			
		||||
          The max luminance in nits that the output is capable of rendering for the
 | 
			
		||||
          full frame sustained.
 | 
			
		||||
 | 
			
		||||
          This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
 | 
			
		||||
          where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
 | 
			
		||||
        </description>
 | 
			
		||||
      </arg>
 | 
			
		||||
    </event>
 | 
			
		||||
  </interface>
 | 
			
		||||
</protocol>
 | 
			
		||||
		Reference in New Issue
	
	Block a user