libweston: add unique id generator
This is preparation for the CM&HDR protocol implementation. It requires us to give a unique id to each color-profile, so let's do that. In this commit we introduce a generic id generator to libweston, and its first user: the color-profile. Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
This commit is contained in:
parent
ba1561946f
commit
a84806a88e
|
@ -1438,6 +1438,8 @@ struct weston_compositor {
|
|||
uint32_t capabilities; /* combination of enum weston_capability */
|
||||
|
||||
struct weston_color_manager *color_manager;
|
||||
struct weston_idalloc *color_profile_id_generator;
|
||||
|
||||
struct weston_renderer *renderer;
|
||||
const struct pixel_format_info *read_format;
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "color.h"
|
||||
#include "id-number-allocator.h"
|
||||
#include "libweston-internal.h"
|
||||
#include <libweston/weston-log.h>
|
||||
#include "shared/xalloc.h"
|
||||
|
@ -73,6 +74,9 @@ weston_color_profile_unref(struct weston_color_profile *cprof)
|
|||
if (--cprof->ref_count > 0)
|
||||
return;
|
||||
|
||||
weston_idalloc_put_id(cprof->cm->compositor->color_profile_id_generator,
|
||||
cprof->id);
|
||||
|
||||
cprof->cm->destroy_color_profile(cprof);
|
||||
}
|
||||
|
||||
|
@ -109,6 +113,7 @@ weston_color_profile_init(struct weston_color_profile *cprof,
|
|||
{
|
||||
cprof->cm = cm;
|
||||
cprof->ref_count = 1;
|
||||
cprof->id = weston_idalloc_get_id(cm->compositor->color_profile_id_generator);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,6 +40,9 @@ struct weston_color_profile {
|
|||
struct weston_color_manager *cm;
|
||||
int ref_count;
|
||||
char *description;
|
||||
|
||||
/* Unique id to be used by the CM&HDR protocol extension. */
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
/** Type or formula for a curve */
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
#include "backend.h"
|
||||
#include "libweston-internal.h"
|
||||
#include "color.h"
|
||||
#include "id-number-allocator.h"
|
||||
#include "output-capture.h"
|
||||
#include "pixman-renderer.h"
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
|
@ -9171,6 +9172,11 @@ weston_compositor_shutdown(struct weston_compositor *ec)
|
|||
ec->color_manager = NULL;
|
||||
}
|
||||
|
||||
/* Already destroyed color manager, now we can safely destroy the color
|
||||
* profile id generator. */
|
||||
weston_idalloc_destroy(ec->color_profile_id_generator);
|
||||
ec->color_profile_id_generator = NULL;
|
||||
|
||||
if (ec->renderer)
|
||||
ec->renderer->destroy(ec);
|
||||
|
||||
|
@ -9284,6 +9290,9 @@ weston_compositor_backends_loaded(struct weston_compositor *compositor)
|
|||
if (!compositor->color_manager)
|
||||
return -1;
|
||||
|
||||
/* Create id generator before initing the color manager. */
|
||||
compositor->color_profile_id_generator = weston_idalloc_create(compositor);
|
||||
|
||||
if (!compositor->color_manager->init(compositor->color_manager))
|
||||
return -1;
|
||||
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright 2024 Collabora, Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "id-number-allocator.h"
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include "shared/weston-assert.h"
|
||||
|
||||
struct weston_idalloc {
|
||||
struct weston_compositor *compositor;
|
||||
|
||||
/* Each value on this array is a bucket of size 32. Bit is 0 if the id
|
||||
* is available, 1 otherwise. */
|
||||
uint32_t *buckets;
|
||||
|
||||
uint32_t num_buckets;
|
||||
uint32_t lowest_free_bucket;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a unique id allocator
|
||||
*
|
||||
* \param compositor The compositor
|
||||
* \return The unique id allocator
|
||||
*/
|
||||
WESTON_EXPORT_FOR_TESTS struct weston_idalloc *
|
||||
weston_idalloc_create(struct weston_compositor *compositor)
|
||||
{
|
||||
struct weston_idalloc *idalloc;
|
||||
|
||||
idalloc = xzalloc(sizeof(*idalloc));
|
||||
|
||||
idalloc->compositor = compositor;
|
||||
|
||||
/* Start with 2 buckets. If necessary we increase that on demand. */
|
||||
idalloc->num_buckets = 2;
|
||||
idalloc->buckets = xzalloc(idalloc->num_buckets * sizeof(*idalloc->buckets));
|
||||
|
||||
/* Let's reserve id 0 for errors. So start with id 0 already taken. Set
|
||||
* the first bit of the first bucket to 1. */
|
||||
idalloc->buckets[idalloc->lowest_free_bucket] = 1;
|
||||
|
||||
return idalloc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys a unique id allocator
|
||||
*
|
||||
* \param idalloc The unique id allocator to destroy
|
||||
*/
|
||||
WESTON_EXPORT_FOR_TESTS void
|
||||
weston_idalloc_destroy(struct weston_idalloc *idalloc)
|
||||
{
|
||||
/* Sanity check: id 0 should still be taken. */
|
||||
weston_assert_true(idalloc->compositor, idalloc->buckets[0] & 1);
|
||||
|
||||
free(idalloc->buckets);
|
||||
free(idalloc);
|
||||
}
|
||||
|
||||
static void
|
||||
update_lowest_free_bucket(struct weston_idalloc *idalloc)
|
||||
{
|
||||
uint32_t old_lowest_free_bucket = idalloc->lowest_free_bucket;
|
||||
uint32_t *bucket;
|
||||
unsigned int i;
|
||||
|
||||
for (i = old_lowest_free_bucket; i < idalloc->num_buckets; i++) {
|
||||
bucket = &idalloc->buckets[i];
|
||||
|
||||
/* Skip full bucket */
|
||||
if (*bucket == 0xffffffff)
|
||||
continue;
|
||||
|
||||
idalloc->lowest_free_bucket = i;
|
||||
return;
|
||||
}
|
||||
|
||||
/* We didn't find any free bucket, so we need to add more buckets. The
|
||||
* first one (from the new added) will be the lowest free. */
|
||||
idalloc->lowest_free_bucket = idalloc->num_buckets;
|
||||
idalloc->num_buckets *= 2;
|
||||
idalloc->buckets = xrealloc(idalloc->buckets,
|
||||
idalloc->num_buckets * sizeof(*idalloc->buckets));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an id from unique id allocator
|
||||
*
|
||||
* \param idalloc The unique id allocator
|
||||
* \return The unique id
|
||||
*/
|
||||
WESTON_EXPORT_FOR_TESTS uint32_t
|
||||
weston_idalloc_get_id(struct weston_idalloc *idalloc)
|
||||
{
|
||||
uint32_t *bucket = &idalloc->buckets[idalloc->lowest_free_bucket];
|
||||
unsigned int i;
|
||||
uint32_t id;
|
||||
|
||||
/* Sanity check: lowest free bucket should not be full. */
|
||||
weston_assert_uint32_neq(idalloc->compositor, *bucket, 0xffffffff);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
/* Id already used, skip it. */
|
||||
if ((*bucket >> i) & 1)
|
||||
continue;
|
||||
|
||||
/* Found free id, take it and set it to 1 on the bucket. */
|
||||
*bucket |= 1 << i;
|
||||
id = (32 * idalloc->lowest_free_bucket) + i;
|
||||
|
||||
/* Bucket may become full... */
|
||||
if (*bucket == 0xffffffff)
|
||||
update_lowest_free_bucket(idalloc);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/* We need to find an available id. */
|
||||
weston_assert_not_reached(idalloc->compositor,
|
||||
"should be able to allocate unique id");
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases a id back to unique id allocator
|
||||
*
|
||||
* When an id from the unique id allocator will not be used anymore, users
|
||||
* should call this function so that this id can be advertised again by the id
|
||||
* allocator.
|
||||
*
|
||||
* \param idalloc The unique id allocator
|
||||
* \param id The id to release
|
||||
*/
|
||||
WESTON_EXPORT_FOR_TESTS void
|
||||
weston_idalloc_put_id(struct weston_idalloc *idalloc, uint32_t id)
|
||||
{
|
||||
uint32_t bucket_index = id / 32;
|
||||
uint32_t id_index_on_bucket = id % 32;
|
||||
uint32_t *bucket;
|
||||
|
||||
/* Shouldn't try to release index 0, we never advertise this id to anyone. */
|
||||
weston_assert_uint32_neq(idalloc->compositor, id, 0);
|
||||
|
||||
/* Bucket index should be lower than num_buckets. */
|
||||
weston_assert_uint32_lt(idalloc->compositor,
|
||||
bucket_index, idalloc->num_buckets);
|
||||
|
||||
bucket = &idalloc->buckets[bucket_index];
|
||||
|
||||
/* Shouldn't try to release a free index. */
|
||||
weston_assert_true(idalloc->compositor,
|
||||
(*bucket >> id_index_on_bucket) & 1);
|
||||
|
||||
/* We now have an available index id on this bucket, so it may become
|
||||
* the lowest bucket. */
|
||||
if (bucket_index < idalloc->lowest_free_bucket)
|
||||
idalloc->lowest_free_bucket = bucket_index;
|
||||
|
||||
/* Zero the bit on the bucket. */
|
||||
*bucket &= ~(1 << id_index_on_bucket);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2023 Collabora, Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef WESTON_ID_NUMBER_ALLOCATOR_H
|
||||
#define WESTON_ID_NUMBER_ALLOCATOR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct weston_compositor;
|
||||
|
||||
struct weston_idalloc *
|
||||
weston_idalloc_create(struct weston_compositor *compositor);
|
||||
|
||||
void
|
||||
weston_idalloc_destroy(struct weston_idalloc *idalloc);
|
||||
|
||||
uint32_t
|
||||
weston_idalloc_get_id(struct weston_idalloc *idalloc);
|
||||
|
||||
void
|
||||
weston_idalloc_put_id(struct weston_idalloc *idalloc, uint32_t id);
|
||||
|
||||
#endif /* WESTON_ID_NUMBER_ALLOCATOR_H */
|
|
@ -19,6 +19,7 @@ srcs_libweston = [
|
|||
'content-protection.c',
|
||||
'data-device.c',
|
||||
'drm-formats.c',
|
||||
'id-number-allocator.c',
|
||||
'input.c',
|
||||
'linux-dmabuf.c',
|
||||
'linux-explicit-synchronization.c',
|
||||
|
|
|
@ -74,6 +74,13 @@ weston_assert_fail_(const struct weston_compositor *compositor, const char *fmt,
|
|||
cond; \
|
||||
})
|
||||
|
||||
#define weston_assert_not_reached(compositor, reason) \
|
||||
do { \
|
||||
struct weston_compositor *ec = compositor; \
|
||||
custom_assert_fail_(ec, "%s:%u: Assertion failed! This should not be reached: %s\n", \
|
||||
__FILE__, __LINE__, reason); \
|
||||
} while (0)
|
||||
|
||||
#define weston_assert_true(compositor, a) \
|
||||
weston_assert_(compositor, a, true, bool, "%d", ==)
|
||||
|
||||
|
@ -89,5 +96,11 @@ weston_assert_fail_(const struct weston_compositor *compositor, const char *fmt,
|
|||
#define weston_assert_double_eq(compositor, a, b) \
|
||||
weston_assert_(compositor, a, b, double, "%.10g", ==)
|
||||
|
||||
#define weston_assert_uint32_neq(compositor, a, b) \
|
||||
weston_assert_(compositor, a, b, uint32_t, "%u", !=)
|
||||
|
||||
#define weston_assert_uint32_lt(compositor, a, b) \
|
||||
weston_assert_(compositor, a, b, uint32_t, "%u", <)
|
||||
|
||||
#define weston_assert_str_eq(compositor, a, b) \
|
||||
weston_assert_fn_(compositor, strcmp, a, b, const char *, "%s", ==)
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "libweston-internal.h"
|
||||
#include "backend.h"
|
||||
#include "color.h"
|
||||
#include "id-number-allocator.h"
|
||||
#include "shared/xalloc.h"
|
||||
|
||||
struct config_testcase {
|
||||
|
@ -178,6 +179,7 @@ mock_cm_get_stock_sRGB_color_profile(struct weston_color_manager *mock_cm)
|
|||
mock_cprof->cm = mock_cm;
|
||||
mock_cprof->ref_count = 1;
|
||||
mock_cprof->description = xstrdup("mock cprof");
|
||||
mock_cprof->id = weston_idalloc_get_id(mock_cm->compositor->color_profile_id_generator);
|
||||
|
||||
return mock_cprof;
|
||||
}
|
||||
|
@ -209,9 +211,12 @@ TEST_P(color_characteristics_config_error, config_cases)
|
|||
};
|
||||
struct weston_compositor mock_compositor = {
|
||||
.color_manager = &mock_cm.base,
|
||||
.color_profile_id_generator = weston_idalloc_create(&mock_compositor),
|
||||
};
|
||||
struct weston_output mock_output = {};
|
||||
|
||||
mock_cm.base.compositor = &mock_compositor;
|
||||
|
||||
wl_list_init(&mock_compositor.plane_list);
|
||||
weston_output_init(&mock_output, &mock_compositor, "mockoutput");
|
||||
|
||||
|
@ -235,6 +240,7 @@ TEST_P(color_characteristics_config_error, config_cases)
|
|||
weston_config_destroy(wc);
|
||||
free(logbuf);
|
||||
weston_output_release(&mock_output);
|
||||
weston_idalloc_destroy(mock_compositor.color_profile_id_generator);
|
||||
}
|
||||
|
||||
/* Setting NULL resets group_mask */
|
||||
|
@ -247,9 +253,12 @@ TEST(weston_output_set_color_characteristics_null)
|
|||
};
|
||||
struct weston_compositor mock_compositor = {
|
||||
.color_manager = &mock_cm.base,
|
||||
.color_profile_id_generator = weston_idalloc_create(&mock_compositor),
|
||||
};
|
||||
struct weston_output mock_output = {};
|
||||
|
||||
mock_cm.base.compositor = &mock_compositor;
|
||||
|
||||
wl_list_init(&mock_compositor.plane_list);
|
||||
weston_output_init(&mock_output, &mock_compositor, "mockoutput");
|
||||
|
||||
|
@ -258,6 +267,7 @@ TEST(weston_output_set_color_characteristics_null)
|
|||
assert(mock_output.color_characteristics.group_mask == 0);
|
||||
|
||||
weston_output_release(&mock_output);
|
||||
weston_idalloc_destroy(mock_compositor.color_profile_id_generator);
|
||||
}
|
||||
|
||||
struct value_testcase {
|
||||
|
@ -325,12 +335,15 @@ TEST_P(hdr_metadata_type1_errors, value_cases)
|
|||
};
|
||||
struct weston_compositor mock_compositor = {
|
||||
.color_manager = &mock_cm.base,
|
||||
.color_profile_id_generator = weston_idalloc_create(&mock_compositor),
|
||||
};
|
||||
struct weston_output mock_output = {};
|
||||
bool ret;
|
||||
|
||||
weston_log_set_handler(no_logger, no_logger);
|
||||
|
||||
mock_cm.base.compositor = &mock_compositor;
|
||||
|
||||
wl_list_init(&mock_compositor.plane_list);
|
||||
weston_output_init(&mock_output, &mock_compositor, "mockoutput");
|
||||
|
||||
|
@ -341,6 +354,7 @@ TEST_P(hdr_metadata_type1_errors, value_cases)
|
|||
|
||||
weston_output_color_outcome_destroy(&mock_output.color_outcome);
|
||||
weston_output_release(&mock_output);
|
||||
weston_idalloc_destroy(mock_compositor.color_profile_id_generator);
|
||||
}
|
||||
|
||||
/* Unflagged members are ignored in validity check */
|
||||
|
@ -366,10 +380,13 @@ TEST(hdr_metadata_type1_ignore_unflagged)
|
|||
};
|
||||
struct weston_compositor mock_compositor = {
|
||||
.color_manager = &mock_cm.base,
|
||||
.color_profile_id_generator = weston_idalloc_create(&mock_compositor),
|
||||
};
|
||||
struct weston_output mock_output = {};
|
||||
bool ret;
|
||||
|
||||
mock_cm.base.compositor = &mock_compositor;
|
||||
|
||||
wl_list_init(&mock_compositor.plane_list);
|
||||
weston_log_set_handler(no_logger, no_logger);
|
||||
|
||||
|
@ -380,4 +397,5 @@ TEST(hdr_metadata_type1_ignore_unflagged)
|
|||
|
||||
weston_output_color_outcome_destroy(&mock_output.color_outcome);
|
||||
weston_output_release(&mock_output);
|
||||
weston_idalloc_destroy(mock_compositor.color_profile_id_generator);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue