mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-21 09:11:49 +00:00
wayland: Add color manager protocol support
Support the official wp_color_manager_v1 protocol.
This commit is contained in:
224
src/video/wayland/SDL_waylandcolor.c
Normal file
224
src/video/wayland/SDL_waylandcolor.c
Normal file
@@ -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
src/video/wayland/SDL_waylandcolor.h
Normal file
41
src/video/wayland/SDL_waylandcolor.h
Normal file
@@ -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_
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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
wayland-protocols/color-management-v1.xml
Normal file
1631
wayland-protocols/color-management-v1.xml
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user