[PATCH 2/6] Attach input profiles and build corresponding LUTs

Bryce Harrington bryce at osg.samsung.com
Wed Oct 15 21:54:37 PDT 2014


On Mon, Oct 13, 2014 at 07:40:47PM +0200, Niels Ole Salscheider wrote:
> This implements the functionality to attach a profile to a surface
> in weston. An LUT is built from the profile that can be used to
> transform colors from the input color space to the blending color
> space.
> 
> An sRGB color space is assumed for all newly created outputs
> 
> This patch uses the sRGB color space as blending space because it
> uses 8 bit LUTs for now and I want to avoid additional banding. In
> the long term we should use a linear blending space though to get
> correct results.
> 
> Signed-off-by: Niels Ole Salscheider <niels_ole at salscheider-online.de>
> ---
>  Makefile.am      |   3 +
>  configure.ac     |   2 +-
>  src/compositor.c | 411 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  src/compositor.h |  41 ++++++
>  4 files changed, 453 insertions(+), 4 deletions(-)
> 
> diff --git a/Makefile.am b/Makefile.am
> index 3af3b46..1ecab56 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -45,6 +45,9 @@ weston_CPPFLAGS = $(AM_CPPFLAGS) -DIN_WESTON
>  weston_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS) $(LIBUNWIND_CFLAGS)
>  weston_LDADD = $(COMPOSITOR_LIBS) $(LIBUNWIND_LIBS) \
>  	$(DLOPEN_LIBS) -lm libshared.la
> +if HAVE_LCMS
> +weston_LDADD += $(LCMS_LIBS)
> +endif
>  
>  weston_SOURCES =					\
>  	src/git-version.h				\
> diff --git a/configure.ac b/configure.ac
> index 1c133bd..00b7cca 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -59,7 +59,7 @@ AC_CHECK_HEADERS([execinfo.h])
>  
>  AC_CHECK_FUNCS([mkostemp strchrnul initgroups posix_fallocate])
>  
> -COMPOSITOR_MODULES="wayland-server >= 1.5.91 pixman-1 >= 0.25.2"
> +COMPOSITOR_MODULES="wayland-server >= 1.5.91 pixman-1 >= 0.25.2 glib-2.0"

Depending on glib seems a pretty big step.  I see it's needed for
GHashTable, anything else?

Wayland has a wl_map data structure; could that be used instead of
GHashTable, in order to avoid the glib dependency?
  
>  AC_ARG_ENABLE(egl, [  --disable-egl],,
>                enable_egl=yes)
> diff --git a/src/compositor.c b/src/compositor.c
> index 29731c7..4f959a4 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -56,6 +56,7 @@
>  #include "compositor.h"
>  #include "scaler-server-protocol.h"
>  #include "presentation_timing-server-protocol.h"
> +#include "cms-server-protocol.h"
>  #include "../shared/os-compatibility.h"
>  #include "git-version.h"
>  #include "version.h"
> @@ -518,7 +519,8 @@ surface_state_handle_buffer_destroy(struct wl_listener *listener, void *data)
>  }
>  
>  static void
> -weston_surface_state_init(struct weston_surface_state *state)
> +weston_surface_state_init(struct weston_surface_state *state,
> +			  struct weston_compositor *compositor)
>  {
>  	state->newly_attached = 0;
>  	state->buffer = NULL;
> @@ -539,6 +541,8 @@ weston_surface_state_init(struct weston_surface_state *state)
>  	state->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
>  	state->buffer_viewport.surface.width = -1;
>  	state->buffer_viewport.changed = 0;
> +
> +	state->colorspace = &compositor->srgb_colorspace;
>  }
>  
>  static void
> @@ -576,6 +580,163 @@ weston_surface_state_set_buffer(struct weston_surface_state *state,
>  			      &state->buffer_destroy_listener);
>  }
>  
> +#if HAVE_LCMS
> +static void
> +weston_free_clut(struct weston_clut *clut)
> +{
> +	clut->points = 0;
> +	free(clut->data);
> +	clut->data = NULL;
> +}
> +
> +static void
> +weston_build_clut(struct weston_colorspace *colorspace)
> +{
> +	cmsHTRANSFORM xform;
> +	unsigned r, g, b;
> +	cmsHPROFILE input_profile, output_profile;
> +	cmsUInt8Number input_id[16];
> +	cmsUInt8Number output_id[16];
> +	struct weston_clut *clut = &colorspace->clut;
> +	struct weston_compositor *ec = colorspace->compositor;
> +
> +	weston_free_clut(clut);
> +
> +	if (colorspace->input) {
> +		input_profile = colorspace->lcms_handle;
> +		output_profile = ec->blending_colorspace.lcms_handle;
> +	} else {
> +		input_profile = ec->blending_colorspace.lcms_handle;
> +		output_profile = colorspace->lcms_handle;
> +	}
> +
> +	cmsGetHeaderProfileID(input_profile, input_id);
> +	cmsGetHeaderProfileID(output_profile, output_id);
> +	if (memcmp(input_id, output_id, 16) == 0)
> +		return;

Don't hide the error here, propagate it by returning false.
And obviously all callers of this routine should check it.  :-)

> +	clut->points = 64;

Does this ever change to anything besides 64?  If not, wouldn't this be
better as a constant?

> +	xform = cmsCreateTransform(input_profile, TYPE_RGB_8, output_profile,
> +				   TYPE_RGB_8, INTENT_PERCEPTUAL, 0);

Looks like cmsCreateTransform has a return value that can be checked for
NULL to detect errors.  Looks like it signals some errors that could be
propagated too.

> +	clut->data = malloc(clut->points * clut->points * clut->points *
> +			    3 * sizeof(char));

Needs error check here too.

> +	for (b = 0; b < clut->points; b++)
> +		for (g = 0; g < clut->points; g++)
> +			for (r = 0; r < clut->points; r++) {
> +				char in[3];
> +				unsigned entry = 3 * (r + clut->points *
> +						 (g + clut->points * b));
> +				const float step = 255.0 / (clut->points - 1);
> +				in[0] = (char) (r * step + 0.5);
> +				in[1] = (char) (g * step + 0.5);
> +				in[2] = (char) (b * step + 0.5);
> +				cmsDoTransform(xform, in,
> +					       &clut->data[entry], 1);
> +			}
> +
> +	cmsDeleteTransform(xform);
> +}
> +
> +WL_EXPORT struct weston_colorspace *
> +weston_colorspace_from_fd(int fd, int input, struct weston_compositor *ec)
> +{
> +	FILE *profile;
> +	cmsHPROFILE lcms_handle;
> +	cmsUInt8Number profile_id[17];
> +	struct weston_colorspace *colorspace;
> +
> +	profile = fdopen(fd, "r");
> +	if (!profile) {
> +		return 0;

Should return NULL explicitly rather than 0 here.

> +	}
> +
> +	lcms_handle = cmsOpenProfileFromStream(profile, "r");
> +	if (!lcms_handle) {
> +		return 0;
> +	}

Same here.  In fact you may want to do a goto error handler, so you can
close the fd and other cleanup.

> +	cmsMD5computeID(lcms_handle);

Check return status for FALSE on this one.

> +	cmsGetHeaderProfileID(lcms_handle, profile_id);
> +	profile_id[16] = '\0';

Google isn't giving up an API definition on this one so don't know if it
returns an error code.

> +	if (input)
> +		colorspace = g_hash_table_lookup(ec->input_colorspaces,
> +						 profile_id);
> +	else
> +		colorspace = g_hash_table_lookup(ec->output_colorspaces,
> +						 profile_id);
> +	if (colorspace) {
> +		colorspace->refcount++;
> +
> +		cmsCloseProfile(lcms_handle);
> +		return colorspace;
> +	}
> +
> +	colorspace = calloc(1, sizeof(struct weston_colorspace));

Check for NULL on the calloc

> +	colorspace->refcount = 1;
> +	colorspace->destroyable = 1;
> +	colorspace->input = input;
> +	colorspace->lcms_handle = lcms_handle;
> +	colorspace->compositor = ec;
> +
> +	weston_build_clut(colorspace);

Check error return for weston_build_clut.

> +	g_hash_table_insert(ec->input_colorspaces,
> +			    g_strdup((const gchar *) profile_id),
> +			    colorspace);
> +
> +	return colorspace;
> +}
> +
> +/* This function is called when a color space is removed from the hash table */
> +static void
> +weston_colorspace_free(struct weston_colorspace *colorspace)
> +{
> +	if (!colorspace->destroyable)
> +		return;

No chance this can't result in memory leakage?

> +	cmsCloseProfile(colorspace->lcms_handle);
> +
> +	weston_free_clut(&colorspace->clut);
> +	free(colorspace);
> +}
> +
> +WL_EXPORT void
> +weston_colorspace_destroy(struct weston_colorspace *colorspace)
> +{
> +	cmsUInt8Number profile_id[17];
> +
> +	if (!colorspace->destroyable)
> +		return;
> +
> +	colorspace->refcount--;
> +	if (colorspace->refcount > 0)
> +		return;
> +
> +	cmsGetHeaderProfileID(colorspace->lcms_handle, profile_id);
> +	profile_id[16] = '\0';
> +
> +	if (colorspace->input)
> +		g_hash_table_remove(colorspace->compositor->input_colorspaces,
> +				    profile_id);
> +	else
> +		g_hash_table_remove(colorspace->compositor->output_colorspaces,
> +				    profile_id);
> +
> +}

Why is there both a *_free() and a *_destroy() for weston_colorspace?

> +static void
> +weston_colorspace_resource_destroy(struct wl_resource *cms_colorspace)
> +{
> +	struct weston_colorspace *colorspace =
> +		wl_resource_get_user_data(cms_colorspace);
> +	weston_colorspace_destroy(colorspace);
> +}
> +#endif
> +
>  WL_EXPORT struct weston_surface *
>  weston_surface_create(struct weston_compositor *compositor)
>  {
> @@ -597,7 +758,9 @@ weston_surface_create(struct weston_compositor *compositor)
>  	surface->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
>  	surface->buffer_viewport.surface.width = -1;
>  
> -	weston_surface_state_init(&surface->pending);
> +	surface->colorspace = &compositor->srgb_colorspace;
> +
> +	weston_surface_state_init(&surface->pending, compositor);
>  
>  	surface->output = NULL;
>  
> @@ -615,6 +778,7 @@ weston_surface_create(struct weston_compositor *compositor)
>  	wl_list_init(&surface->subsurface_list);
>  	wl_list_init(&surface->subsurface_list_pending);
>  
> +
>  	return surface;

Extraneous newline?

>  }
>  
> @@ -2369,6 +2533,8 @@ weston_surface_commit_state(struct weston_surface *surface,
>  	wl_list_insert_list(&surface->feedback_list,
>  			    &state->feedback_list);
>  	wl_list_init(&state->feedback_list);
> +
> +	surface->colorspace = state->colorspace;
>  }
>  
>  static void
> @@ -2609,6 +2775,8 @@ weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
>  	sub->cached.buffer_viewport.surface =
>  		surface->pending.buffer_viewport.surface;
>  
> +	sub->cached.colorspace = surface->colorspace;
> +
>  	weston_surface_reset_pending_buffer(surface);
>  
>  	pixman_region32_copy(&sub->cached.opaque, &surface->pending.opaque);
> @@ -3041,7 +3209,7 @@ weston_subsurface_create(uint32_t id, struct weston_surface *surface,
>  				       sub, subsurface_resource_destroy);
>  	weston_subsurface_link_surface(sub, surface);
>  	weston_subsurface_link_parent(sub, parent);
> -	weston_surface_state_init(&sub->cached);
> +	weston_surface_state_init(&sub->cached, surface->compositor);
>  	sub->cached_buffer_ref.buffer = NULL;
>  	sub->synchronized = 1;
>  
> @@ -3363,6 +3531,10 @@ weston_output_destroy(struct weston_output *output)
>  	wl_signal_emit(&output->compositor->output_destroyed_signal, output);
>  	wl_signal_emit(&output->destroy_signal, output);
>  
> +#ifdef HAVE_LCMS
> +	weston_colorspace_destroy(output->colorspace);
> +#endif
> +
>  	free(output->name);
>  	pixman_region32_fini(&output->region);
>  	pixman_region32_fini(&output->previous_damage);
> @@ -3554,6 +3726,7 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
>  	output->mm_height = mm_height;
>  	output->dirty = 1;
>  	output->original_scale = scale;
> +	output->colorspace = &c->srgb_colorspace;
>  
>  	weston_output_transform_scale_init(output, transform, scale);
>  	weston_output_init_zoom(output);
> @@ -3917,6 +4090,181 @@ bind_presentation(struct wl_client *client,
>  	presentation_send_clock_id(resource, compositor->presentation_clock);
>  }
>  
> +#ifdef HAVE_LCMS
> +static void
> +cms_colorspace_destroy(struct wl_client *client,
> +		       struct wl_resource *cms_colorspace)
> +{
> +	wl_resource_destroy(cms_colorspace);
> +}
> +
> +static void
> +cms_colorspace_get_profile_fd(struct wl_client *client,
> +			      struct wl_resource *cms_colorspace)
> +{
> +	struct weston_colorspace *colorspace =
> +		wl_resource_get_user_data(cms_colorspace);
> +	char template[24];
> +	FILE *profilefile;
> +	int fd = -1;
> +
> +	strncpy(template, "/tmp/weston-cms-XXXXXX", 24);
> +	fd = mkstemp(template);
> +	profilefile = fdopen(fd, "w");
> +	cmsSaveProfileToStream(colorspace->lcms_handle, profilefile);
> +	rewind(profilefile);
> +
> +	wl_cms_colorspace_send_profile_data(cms_colorspace, fd);
> +
> +	close(fd);
> +}
> +
> +static const struct wl_cms_colorspace_interface cms_colorspace_interface = {
> +	cms_colorspace_destroy,
> +	cms_colorspace_get_profile_fd
> +};
> +
> +static void
> +cms_set_colorspace(struct wl_client *client, struct wl_resource *cms,
> +		   struct wl_resource *surface_resource,
> +		   struct wl_resource *colorspace_resource)
> +{
> +	struct weston_surface *surface =
> +		wl_resource_get_user_data(surface_resource);

wl_resource_get_user_data() returns a void*; does this need a cast?
Also, I can't tell whether it's guaranteed not to return NULL or not.
If it can return NULL, better check for it here.

> +
> +	struct weston_colorspace *colorspace =
> +		wl_resource_get_user_data(colorspace_resource);
> +	surface->pending.colorspace = colorspace;
> +}
> +
> +static void
> +cms_colorspace_from_fd(struct wl_client *client, struct wl_resource *cms,
> +		       int fd, uint32_t id)
> +{
> +	struct weston_compositor *compositor =
> +		wl_resource_get_user_data(cms);
> +
> +	struct weston_colorspace *colorspace;
> +	struct wl_resource *colorspace_resource;
> +
> +	colorspace = weston_colorspace_from_fd(fd, 1, compositor);
> +	if (colorspace == NULL) {
> +		wl_resource_post_error(cms,
> +				       WL_CMS_ERROR_INVALID_PROFILE,
> +				       "the passed ICC profile is not valid");
> +		return;

Should return false in case of an error.

> +	}
> +
> +	colorspace_resource = wl_resource_create(client,
> +						 &wl_cms_colorspace_interface,
> +						 1, id);
> +	if (colorspace_resource == NULL) {
> +		weston_colorspace_destroy(colorspace);
> +		wl_client_post_no_memory(client);
> +		return;

ditto

> +	}
> +	wl_resource_set_implementation(colorspace_resource,
> +				       &cms_colorspace_interface, colorspace,
> +				       weston_colorspace_resource_destroy);
> +}
> +
> +static void
> +cms_output_colorspace(struct wl_client *client, struct wl_resource *cms,
> +		      struct wl_resource *output_resource, uint32_t id)
> +{
> +	struct weston_output *output =
> +		wl_resource_get_user_data(output_resource);
> +
> +	struct weston_colorspace *colorspace;
> +	struct wl_resource *colorspace_resource;
> +
> +	colorspace = output->colorspace;
> +	colorspace->refcount++;
> +
> +	colorspace_resource = wl_resource_create(client,
> +						 &wl_cms_colorspace_interface,
> +						 1, id);
> +	if (colorspace_resource == NULL) {
> +		weston_colorspace_destroy(colorspace);
> +		wl_client_post_no_memory(client);
> +		return;
> +	}
> +	wl_resource_set_implementation(colorspace_resource,
> +				       &cms_colorspace_interface, colorspace,
> +				       weston_colorspace_resource_destroy);
> +}
> +
> +static void
> +cms_srgb_colorspace(struct wl_client *client, struct wl_resource *cms,
> +		    uint32_t id)
> +{
> +	struct weston_compositor *compositor =
> +		wl_resource_get_user_data(cms);
> +	struct weston_colorspace *colorspace;
> +	struct wl_resource *colorspace_resource;
> +
> +	colorspace = &compositor->srgb_colorspace;
> +
> +	colorspace_resource = wl_resource_create(client,
> +						 &wl_cms_colorspace_interface,
> +						 1, id);
> +	if (colorspace_resource == NULL) {
> +		weston_colorspace_destroy(colorspace);
> +		wl_client_post_no_memory(client);
> +		return;
> +	}
> +	wl_resource_set_implementation(colorspace_resource,
> +				       &cms_colorspace_interface, colorspace,
> +				       weston_colorspace_resource_destroy);
> +}
> +
> +static void
> +cms_blending_colorspace(struct wl_client *client, struct wl_resource *cms,
> +			uint32_t id)
> +{
> +	struct weston_compositor *compositor =
> +		wl_resource_get_user_data(cms);
> +	struct weston_colorspace *colorspace;
> +	struct wl_resource *colorspace_resource;
> +
> +	colorspace = &compositor->blending_colorspace;
> +
> +	colorspace_resource = wl_resource_create(client,
> +						 &wl_cms_colorspace_interface,
> +						 1, id);
> +	if (colorspace_resource == NULL) {
> +		weston_colorspace_destroy(colorspace);
> +		wl_client_post_no_memory(client);
> +		return;
> +	}
> +	wl_resource_set_implementation(colorspace_resource,
> +				       &cms_colorspace_interface, colorspace,
> +				       weston_colorspace_resource_destroy);
> +}
> +
> +static const struct wl_cms_interface cms_interface = {
> +	cms_set_colorspace,
> +	cms_colorspace_from_fd,
> +	cms_output_colorspace,
> +	cms_srgb_colorspace,
> +	cms_blending_colorspace
> +};
> +
> +static void
> +bind_cms(struct wl_client *client, void *data, uint32_t version, uint32_t id)
> +{
> +	struct wl_resource *resource;
> +
> +	resource = wl_resource_create(client, &wl_cms_interface, 1, id);
> +	if (resource == NULL) {
> +		wl_client_post_no_memory(client);
> +		return;
> +	}
> +
> +	wl_resource_set_implementation(resource, &cms_interface, data, NULL);
> +}
> +#endif
> +
>  static void
>  compositor_bind(struct wl_client *client,
>  		void *data, uint32_t version, uint32_t id)
> @@ -4016,6 +4364,12 @@ weston_compositor_init(struct weston_compositor *ec,
>  			      ec, bind_presentation))
>  		return -1;
>  
> +#ifdef HAVE_LCMS
> +	if (!wl_global_create(display, &wl_cms_interface, 1,
> +			      ec, bind_cms))
> +		return -1;
> +#endif
> +
>  	wl_list_init(&ec->view_list);
>  	wl_list_init(&ec->plane_list);
>  	wl_list_init(&ec->layer_list);
> @@ -4600,6 +4954,10 @@ int main(int argc, char *argv[])
>  	struct wl_client *primary_client;
>  	struct wl_listener primary_client_destroyed;
>  	struct weston_seat *seat;
> +#ifdef HAVE_LCMS
> +	cmsUInt8Number srgb_id[17];
> +	cmsUInt8Number blending_id[17];
> +#endif
>  
>  	const struct weston_option core_options[] = {
>  		{ WESTON_OPTION_STRING, "backend", 'B', &backend },
> @@ -4690,6 +5048,45 @@ int main(int argc, char *argv[])
>  	ec->idle_time = idle_time;
>  	ec->default_pointer_grab = NULL;
>  
> +#ifdef HAVE_LCMS
> +	ec->input_colorspaces =
> +		g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
> +				      (GDestroyNotify) weston_colorspace_free);
> +	ec->output_colorspaces =
> +		g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
> +				      (GDestroyNotify) weston_colorspace_free);
> +
> +	ec->srgb_colorspace.destroyable = 0;
> +	ec->srgb_colorspace.input = 1;
> +	ec->srgb_colorspace.compositor = ec;
> +	ec->blending_colorspace.destroyable = 0;
> +	ec->blending_colorspace.input = 1;
> +	ec->blending_colorspace.compositor = ec;
> +
> +	ec->srgb_colorspace.lcms_handle = cmsCreate_sRGBProfile();
> +	/* TODO: We should really use a linear blending space. But this would
> +	 * cause additional banding since we only use an 8 bit LUT for now. */
> +	ec->blending_colorspace.lcms_handle = cmsCreate_sRGBProfile();
> +
> +	weston_build_clut(&ec->srgb_colorspace);
> +	/* This is unnecessary but will initialize everything with 0 */
> +	weston_build_clut(&ec->blending_colorspace);
> +
> +	cmsMD5computeID(ec->srgb_colorspace.lcms_handle);
> +	cmsMD5computeID(ec->blending_colorspace.lcms_handle);
> +	cmsGetHeaderProfileID(ec->srgb_colorspace.lcms_handle, srgb_id);
> +	cmsGetHeaderProfileID(ec->blending_colorspace.lcms_handle, blending_id);
> +	srgb_id[16] = '\0';
> +	blending_id[16] = '\0';
> +
> +	g_hash_table_insert(ec->input_colorspaces,
> +			    g_strdup((const gchar *) srgb_id),
> +			    &ec->srgb_colorspace);
> +	g_hash_table_insert(ec->input_colorspaces,
> +			    g_strdup((const gchar *) blending_id),
> +			    &ec->srgb_colorspace);
> +#endif
> +
>  	for (i = 1; i < argc; i++)
>  		weston_log("fatal: unhandled option: %s\n", argv[i]);
>  	if (argc > 1) {
> @@ -4760,6 +5157,14 @@ out:
>  
>  	wl_signal_emit(&ec->destroy_signal, ec);
>  
> +#ifdef HAVE_LCMS
> +	g_hash_table_unref(ec->input_colorspaces);
> +	g_hash_table_unref(ec->output_colorspaces);
> +
> +	weston_free_clut(&ec->srgb_colorspace.clut);
> +	/* The blending colorspace cannot have a clut */
> +#endif
> +
>  	weston_compositor_xkb_destroy(ec);
>  
>  	ec->destroy(ec);
> diff --git a/src/compositor.h b/src/compositor.h
> index 44379fe..5f198a9 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -31,6 +31,7 @@ extern "C" {
>  #include <time.h>
>  #include <pixman.h>
>  #include <xkbcommon/xkbcommon.h>
> +#include <glib.h>
>
>  #define WL_HIDE_DEPRECATED
>  #include <wayland-server.h>
> @@ -40,6 +41,10 @@ extern "C" {
>  #include "config-parser.h"
>  #include "zalloc.h"
>  
> +#ifdef HAVE_LCMS
> +#include <lcms2.h>
> +#endif
> +
>  #ifndef MIN
>  #define MIN(x,y) (((x) < (y)) ? (x) : (y))
>  #endif
> @@ -179,6 +184,24 @@ enum weston_mode_switch_op {
>  	WESTON_MODE_SWITCH_RESTORE_NATIVE
>  };
>  
> +struct weston_clut {
> +	unsigned points;
> +	char *data;
> +};
> +
> +struct weston_colorspace {
> +#ifdef HAVE_LCMS
> +	cmsHPROFILE lcms_handle;
> +#endif
> +	struct weston_clut clut;
> +
> +	int destroyable;
> +	int refcount;
> +	int input;
> +
> +	struct weston_compositor *compositor;
> +};
> +
>  struct weston_output {
>  	uint32_t id;
>  	char *name;
> @@ -220,6 +243,8 @@ struct weston_output {
>  	struct weston_mode *original_mode;
>  	struct wl_list mode_list;
>  
> +	struct weston_colorspace *colorspace;
> +
>  	void (*start_repaint_loop)(struct weston_output *output);
>  	int (*repaint)(struct weston_output *output,
>  			pixman_region32_t *damage);
> @@ -668,6 +693,11 @@ struct weston_compositor {
>  	int32_t kb_repeat_delay;
>  
>  	clockid_t presentation_clock;
> +
> +	struct weston_colorspace srgb_colorspace;
> +	struct weston_colorspace blending_colorspace;
> +	GHashTable *input_colorspaces;
> +	GHashTable *output_colorspaces;
>  };
>  
>  struct weston_buffer {
> @@ -844,6 +874,9 @@ struct weston_surface_state {
>  	/* wl_surface.set_scaling_factor */
>  	/* wl_viewport.set */
>  	struct weston_buffer_viewport buffer_viewport;
> +
> +	/* wl_cms.set_colorspace*/
> +	struct weston_colorspace *colorspace;
>  };
>  
>  struct weston_surface {
> @@ -887,6 +920,8 @@ struct weston_surface {
>  	int32_t height_from_buffer;
>  	int keep_buffer; /* bool for backends to prevent early release */
>  
> +	struct weston_colorspace *colorspace;
> +
>  	/* wl_viewport resource for this surface */
>  	struct wl_resource *viewport_resource;
>  
> @@ -1410,6 +1445,12 @@ struct weston_view_animation *
>  weston_slide_run(struct weston_view *view, float start, float stop,
>  		 weston_view_animation_done_func_t done, void *data);
>  
> +struct weston_colorspace *
> +weston_colorspace_from_fd(int fd, int input, struct weston_compositor *ec);
> +
> +void
> +weston_colorspace_destroy(struct weston_colorspace *colorspace);
> +
>  void
>  weston_surface_set_color(struct weston_surface *surface,
>  			 float red, float green, float blue, float alpha);
> -- 
> 2.1.2
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list