mirror of https://github.com/libsdl-org/SDL.git
wayland: Ensure that color descriptions are always retrieved
This commit is contained in:
parent
9464aaa8af
commit
fab52b578f
|
|
@ -27,31 +27,87 @@
|
|||
#include "SDL_waylandvideo.h"
|
||||
#include "SDL_waylandwindow.h"
|
||||
#include "color-management-v1-client-protocol.h"
|
||||
#include "../../events/SDL_windowevents_c.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;
|
||||
union
|
||||
{
|
||||
SDL_WindowData *window_data;
|
||||
SDL_DisplayData *display_data;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
WAYLAND_COLOR_OBJECT_TYPE_WINDOW,
|
||||
WAYLAND_COLOR_OBJECT_TYPE_DISPLAY
|
||||
} object_type;
|
||||
|
||||
SDL_HDROutputProperties HDR;
|
||||
|
||||
// The ICC fd is only valid if the size is non-zero.
|
||||
int icc_fd;
|
||||
Uint32 icc_size;
|
||||
|
||||
bool deferred_event_processing;
|
||||
} Wayland_ColorInfoState;
|
||||
|
||||
static void Wayland_CancelColorInfoRequest(Wayland_ColorInfoState *state)
|
||||
{
|
||||
if (state) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Wayland_FreeColorInfoState(Wayland_ColorInfoState *state)
|
||||
{
|
||||
if (state) {
|
||||
Wayland_CancelColorInfoRequest(state);
|
||||
|
||||
switch (state->object_type) {
|
||||
case WAYLAND_COLOR_OBJECT_TYPE_WINDOW:
|
||||
state->window_data->color_info_state = NULL;
|
||||
break;
|
||||
case WAYLAND_COLOR_OBJECT_TYPE_DISPLAY:
|
||||
state->display_data->color_info_state = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_free(state);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
Wayland_CancelColorInfoRequest(state);
|
||||
|
||||
if (state->wp_image_description_info) {
|
||||
wp_image_description_info_v1_destroy(state->wp_image_description_info);
|
||||
state->wp_image_description_info = NULL;
|
||||
switch (state->object_type) {
|
||||
case WAYLAND_COLOR_OBJECT_TYPE_WINDOW:
|
||||
{
|
||||
SDL_SetWindowHDRProperties(state->window_data->sdlwindow, &state->HDR, true);
|
||||
if (state->icc_size) {
|
||||
state->window_data->icc_fd = state->icc_fd;
|
||||
state->window_data->icc_size = state->icc_size;
|
||||
SDL_SendWindowEvent(state->window_data->sdlwindow, SDL_EVENT_WINDOW_ICCPROF_CHANGED, 0, 0);
|
||||
}
|
||||
} break;
|
||||
case WAYLAND_COLOR_OBJECT_TYPE_DISPLAY:
|
||||
{
|
||||
SDL_copyp(&state->display_data->HDR, &state->HDR);
|
||||
} break;
|
||||
}
|
||||
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,
|
||||
|
|
@ -60,8 +116,8 @@ static void image_description_info_handle_icc_file(void *data,
|
|||
{
|
||||
Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
|
||||
|
||||
state->info->icc_fd = icc;
|
||||
state->info->icc_size = icc_size;
|
||||
state->icc_fd = icc;
|
||||
state->icc_size = icc_size;
|
||||
}
|
||||
|
||||
static void image_description_info_handle_primaries(void *data,
|
||||
|
|
@ -102,7 +158,7 @@ static void image_description_info_handle_luminances(void *data,
|
|||
uint32_t reference_lum)
|
||||
{
|
||||
Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
|
||||
state->info->HDR.HDR_headroom = (float)max_lum / (float)reference_lum;
|
||||
state->HDR.HDR_headroom = (float)max_lum / (float)reference_lum;
|
||||
}
|
||||
|
||||
static void image_description_info_handle_target_primaries(void *data,
|
||||
|
|
@ -157,13 +213,18 @@ static void PumpColorspaceEvents(Wayland_ColorInfoState *state)
|
|||
|
||||
// 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);
|
||||
if (state->deferred_event_processing) {
|
||||
WAYLAND_wl_proxy_set_queue((struct wl_proxy *)state->wp_image_description_info, queue);
|
||||
} else {
|
||||
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);
|
||||
Wayland_FreeColorInfoState(state);
|
||||
}
|
||||
|
||||
static void image_description_handle_failed(void *data,
|
||||
|
|
@ -172,9 +233,11 @@ static void image_description_handle_failed(void *data,
|
|||
const char *msg)
|
||||
{
|
||||
Wayland_ColorInfoState *state = (Wayland_ColorInfoState *)data;
|
||||
Wayland_CancelColorInfoRequest(state);
|
||||
|
||||
wp_image_description_v1_destroy(state->wp_image_description);
|
||||
state->wp_image_description = NULL;
|
||||
if (state->deferred_event_processing) {
|
||||
Wayland_FreeColorInfoState(state);
|
||||
}
|
||||
}
|
||||
|
||||
static void image_description_handle_ready(void *data,
|
||||
|
|
@ -186,6 +249,10 @@ static void image_description_handle_ready(void *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);
|
||||
|
||||
if (state->deferred_event_processing) {
|
||||
PumpColorspaceEvents(state);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wp_image_description_v1_listener image_description_listener = {
|
||||
|
|
@ -193,32 +260,44 @@ static const struct wp_image_description_v1_listener image_description_listener
|
|||
image_description_handle_ready
|
||||
};
|
||||
|
||||
bool Wayland_GetColorInfoForWindow(SDL_WindowData *window_data, Wayland_ColorInfo *info)
|
||||
void Wayland_GetColorInfoForWindow(SDL_WindowData *window_data, bool defer_event_processing)
|
||||
{
|
||||
Wayland_ColorInfoState state;
|
||||
SDL_zero(state);
|
||||
state.info = info;
|
||||
// Cancel any pending request, as it is out-of-date.
|
||||
Wayland_FreeColorInfoState(window_data->color_info_state);
|
||||
Wayland_ColorInfoState *state = SDL_calloc(1, sizeof(Wayland_ColorInfoState));
|
||||
|
||||
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);
|
||||
if (state) {
|
||||
window_data->color_info_state = state;
|
||||
state->window_data = window_data;
|
||||
state->object_type = WAYLAND_COLOR_OBJECT_TYPE_WINDOW;
|
||||
state->deferred_event_processing = defer_event_processing;
|
||||
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;
|
||||
if (!defer_event_processing) {
|
||||
PumpColorspaceEvents(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Wayland_GetColorInfoForOutput(SDL_DisplayData *display_data, Wayland_ColorInfo *info)
|
||||
void Wayland_GetColorInfoForOutput(SDL_DisplayData *display_data, bool defer_event_processing)
|
||||
{
|
||||
Wayland_ColorInfoState state;
|
||||
SDL_zero(state);
|
||||
state.info = info;
|
||||
// Cancel any pending request, as it is out-of-date.
|
||||
Wayland_FreeColorInfoState(display_data->color_info_state);
|
||||
Wayland_ColorInfoState *state = SDL_calloc(1, sizeof(Wayland_ColorInfoState));
|
||||
|
||||
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);
|
||||
if (state) {
|
||||
display_data->color_info_state = state;
|
||||
state->display_data = display_data;
|
||||
state->object_type = WAYLAND_COLOR_OBJECT_TYPE_DISPLAY;
|
||||
state->deferred_event_processing = defer_event_processing;
|
||||
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;
|
||||
if (!defer_event_processing) {
|
||||
PumpColorspaceEvents(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SDL_VIDEO_DRIVER_WAYLAND
|
||||
|
|
|
|||
|
|
@ -26,16 +26,10 @@
|
|||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
typedef struct Wayland_ColorInfo
|
||||
{
|
||||
SDL_HDROutputProperties HDR;
|
||||
struct Wayland_ColorInfoState;
|
||||
|
||||
// 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);
|
||||
extern void Wayland_FreeColorInfoState(struct Wayland_ColorInfoState *state);
|
||||
extern void Wayland_GetColorInfoForWindow(SDL_WindowData *window_data, bool defer_event_processing);
|
||||
extern void Wayland_GetColorInfoForOutput(SDL_DisplayData *display_data, bool defer_event_processing);
|
||||
|
||||
#endif // SDL_waylandcolor_h_
|
||||
|
|
|
|||
|
|
@ -1118,21 +1118,12 @@ 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)
|
||||
{
|
||||
SDL_DisplayData *display = (SDL_DisplayData *)data;
|
||||
// wl_display.done is called after this event, so the display HDR status will be updated there.
|
||||
Wayland_GetOutputColorInfo(data);
|
||||
Wayland_GetColorInfoForOutput(display, false);
|
||||
}
|
||||
|
||||
static const struct wp_color_management_output_v1_listener wp_color_management_output_listener = {
|
||||
|
|
@ -1171,7 +1162,7 @@ static bool Wayland_add_display(SDL_VideoData *d, uint32_t id, uint32_t version)
|
|||
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);
|
||||
Wayland_GetColorInfoForOutput(data, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1191,6 +1182,7 @@ 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) {
|
||||
Wayland_FreeColorInfoState(display_data->color_info_state);
|
||||
wp_color_management_output_v1_destroy(display_data->wp_color_management_output);
|
||||
}
|
||||
|
||||
|
|
@ -1221,7 +1213,7 @@ static void Wayland_FinalizeDisplays(SDL_VideoData *vid)
|
|||
|
||||
static void Wayland_init_xdg_output(SDL_VideoData *d)
|
||||
{
|
||||
for(int i = 0; i < d->output_count; ++i) {
|
||||
for (int i = 0; i < d->output_count; ++i) {
|
||||
SDL_DisplayData *disp = d->output_list[i];
|
||||
disp->xdg_output = zxdg_output_manager_v1_get_xdg_output(disp->videodata->xdg_output_manager, disp->output);
|
||||
zxdg_output_v1_add_listener(disp->xdg_output, &xdg_output_listener, disp);
|
||||
|
|
@ -1234,7 +1226,7 @@ static void Wayland_InitColorManager(SDL_VideoData *d)
|
|||
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);
|
||||
Wayland_GetColorInfoForOutput(disp, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ struct SDL_DisplayData
|
|||
SDL_DisplayID display;
|
||||
SDL_VideoDisplay placeholder;
|
||||
int wl_output_done_count;
|
||||
struct Wayland_ColorInfoState *color_info_state;
|
||||
};
|
||||
|
||||
// Needed here to get wl_surface declaration, fixes GitHub#4594
|
||||
|
|
|
|||
|
|
@ -1656,17 +1656,7 @@ static void feedback_surface_preferred_changed(void *data,
|
|||
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);
|
||||
}
|
||||
}
|
||||
Wayland_GetColorInfoForWindow(wind, false);
|
||||
}
|
||||
|
||||
static const struct wp_color_management_surface_feedback_v1_listener color_management_surface_feedback_listener = {
|
||||
|
|
@ -2626,6 +2616,7 @@ bool Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Proper
|
|||
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);
|
||||
Wayland_GetColorInfoForWindow(data, true);
|
||||
} 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);
|
||||
|
|
@ -3092,6 +3083,7 @@ void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
|||
}
|
||||
|
||||
if (wind->wp_color_management_surface_feedback) {
|
||||
Wayland_FreeColorInfoState(wind->color_info_state);
|
||||
wp_color_management_surface_feedback_v1_destroy(wind->wp_color_management_surface_feedback);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ struct SDL_WindowData
|
|||
struct frog_color_managed_surface *frog_color_managed_surface;
|
||||
struct wp_color_management_surface_feedback_v1 *wp_color_management_surface_feedback;
|
||||
|
||||
struct Wayland_ColorInfoState *color_info_state;
|
||||
|
||||
SDL_AtomicInt swap_interval_ready;
|
||||
|
||||
SDL_DisplayData **outputs;
|
||||
|
|
|
|||
Loading…
Reference in New Issue