clients: add widget_set_image_description_icc()
This function takes an ICC fd, creates an image description for that and sets the widget surface image description to this one. Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
This commit is contained in:
parent
cf59ed0ebe
commit
dbdcae9801
@ -4,6 +4,8 @@ endif
|
||||
|
||||
srcs_toytoolkit = [
|
||||
'window.c',
|
||||
color_management_v1_client_protocol_h,
|
||||
color_management_v1_protocol_c,
|
||||
xdg_shell_client_protocol_h,
|
||||
xdg_shell_protocol_c,
|
||||
text_cursor_position_client_protocol_h,
|
||||
|
234
clients/window.c
234
clients/window.c
@ -56,6 +56,7 @@
|
||||
#include "shared/xalloc.h"
|
||||
#include <libweston/zalloc.h>
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
#include "color-management-v1-client-protocol.h"
|
||||
#include "text-cursor-position-client-protocol.h"
|
||||
#include "pointer-constraints-unstable-v1-client-protocol.h"
|
||||
#include "relative-pointer-unstable-v1-client-protocol.h"
|
||||
@ -90,11 +91,15 @@ struct display {
|
||||
struct wl_data_device_manager *data_device_manager;
|
||||
struct text_cursor_position *text_cursor_position;
|
||||
struct xdg_wm_base *xdg_shell;
|
||||
struct xx_color_manager_v2 *color_manager;
|
||||
struct zwp_tablet_manager_v2 *tablet_manager;
|
||||
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
|
||||
struct zwp_pointer_constraints_v1 *pointer_constraints;
|
||||
uint32_t serial;
|
||||
|
||||
uint32_t color_manager_features;
|
||||
uint32_t color_manager_rendering_intents;
|
||||
|
||||
int display_fd;
|
||||
bool display_fd_was_read;
|
||||
uint32_t display_fd_events;
|
||||
@ -212,6 +217,8 @@ struct surface {
|
||||
struct wl_callback *frame_cb;
|
||||
uint32_t last_time;
|
||||
|
||||
struct xx_color_management_surface_v2 *cm_surface;
|
||||
|
||||
struct rectangle allocation;
|
||||
struct rectangle server_allocation;
|
||||
|
||||
@ -472,6 +479,44 @@ struct shm_pool {
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct cm_image_description {
|
||||
struct xx_image_description_v2 *image_desc;
|
||||
enum cm_image_desc_status {
|
||||
CM_IMAGE_DESC_NOT_CREATED = 0,
|
||||
CM_IMAGE_DESC_READY,
|
||||
CM_IMAGE_DESC_FAILED,
|
||||
} status;
|
||||
};
|
||||
|
||||
static const struct render_intent_info
|
||||
render_intent_info_table[] = {
|
||||
{
|
||||
.intent = RENDER_INTENT_PERCEPTUAL,
|
||||
.desc = "Perceptual",
|
||||
.protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_PERCEPTUAL,
|
||||
},
|
||||
{
|
||||
.intent = RENDER_INTENT_RELATIVE,
|
||||
.desc = "Media-relative colorimetric",
|
||||
.protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_RELATIVE,
|
||||
},
|
||||
{
|
||||
.intent = RENDER_INTENT_RELATIVE_BPC,
|
||||
.desc = "Media-relative colorimetric + black point compensation",
|
||||
.protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_RELATIVE_BPC,
|
||||
},
|
||||
{
|
||||
.intent = RENDER_INTENT_SATURATION,
|
||||
.desc = "Saturation",
|
||||
.protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_SATURATION,
|
||||
},
|
||||
{
|
||||
.intent = RENDER_INTENT_ABSOLUTE,
|
||||
.desc = "ICC-absolute colorimetric",
|
||||
.protocol_intent = XX_COLOR_MANAGER_V2_RENDER_INTENT_ABSOLUTE,
|
||||
},
|
||||
};
|
||||
|
||||
enum {
|
||||
CURSOR_DEFAULT = 100,
|
||||
CURSOR_UNSET
|
||||
@ -522,6 +567,139 @@ debug_print(void *proxy, int line, const char *func, const char *fmt, ...)
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
cm_image_desc_ready(void *data, struct xx_image_description_v2 *xx_image_description_v2,
|
||||
uint32_t identity)
|
||||
{
|
||||
struct cm_image_description *cm_image_desc = data;
|
||||
|
||||
cm_image_desc->status = CM_IMAGE_DESC_READY;
|
||||
}
|
||||
|
||||
static void
|
||||
cm_image_desc_failed(void *data, struct xx_image_description_v2 *xx_image_description_v2,
|
||||
uint32_t cause, const char *msg)
|
||||
{
|
||||
struct cm_image_description *cm_image_desc = data;
|
||||
|
||||
fprintf(stderr, "failed to create image description: %u - %s\n",
|
||||
cause, msg);
|
||||
|
||||
cm_image_desc->status = CM_IMAGE_DESC_FAILED;
|
||||
}
|
||||
|
||||
static const struct xx_image_description_v2_listener cm_image_desc_listener = {
|
||||
.ready = cm_image_desc_ready,
|
||||
.failed = cm_image_desc_failed,
|
||||
};
|
||||
|
||||
const struct render_intent_info *
|
||||
render_intent_info_from(enum render_intent intent)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(render_intent_info_table); i++)
|
||||
if (render_intent_info_table[i].intent == intent)
|
||||
return &render_intent_info_table[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
widget_set_image_description_icc(struct widget *widget, int icc_fd,
|
||||
uint32_t length, uint32_t offset,
|
||||
enum render_intent intent, char **err_msg)
|
||||
{
|
||||
struct xx_image_description_creator_icc_v2 *icc_creator;
|
||||
struct display *display = widget->window->display;
|
||||
struct surface *surface = widget->surface;
|
||||
struct xx_color_manager_v2 *color_manager_wrapper;
|
||||
struct wl_event_queue *queue;
|
||||
struct cm_image_description cm_image_desc;
|
||||
const struct render_intent_info *intent_info;
|
||||
int ret = 0;
|
||||
|
||||
if (!display->color_manager) {
|
||||
str_printf(err_msg,
|
||||
"%s extension not supported by the Wayland " \
|
||||
"compositor, ignoring image color profile.",
|
||||
xx_color_manager_v2_interface.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!((display->color_manager_features >> XX_COLOR_MANAGER_V2_FEATURE_ICC_V2_V4) & 1)) {
|
||||
str_printf(err_msg,
|
||||
"Wayland compositor does not support creating image " \
|
||||
"descriptions from ICC files, ignoring color profile.");
|
||||
return false;
|
||||
}
|
||||
|
||||
intent_info = render_intent_info_from(intent);
|
||||
assert(intent_info && "error: unknown rendering intent\n");
|
||||
|
||||
if (!((display->color_manager_rendering_intents >> intent_info->protocol_intent) & 1)) {
|
||||
str_printf(err_msg,
|
||||
"Wayland compositor does not support creating image " \
|
||||
"descriptions with the following rendering intent: %s. " \
|
||||
"Ignoring color profile.", intent_info->desc);
|
||||
return false;
|
||||
}
|
||||
|
||||
color_manager_wrapper = wl_proxy_create_wrapper(display->color_manager);
|
||||
queue = wl_display_create_queue(display->display);
|
||||
wl_proxy_set_queue((struct wl_proxy *)color_manager_wrapper, queue);
|
||||
|
||||
/* Create ICC image description creator and set the ICC file. */
|
||||
icc_creator = xx_color_manager_v2_new_icc_creator(color_manager_wrapper);
|
||||
wl_proxy_wrapper_destroy(color_manager_wrapper);
|
||||
xx_image_description_creator_icc_v2_set_icc_file(icc_creator,
|
||||
icc_fd, offset, length);
|
||||
|
||||
/* Create the image description. It will also destroy the ICC creator. */
|
||||
cm_image_desc.status = CM_IMAGE_DESC_NOT_CREATED;
|
||||
cm_image_desc.image_desc = xx_image_description_creator_icc_v2_create(icc_creator);
|
||||
xx_image_description_v2_add_listener(cm_image_desc.image_desc,
|
||||
&cm_image_desc_listener, &cm_image_desc);
|
||||
|
||||
/* Wait until compositor creates the image description or gracefully
|
||||
* fail to do that. */
|
||||
while (ret != -1 && cm_image_desc.status == CM_IMAGE_DESC_NOT_CREATED)
|
||||
ret = wl_display_dispatch_queue(display->display, queue);
|
||||
if (ret == -1) {
|
||||
xx_image_description_v2_destroy(cm_image_desc.image_desc);
|
||||
wl_event_queue_destroy(queue);
|
||||
str_printf(err_msg,
|
||||
"Disconnected from the Wayland compositor, " \
|
||||
"wl_display_dispatch() failed: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Gracefully failed to create image description. Error already printed
|
||||
* in the handler. */
|
||||
if (cm_image_desc.status == CM_IMAGE_DESC_FAILED) {
|
||||
xx_image_description_v2_destroy(cm_image_desc.image_desc);
|
||||
wl_event_queue_destroy(queue);
|
||||
str_printf(err_msg,
|
||||
"Image description creation gracefully failed.");
|
||||
return false;
|
||||
}
|
||||
assert(cm_image_desc.status == CM_IMAGE_DESC_READY);
|
||||
|
||||
if (!surface->cm_surface)
|
||||
surface->cm_surface =
|
||||
xx_color_manager_v2_get_surface(display->color_manager,
|
||||
surface->surface);
|
||||
|
||||
xx_color_management_surface_v2_set_image_description(surface->cm_surface,
|
||||
cm_image_desc.image_desc,
|
||||
intent_info->protocol_intent);
|
||||
|
||||
xx_image_description_v2_destroy(cm_image_desc.image_desc);
|
||||
wl_event_queue_destroy(queue);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
surface_to_buffer_size (enum wl_output_transform buffer_transform, int32_t buffer_scale, int32_t *width, int32_t *height)
|
||||
{
|
||||
@ -1399,6 +1577,9 @@ surface_destroy(struct surface *surface)
|
||||
if (surface->viewport)
|
||||
wp_viewport_destroy(surface->viewport);
|
||||
|
||||
if (surface->cm_surface)
|
||||
xx_color_management_surface_v2_destroy(surface->cm_surface);
|
||||
|
||||
wl_surface_destroy(surface->surface);
|
||||
|
||||
if (surface->toysurface)
|
||||
@ -6489,6 +6670,45 @@ display_bind_tablets(struct display *d, uint32_t id)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cm_supported_intent(void *data, struct xx_color_manager_v2 *xx_color_manager_v2,
|
||||
uint32_t render_intent)
|
||||
{
|
||||
struct display *d = data;
|
||||
|
||||
d->color_manager_rendering_intents |= (1 << render_intent);
|
||||
}
|
||||
|
||||
static void
|
||||
cm_supported_feature(void *data, struct xx_color_manager_v2 *xx_color_manager_v2,
|
||||
uint32_t feature)
|
||||
{
|
||||
struct display *d = data;
|
||||
|
||||
d->color_manager_features |= (1 << feature);
|
||||
}
|
||||
|
||||
static void
|
||||
cm_supported_tf_named(void *data, struct xx_color_manager_v2 *xx_color_manager_v2,
|
||||
uint32_t tf_code)
|
||||
{
|
||||
/* unused in this file */
|
||||
}
|
||||
|
||||
static void
|
||||
cm_supported_primaries_named(void *data, struct xx_color_manager_v2 *xx_color_manager_v2,
|
||||
uint32_t primaries_code)
|
||||
{
|
||||
/* unused in this file */
|
||||
}
|
||||
|
||||
static const struct xx_color_manager_v2_listener cm_listener = {
|
||||
.supported_intent = cm_supported_intent,
|
||||
.supported_feature = cm_supported_feature,
|
||||
.supported_tf_named = cm_supported_tf_named,
|
||||
.supported_primaries_named = cm_supported_primaries_named,
|
||||
};
|
||||
|
||||
static void
|
||||
global_destroy(struct display *disp, struct global *g)
|
||||
{
|
||||
@ -6557,6 +6777,12 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
|
||||
&wp_viewporter_interface, 1);
|
||||
} else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) {
|
||||
display_bind_tablets(d, id);
|
||||
} else if (strcmp(interface, "xx_color_manager_v2") == 0) {
|
||||
d->color_manager =
|
||||
wl_registry_bind(registry, id,
|
||||
&xx_color_manager_v2_interface, 1);
|
||||
xx_color_manager_v2_add_listener(d->color_manager,
|
||||
&cm_listener, d);
|
||||
}
|
||||
|
||||
if (d->global_handler)
|
||||
@ -6693,7 +6919,10 @@ display_create(int *argc, char *argv[])
|
||||
d->registry = wl_display_get_registry(d->display);
|
||||
wl_registry_add_listener(d->registry, ®istry_listener, d);
|
||||
|
||||
if (wl_display_roundtrip(d->display) < 0) {
|
||||
/* Two roundtrips to get the global and then the events of listeners
|
||||
* that we register on such globals. */
|
||||
if (wl_display_roundtrip(d->display) < 0 ||
|
||||
wl_display_roundtrip(d->display) < 0) {
|
||||
fprintf(stderr, "Failed to process Wayland connection: %s\n",
|
||||
strerror(errno));
|
||||
display_destroy(d);
|
||||
@ -6775,6 +7004,9 @@ display_destroy(struct display *display)
|
||||
if (display->xdg_shell)
|
||||
xdg_wm_base_destroy(display->xdg_shell);
|
||||
|
||||
if (display->color_manager)
|
||||
xx_color_manager_v2_destroy(display->color_manager);
|
||||
|
||||
if (display->shm)
|
||||
wl_shm_destroy(display->shm);
|
||||
|
||||
|
@ -545,6 +545,28 @@ window_get_appid(struct window *window);
|
||||
void
|
||||
window_set_text_cursor_position(struct window *window, int32_t x, int32_t y);
|
||||
|
||||
enum render_intent {
|
||||
RENDER_INTENT_PERCEPTUAL,
|
||||
RENDER_INTENT_RELATIVE,
|
||||
RENDER_INTENT_RELATIVE_BPC,
|
||||
RENDER_INTENT_SATURATION,
|
||||
RENDER_INTENT_ABSOLUTE,
|
||||
};
|
||||
|
||||
struct render_intent_info {
|
||||
enum render_intent intent;
|
||||
uint32_t protocol_intent;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
const struct render_intent_info *
|
||||
render_intent_info_from(enum render_intent intent);
|
||||
|
||||
bool
|
||||
widget_set_image_description_icc(struct widget *widget, int icc_fd,
|
||||
uint32_t length, uint32_t offset,
|
||||
enum render_intent intent, char **err_msg);
|
||||
|
||||
int
|
||||
widget_set_tooltip(struct widget *parent, char *entry, float x, float y);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user