Skip to content

Commit fadb261

Browse files
committed
wayland: Add color manager protocol support
Support the official wp_color_manager_v1 protocol.
1 parent 6ef687c commit fadb261

7 files changed

+2022
-6
lines changed

src/video/wayland/SDL_waylandcolor.c

+224
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/*
2+
Simple DirectMedia Layer
3+
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
4+
5+
This software is provided 'as-is', without any express or implied
6+
warranty. In no event will the authors be held liable for any damages
7+
arising from the use of this software.
8+
9+
Permission is granted to anyone to use this software for any purpose,
10+
including commercial applications, and to alter it and redistribute it
11+
freely, subject to the following restrictions:
12+
13+
1. The origin of this software must not be misrepresented; you must not
14+
claim that you wrote the original software. If you use this software
15+
in a product, an acknowledgment in the product documentation would be
16+
appreciated but is not required.
17+
2. Altered source versions must be plainly marked as such, and must not be
18+
misrepresented as being the original software.
19+
3. This notice may not be removed or altered from any source distribution.
20+
*/
21+
22+
#include "SDL_internal.h"
23+
24+
#ifdef SDL_VIDEO_DRIVER_WAYLAND
25+
26+
#include "SDL_waylandcolor.h"
27+
#include "SDL_waylandvideo.h"
28+
#include "SDL_waylandwindow.h"
29+
#include "color-management-v1-client-protocol.h"
30+
31+
typedef struct Wayland_ColorInfoState
32+
{
33+
struct wp_image_description_v1 *wp_image_description;
34+
struct wp_image_description_info_v1 *wp_image_description_info;
35+
Wayland_ColorInfo *info;
36+
37+
bool result;
38+
} Wayland_ColorInfoState;
39+
40+
static void image_description_info_handle_done(void *data,
41+
struct wp_image_description_info_v1 *wp_image_description_info_v1)
42+
{
43+
Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
44+
45+
if (state->wp_image_description_info) {
46+
wp_image_description_info_v1_destroy(state->wp_image_description_info);
47+
state->wp_image_description_info = NULL;
48+
}
49+
if (state->wp_image_description) {
50+
wp_image_description_v1_destroy(state->wp_image_description);
51+
state->wp_image_description = NULL;
52+
}
53+
54+
state->result = true;
55+
}
56+
57+
static void image_description_info_handle_icc_file(void *data,
58+
struct wp_image_description_info_v1 *wp_image_description_info_v1,
59+
int32_t icc, uint32_t icc_size)
60+
{
61+
Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
62+
63+
state->info->icc_fd = icc;
64+
state->info->icc_size = icc_size;
65+
}
66+
67+
static void image_description_info_handle_primaries(void *data,
68+
struct wp_image_description_info_v1 *wp_image_description_info_v1,
69+
int32_t r_x, int32_t r_y,
70+
int32_t g_x, int32_t g_y,
71+
int32_t b_x, int32_t b_y,
72+
int32_t w_x, int32_t w_y)
73+
{
74+
// NOP
75+
}
76+
77+
static void image_description_info_handle_primaries_named(void *data,
78+
struct wp_image_description_info_v1 *wp_image_description_info_v1,
79+
uint32_t primaries)
80+
{
81+
// NOP
82+
}
83+
84+
static void image_description_info_handle_tf_power(void *data,
85+
struct wp_image_description_info_v1 *wp_image_description_info_v1,
86+
uint32_t eexp)
87+
{
88+
// NOP
89+
}
90+
91+
static void image_description_info_handle_tf_named(void *data,
92+
struct wp_image_description_info_v1 *wp_image_description_info_v1,
93+
uint32_t tf)
94+
{
95+
// NOP
96+
}
97+
98+
static void image_description_info_handle_luminances(void *data,
99+
struct wp_image_description_info_v1 *wp_image_description_info_v1,
100+
uint32_t min_lum,
101+
uint32_t max_lum,
102+
uint32_t reference_lum)
103+
{
104+
Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
105+
state->info->HDR.HDR_headroom = (float)max_lum / (float)reference_lum;
106+
}
107+
108+
static void image_description_info_handle_target_primaries(void *data,
109+
struct wp_image_description_info_v1 *wp_image_description_info_v1,
110+
int32_t r_x, int32_t r_y,
111+
int32_t g_x, int32_t g_y,
112+
int32_t b_x, int32_t b_y,
113+
int32_t w_x, int32_t w_y)
114+
{
115+
// NOP
116+
}
117+
118+
static void image_description_info_handle_target_luminance(void *data,
119+
struct wp_image_description_info_v1 *wp_image_description_info_v1,
120+
uint32_t min_lum,
121+
uint32_t max_lum)
122+
{
123+
// NOP
124+
}
125+
126+
static void image_description_info_handle_target_max_cll(void *data,
127+
struct wp_image_description_info_v1 *wp_image_description_info_v1,
128+
uint32_t max_cll)
129+
{
130+
// NOP
131+
}
132+
133+
static void image_description_info_handle_target_max_fall(void *data,
134+
struct wp_image_description_info_v1 *wp_image_description_info_v1,
135+
uint32_t max_fall)
136+
{
137+
// NOP
138+
}
139+
140+
static const struct wp_image_description_info_v1_listener image_description_info_listener = {
141+
image_description_info_handle_done,
142+
image_description_info_handle_icc_file,
143+
image_description_info_handle_primaries,
144+
image_description_info_handle_primaries_named,
145+
image_description_info_handle_tf_power,
146+
image_description_info_handle_tf_named,
147+
image_description_info_handle_luminances,
148+
image_description_info_handle_target_primaries,
149+
image_description_info_handle_target_luminance,
150+
image_description_info_handle_target_max_cll,
151+
image_description_info_handle_target_max_fall
152+
};
153+
154+
static void PumpColorspaceEvents(Wayland_ColorInfoState *state)
155+
{
156+
SDL_VideoData *vid = SDL_GetVideoDevice()->internal;
157+
158+
// Run the image description sequence to completion in its own queue.
159+
struct wl_event_queue *queue = WAYLAND_wl_display_create_queue(vid->display);
160+
WAYLAND_wl_proxy_set_queue((struct wl_proxy *)state->wp_image_description, queue);
161+
162+
while (state->wp_image_description) {
163+
WAYLAND_wl_display_dispatch_queue(vid->display, queue);
164+
}
165+
166+
WAYLAND_wl_event_queue_destroy(queue);
167+
}
168+
169+
static void image_description_handle_failed(void *data,
170+
struct wp_image_description_v1 *wp_image_description_v1,
171+
uint32_t cause,
172+
const char *msg)
173+
{
174+
Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
175+
176+
wp_image_description_v1_destroy(state->wp_image_description);
177+
state->wp_image_description = NULL;
178+
}
179+
180+
static void image_description_handle_ready(void *data,
181+
struct wp_image_description_v1 *wp_image_description_v1,
182+
uint32_t identity)
183+
{
184+
Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
185+
186+
// This will inherit the queue of the factory image description object.
187+
state->wp_image_description_info = wp_image_description_v1_get_information(state->wp_image_description);
188+
wp_image_description_info_v1_add_listener(state->wp_image_description_info, &image_description_info_listener, data);
189+
}
190+
191+
static const struct wp_image_description_v1_listener image_description_listener = {
192+
image_description_handle_failed,
193+
image_description_handle_ready
194+
};
195+
196+
bool Wayland_GetColorInfoForWindow(SDL_WindowData *window_data, Wayland_ColorInfo *info)
197+
{
198+
Wayland_ColorInfoState state;
199+
SDL_zero(state);
200+
state.info = info;
201+
202+
state.wp_image_description = wp_color_management_surface_feedback_v1_get_preferred(window_data->wp_color_management_surface_feedback);
203+
wp_image_description_v1_add_listener(state.wp_image_description, &image_description_listener, &state);
204+
205+
PumpColorspaceEvents(&state);
206+
207+
return state.result;
208+
}
209+
210+
bool Wayland_GetColorInfoForOutput(SDL_DisplayData *display_data, Wayland_ColorInfo *info)
211+
{
212+
Wayland_ColorInfoState state;
213+
SDL_zero(state);
214+
state.info = info;
215+
216+
state.wp_image_description = wp_color_management_output_v1_get_image_description(display_data->wp_color_management_output);
217+
wp_image_description_v1_add_listener(state.wp_image_description, &image_description_listener, &state);
218+
219+
PumpColorspaceEvents(&state);
220+
221+
return state.result;
222+
}
223+
224+
#endif // SDL_VIDEO_DRIVER_WAYLAND

src/video/wayland/SDL_waylandcolor.h

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
Simple DirectMedia Layer
3+
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
4+
5+
This software is provided 'as-is', without any express or implied
6+
warranty. In no event will the authors be held liable for any damages
7+
arising from the use of this software.
8+
9+
Permission is granted to anyone to use this software for any purpose,
10+
including commercial applications, and to alter it and redistribute it
11+
freely, subject to the following restrictions:
12+
13+
1. The origin of this software must not be misrepresented; you must not
14+
claim that you wrote the original software. If you use this software
15+
in a product, an acknowledgment in the product documentation would be
16+
appreciated but is not required.
17+
2. Altered source versions must be plainly marked as such, and must not be
18+
misrepresented as being the original software.
19+
3. This notice may not be removed or altered from any source distribution.
20+
*/
21+
22+
#include "SDL_internal.h"
23+
24+
#ifndef SDL_waylandcolor_h_
25+
#define SDL_waylandcolor_h_
26+
27+
#include "../SDL_sysvideo.h"
28+
29+
typedef struct Wayland_ColorInfo
30+
{
31+
SDL_HDROutputProperties HDR;
32+
33+
// The ICC fd is only valid if the size is non-zero.
34+
int icc_fd;
35+
Uint32 icc_size;
36+
} Wayland_ColorInfo;
37+
38+
extern bool Wayland_GetColorInfoForWindow(SDL_WindowData *window_data, Wayland_ColorInfo *info);
39+
extern bool Wayland_GetColorInfoForOutput(SDL_DisplayData *display_data, Wayland_ColorInfo *info);
40+
41+
#endif // SDL_waylandcolor_h_

0 commit comments

Comments
 (0)