mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-10-29 05:40:12 -04:00
color-representation-v1: new protocol
Add a minimal implementation of the color-representation-v1 protocol (not including anything to actually use the new properties in rendering/scanout)
This commit is contained in:
parent
f5dc6416f0
commit
eff620770c
4 changed files with 427 additions and 0 deletions
85
include/wlr/types/wlr_color_representation_v1.h
Normal file
85
include/wlr/types/wlr_color_representation_v1.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||
* future consistency of this API.
|
||||
*/
|
||||
#ifndef WLR_USE_UNSTABLE
|
||||
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||
#endif
|
||||
|
||||
#ifndef WLR_TYPES_WLR_COLOR_REPRESENTATION_V1_H
|
||||
#define WLR_TYPES_WLR_COLOR_REPRESENTATION_V1_H
|
||||
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/render/color.h>
|
||||
|
||||
#include "color-representation-v1-protocol.h"
|
||||
|
||||
struct wlr_surface;
|
||||
|
||||
// Supported coefficients and range are always paired together
|
||||
struct wlr_color_representation_v1_coeffs_and_range {
|
||||
enum wp_color_representation_surface_v1_coefficients coeffs;
|
||||
enum wp_color_representation_surface_v1_range range;
|
||||
};
|
||||
|
||||
struct wlr_color_representation_manager_v1 {
|
||||
struct wl_global *global;
|
||||
|
||||
struct {
|
||||
// Manager is being destroyed
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct {
|
||||
enum wp_color_representation_surface_v1_alpha_mode
|
||||
*supported_alpha_modes;
|
||||
size_t supported_alpha_modes_len;
|
||||
|
||||
struct wlr_color_representation_v1_coeffs_and_range
|
||||
*supported_coeffs_and_ranges;
|
||||
size_t supported_coeffs_and_ranges_len;
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
// Options used when initialising a wlr_color_representation_manager_v1
|
||||
struct wlr_color_representation_v1_options {
|
||||
enum wp_color_representation_surface_v1_alpha_mode
|
||||
*supported_alpha_modes;
|
||||
size_t supported_alpha_modes_len;
|
||||
|
||||
const struct wlr_color_representation_v1_coeffs_and_range
|
||||
*supported_coeffs_and_ranges;
|
||||
size_t supported_coeffs_and_ranges_len;
|
||||
};
|
||||
|
||||
struct wlr_color_representation_manager_v1 *wlr_color_representation_manager_v1_create(
|
||||
struct wl_display *display, uint32_t version,
|
||||
const struct wlr_color_representation_v1_options *options);
|
||||
|
||||
// This is all the color-representation state which can be attached to a
|
||||
// surface, double-buffered and made current on commit
|
||||
struct wlr_color_representation_v1_surface_state {
|
||||
// The enum premultiplied_electrical has value zero and is defined
|
||||
// to be the default if unspecified.
|
||||
enum wp_color_representation_surface_v1_alpha_mode alpha_mode;
|
||||
|
||||
// If zero then indicates unset, otherwise values correspond to
|
||||
// enum wp_color_representation_surface_v1_coefficients
|
||||
uint32_t coefficients;
|
||||
|
||||
// If zero then indicates unset, otherwise values correspond to
|
||||
// enum wp_color_representation_surface_v1_range
|
||||
uint32_t range;
|
||||
|
||||
// If zero then indicates unset, otherwise values correspond to
|
||||
// enum wp_color_representation_surface_v1_chroma_location
|
||||
uint32_t chroma_location;
|
||||
};
|
||||
|
||||
// Get the current color representation state committed to a surface
|
||||
const struct wlr_color_representation_v1_surface_state *wlr_color_representation_v1_get_surface_state(
|
||||
struct wlr_surface *surface);
|
||||
|
||||
#endif // WLR_TYPES_WLR_COLOR_REPRESENTATION_V1_H
|
||||
|
|
@ -25,6 +25,7 @@ protocols = {
|
|||
# Staging upstream protocols
|
||||
'alpha-modifier-v1': wl_protocol_dir / 'staging/alpha-modifier/alpha-modifier-v1.xml',
|
||||
'color-management-v1': wl_protocol_dir / 'staging/color-management/color-management-v1.xml',
|
||||
'color-representation-v1': wl_protocol_dir / 'staging/color-representation/color-representation-v1.xml',
|
||||
'content-type-v1': wl_protocol_dir / 'staging/content-type/content-type-v1.xml',
|
||||
'cursor-shape-v1': wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
|
||||
'drm-lease-v1': wl_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml',
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ wlr_files += files(
|
|||
'wlr_drm.c',
|
||||
'wlr_export_dmabuf_v1.c',
|
||||
'wlr_foreign_toplevel_management_v1.c',
|
||||
'wlr_color_representation_v1.c',
|
||||
'wlr_ext_image_copy_capture_v1.c',
|
||||
'wlr_ext_foreign_toplevel_list_v1.c',
|
||||
'wlr_ext_data_control_v1.c',
|
||||
|
|
|
|||
340
types/wlr_color_representation_v1.c
Normal file
340
types/wlr_color_representation_v1.c
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_color_representation_v1.h>
|
||||
#include <wlr/util/addon.h>
|
||||
#include <wlr/util/log.h>
|
||||
|
||||
#include "color-representation-v1-protocol.h"
|
||||
#include "util/mem.h"
|
||||
|
||||
#define WP_COLOR_REPRESENTATION_VERSION 1
|
||||
|
||||
struct wlr_color_representation_v1 {
|
||||
struct wl_resource *resource;
|
||||
struct wlr_surface *surface;
|
||||
|
||||
struct wlr_color_representation_manager_v1 *manager;
|
||||
|
||||
// Associate the wlr_color_representation_v1 with a wlr_surface
|
||||
struct wlr_addon addon;
|
||||
|
||||
struct wlr_surface_synced synced;
|
||||
struct wlr_color_representation_v1_surface_state pending, current;
|
||||
};
|
||||
|
||||
static const struct wp_color_representation_surface_v1_interface color_repr_impl;
|
||||
|
||||
static struct wlr_color_representation_v1 *color_repr_from_resource(
|
||||
struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(resource,
|
||||
&wp_color_representation_surface_v1_interface,
|
||||
&color_repr_impl));
|
||||
return wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
static void color_repr_handle_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
// Actual destroying is done by the resource-destroy handler
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static void color_repr_handle_set_alpha_mode(struct wl_client *client,
|
||||
struct wl_resource *resource, uint32_t alpha_mode) {
|
||||
struct wlr_color_representation_v1 *color_repr =
|
||||
color_repr_from_resource(resource);
|
||||
if (color_repr == NULL) {
|
||||
wl_resource_post_error(resource, WP_COLOR_REPRESENTATION_SURFACE_V1_ERROR_INERT,
|
||||
"Associated surface has been destroyed, object is inert");
|
||||
return;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < color_repr->manager->supported_alpha_modes_len; i++) {
|
||||
if (color_repr->manager->supported_alpha_modes[i] == alpha_mode) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
wl_resource_post_error(resource,
|
||||
WP_COLOR_REPRESENTATION_SURFACE_V1_ERROR_ALPHA_MODE,
|
||||
"Unsupported alpha mode");
|
||||
return;
|
||||
}
|
||||
|
||||
color_repr->pending.alpha_mode = alpha_mode;
|
||||
}
|
||||
|
||||
static void color_repr_handle_set_coefficients_and_range(struct wl_client *client,
|
||||
struct wl_resource *resource, uint32_t coefficients,
|
||||
uint32_t range) {
|
||||
struct wlr_color_representation_v1 *color_repr =
|
||||
color_repr_from_resource(resource);
|
||||
if (color_repr == NULL) {
|
||||
wl_resource_post_error(resource, WP_COLOR_REPRESENTATION_SURFACE_V1_ERROR_INERT,
|
||||
"Associated surface has been destroyed, object is inert");
|
||||
return;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < color_repr->manager->supported_coeffs_and_ranges_len; i++) {
|
||||
struct wlr_color_representation_v1_coeffs_and_range *supported =
|
||||
&color_repr->manager->supported_coeffs_and_ranges[i];
|
||||
if (supported->coeffs == coefficients && supported->range == range) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
wl_resource_post_error(resource,
|
||||
WP_COLOR_REPRESENTATION_SURFACE_V1_ERROR_COEFFICIENTS,
|
||||
"Unsupported coefficients/range pair");
|
||||
return;
|
||||
}
|
||||
|
||||
color_repr->pending.coefficients = coefficients;
|
||||
color_repr->pending.range = range;
|
||||
}
|
||||
|
||||
static void color_repr_handle_set_chroma_location(struct wl_client *client,
|
||||
struct wl_resource *resource, uint32_t chroma_location) {
|
||||
struct wlr_color_representation_v1 *color_repr =
|
||||
color_repr_from_resource(resource);
|
||||
if (color_repr == NULL) {
|
||||
wl_resource_post_error(resource, WP_COLOR_REPRESENTATION_SURFACE_V1_ERROR_INERT,
|
||||
"Associated surface has been destroyed, object is inert");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t version = wl_resource_get_version(resource);
|
||||
if (!wp_color_representation_surface_v1_chroma_location_is_valid(
|
||||
version, chroma_location)) {
|
||||
wlr_log(WLR_ERROR, "Client sent chroma location which isn't a valid enum value");
|
||||
// TODO: Post actual error once
|
||||
// https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/429
|
||||
// is merged and wlroots depends on a new enough wayland-protocols.
|
||||
wl_client_post_implementation_error(resource->client,
|
||||
"Chroma location is not a valid enum value");
|
||||
return;
|
||||
}
|
||||
|
||||
// In this protocol there's no concept of supported chroma locations
|
||||
// from a client point-of-view. The compositor should just ignore any
|
||||
// chroma locations it doesn't know what to do with.
|
||||
|
||||
color_repr->pending.chroma_location = chroma_location;
|
||||
}
|
||||
|
||||
static const struct wp_color_representation_surface_v1_interface color_repr_impl = {
|
||||
.destroy = color_repr_handle_destroy,
|
||||
.set_alpha_mode = color_repr_handle_set_alpha_mode,
|
||||
.set_coefficients_and_range = color_repr_handle_set_coefficients_and_range,
|
||||
.set_chroma_location = color_repr_handle_set_chroma_location,
|
||||
};
|
||||
|
||||
static void color_repr_destroy(struct wlr_color_representation_v1 *color_repr) {
|
||||
if (color_repr == NULL) {
|
||||
return;
|
||||
}
|
||||
wlr_surface_synced_finish(&color_repr->synced);
|
||||
wlr_addon_finish(&color_repr->addon);
|
||||
wl_resource_set_user_data(color_repr->resource, NULL);
|
||||
free(color_repr);
|
||||
}
|
||||
|
||||
static void color_repr_addon_destroy(struct wlr_addon *addon) {
|
||||
struct wlr_color_representation_v1 *color_repr =
|
||||
wl_container_of(addon, color_repr, addon);
|
||||
color_repr_destroy(color_repr);
|
||||
}
|
||||
|
||||
static const struct wlr_addon_interface surface_addon_impl = {
|
||||
.name = "wlr_color_representation_v1",
|
||||
.destroy = color_repr_addon_destroy,
|
||||
};
|
||||
|
||||
static void color_repr_handle_resource_destroy(struct wl_resource *resource) {
|
||||
struct wlr_color_representation_v1 *color_repr =
|
||||
color_repr_from_resource(resource);
|
||||
color_repr_destroy(color_repr);
|
||||
}
|
||||
|
||||
static void color_repr_manager_handle_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
// Actual destroying is done by the resource-destroy handler
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct wlr_surface_synced_impl surface_synced_impl = {
|
||||
.state_size = sizeof(struct wlr_color_representation_v1_surface_state),
|
||||
};
|
||||
|
||||
static struct wlr_color_representation_v1 *color_repr_from_surface(
|
||||
struct wlr_surface *surface) {
|
||||
struct wlr_addon *addon = wlr_addon_find(&surface->addons, NULL, &surface_addon_impl);
|
||||
if (addon == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
struct wlr_color_representation_v1 *color_repr = wl_container_of(addon, color_repr, addon);
|
||||
return color_repr;
|
||||
}
|
||||
|
||||
static const struct wp_color_representation_manager_v1_interface color_repr_manager_impl;
|
||||
|
||||
static struct wlr_color_representation_manager_v1 *manager_from_resource(
|
||||
struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(resource,
|
||||
&wp_color_representation_manager_v1_interface,
|
||||
&color_repr_manager_impl));
|
||||
return wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
static void color_repr_manager_handle_get_surface(struct wl_client *client,
|
||||
struct wl_resource *manager_resource,
|
||||
uint32_t color_repr_id,
|
||||
struct wl_resource *surface_resource) {
|
||||
struct wlr_surface *surface = wlr_surface_from_resource(surface_resource);
|
||||
|
||||
// Check if there's already a color-representation attached to
|
||||
// this surface
|
||||
if (color_repr_from_surface(surface) != NULL) {
|
||||
wl_resource_post_error(manager_resource,
|
||||
WP_COLOR_REPRESENTATION_MANAGER_V1_ERROR_SURFACE_EXISTS,
|
||||
"wp_color_representation_surface_v1 already exists for this surface");
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_color_representation_v1 *color_repr = calloc(1, sizeof(*color_repr));
|
||||
if (!color_repr) {
|
||||
wl_resource_post_no_memory(manager_resource);
|
||||
return;
|
||||
}
|
||||
|
||||
color_repr->manager = manager_from_resource(manager_resource);
|
||||
|
||||
if (!wlr_surface_synced_init(&color_repr->synced, surface,
|
||||
&surface_synced_impl, &color_repr->pending, &color_repr->current)) {
|
||||
free(color_repr);
|
||||
wl_resource_post_no_memory(manager_resource);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t version = wl_resource_get_version(manager_resource);
|
||||
color_repr->resource = wl_resource_create(client,
|
||||
&wp_color_representation_surface_v1_interface, version, color_repr_id);
|
||||
if (color_repr->resource == NULL) {
|
||||
wlr_surface_synced_finish(&color_repr->synced);
|
||||
free(color_repr);
|
||||
wl_resource_post_no_memory(manager_resource);
|
||||
return;
|
||||
}
|
||||
wl_resource_set_implementation(color_repr->resource,
|
||||
&color_repr_impl, color_repr, color_repr_handle_resource_destroy);
|
||||
|
||||
wlr_addon_init(&color_repr->addon, &surface->addons, NULL, &surface_addon_impl);
|
||||
}
|
||||
|
||||
static const struct wp_color_representation_manager_v1_interface color_repr_manager_impl = {
|
||||
.destroy = color_repr_manager_handle_destroy,
|
||||
.get_surface = color_repr_manager_handle_get_surface,
|
||||
};
|
||||
|
||||
static void send_supported(struct wlr_color_representation_manager_v1 *manager,
|
||||
struct wl_resource *resource) {
|
||||
for (size_t i = 0; i < manager->supported_alpha_modes_len; i++) {
|
||||
wp_color_representation_manager_v1_send_supported_alpha_mode(
|
||||
resource, manager->supported_alpha_modes[i]);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < manager->supported_coeffs_and_ranges_len; i++) {
|
||||
struct wlr_color_representation_v1_coeffs_and_range *supported =
|
||||
&manager->supported_coeffs_and_ranges[i];
|
||||
wp_color_representation_manager_v1_send_supported_coefficients_and_ranges(
|
||||
resource, supported->coeffs, supported->range);
|
||||
}
|
||||
|
||||
// Note that there is no event for supported chroma locations in the
|
||||
// v1 protocol.
|
||||
|
||||
wp_color_representation_manager_v1_send_done(resource);
|
||||
}
|
||||
|
||||
static void manager_bind(struct wl_client *client, void *data,
|
||||
uint32_t version, uint32_t id) {
|
||||
struct wlr_color_representation_manager_v1 *manager = data;
|
||||
|
||||
struct wl_resource *resource = wl_resource_create(client,
|
||||
&wp_color_representation_manager_v1_interface,
|
||||
version, id);
|
||||
if (resource == NULL) {
|
||||
wl_client_post_no_memory(client);
|
||||
return;
|
||||
}
|
||||
wl_resource_set_implementation(resource, &color_repr_manager_impl, manager, NULL);
|
||||
|
||||
send_supported(manager, resource);
|
||||
}
|
||||
|
||||
static void handle_display_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_color_representation_manager_v1 *manager =
|
||||
wl_container_of(listener, manager, display_destroy);
|
||||
|
||||
wl_signal_emit_mutable(&manager->events.destroy, NULL);
|
||||
|
||||
assert(wl_list_empty(&manager->events.destroy.listener_list));
|
||||
|
||||
wl_list_remove(&manager->display_destroy.link);
|
||||
wl_global_destroy(manager->global);
|
||||
free(manager);
|
||||
}
|
||||
|
||||
struct wlr_color_representation_manager_v1 *wlr_color_representation_manager_v1_create(
|
||||
struct wl_display *display, uint32_t version,
|
||||
const struct wlr_color_representation_v1_options *options) {
|
||||
assert(version <= WP_COLOR_REPRESENTATION_VERSION);
|
||||
|
||||
struct wlr_color_representation_manager_v1 *manager = calloc(1, sizeof(*manager));
|
||||
if (manager == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
manager->global = wl_global_create(display,
|
||||
&wp_color_representation_manager_v1_interface,
|
||||
version, manager, manager_bind);
|
||||
if (manager->global == NULL) {
|
||||
free(manager);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
ok &= memdup(&manager->supported_alpha_modes,
|
||||
options->supported_alpha_modes,
|
||||
sizeof(options->supported_alpha_modes[0]) * options->supported_alpha_modes_len);
|
||||
ok &= memdup(&manager->supported_coeffs_and_ranges,
|
||||
options->supported_coeffs_and_ranges,
|
||||
sizeof(options->supported_coeffs_and_ranges[0]) * options->supported_coeffs_and_ranges_len);
|
||||
if (!ok) {
|
||||
goto err_options;
|
||||
}
|
||||
|
||||
manager->display_destroy.notify = handle_display_destroy;
|
||||
wl_display_add_destroy_listener(display, &manager->display_destroy);
|
||||
|
||||
return manager;
|
||||
|
||||
err_options:
|
||||
free(manager->supported_alpha_modes);
|
||||
free(manager->supported_coeffs_and_ranges);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct wlr_color_representation_v1_surface_state *wlr_color_representation_v1_get_surface_state(
|
||||
struct wlr_surface *surface) {
|
||||
struct wlr_color_representation_v1 *color_repr = color_repr_from_surface(surface);
|
||||
if (color_repr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return &color_repr->current;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue