mutter/clutter/clutter/clutter-pipeline-cache.c
Sebastian Wick 86a0797819 clutter/color-state: Match reference luminance
This uses the luminance levels of the color states to anchor the white
of content instead of hard-coding the levels.

This also starts using uniforms for parts of the mapping which means we
don't have to generate and compile a shader when the luminance levels
change.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3953>
2024-08-30 20:03:43 +00:00

227 lines
6.5 KiB
C

/*
* Copyright (C) 2023 Red Hat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include "clutter/clutter-color-state-private.h"
#include "clutter-pipeline-cache.h"
typedef struct _PipelineGroupEntry
{
GHashTable **slots;
size_t n_slots;
} PipelineGroupEntry;
struct _ClutterPipelineCache
{
GObject parent;
GHashTable *groups;
};
G_DEFINE_TYPE (ClutterPipelineCache, clutter_pipeline_cache, G_TYPE_OBJECT)
static PipelineGroupEntry *
pipeline_group_entry_new (void)
{
PipelineGroupEntry *group_entry;
group_entry = g_new0 (PipelineGroupEntry, 1);
return group_entry;
}
static void
pipeline_group_entry_free (PipelineGroupEntry *group_entry)
{
size_t i;
for (i = 0; i < group_entry->n_slots; i++)
g_clear_pointer (&group_entry->slots[i], g_hash_table_unref);
g_free (group_entry->slots);
g_free (group_entry);
}
static void
clutter_pipeline_cache_dispose (GObject *object)
{
ClutterPipelineCache *pipeline_cache = CLUTTER_PIPELINE_CACHE (object);
g_clear_pointer (&pipeline_cache->groups, g_hash_table_unref);
G_OBJECT_CLASS (clutter_pipeline_cache_parent_class)->dispose (object);
}
static void
clutter_pipeline_cache_class_init (ClutterPipelineCacheClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = clutter_pipeline_cache_dispose;
}
static void
clutter_pipeline_cache_init (ClutterPipelineCache *pipeline_cache)
{
pipeline_cache->groups =
g_hash_table_new_full (NULL,
NULL,
NULL,
(GDestroyNotify) pipeline_group_entry_free);
}
/**
* clutter_pipeline_cache_get_pipeline: (skip)
*/
CoglPipeline *
clutter_pipeline_cache_get_pipeline (ClutterPipelineCache *pipeline_cache,
ClutterPipelineGroup group,
int slot,
ClutterColorState *source_color_state,
ClutterColorState *target_color_state)
{
PipelineGroupEntry *group_entry;
ClutterColorTransformKey key;
CoglPipeline *pipeline;
group_entry = g_hash_table_lookup (pipeline_cache->groups, group);
if (!group_entry)
return NULL;
if (slot >= group_entry->n_slots)
return NULL;
if (!group_entry->slots[slot])
return NULL;
clutter_color_transform_key_init (&key,
source_color_state,
target_color_state);
pipeline = g_hash_table_lookup (group_entry->slots[slot], &key);
if (pipeline)
{
CoglPipeline *new_pipeline;
new_pipeline = cogl_pipeline_copy (pipeline);
clutter_color_state_update_uniforms (source_color_state,
target_color_state,
new_pipeline);
return new_pipeline;
}
else
{
return NULL;
}
}
/**
* clutter_pipeline_cache_sdd_pipeline: (skip)
*/
void
clutter_pipeline_cache_set_pipeline (ClutterPipelineCache *pipeline_cache,
ClutterPipelineGroup group,
int slot,
ClutterColorState *source_color_state,
ClutterColorState *target_color_state,
CoglPipeline *pipeline)
{
PipelineGroupEntry *group_entry;
ClutterColorTransformKey key;
group_entry = g_hash_table_lookup (pipeline_cache->groups, group);
if (!group_entry)
{
group_entry = pipeline_group_entry_new ();
g_hash_table_insert (pipeline_cache->groups, group, group_entry);
}
if (slot >= group_entry->n_slots)
{
size_t new_n_slots;
new_n_slots = slot + 1;
group_entry->slots = g_realloc_n (group_entry->slots,
new_n_slots,
sizeof (GHashTable *));
memset (group_entry->slots + group_entry->n_slots,
0,
(new_n_slots - group_entry->n_slots) * sizeof (GHashTable *));
group_entry->n_slots = new_n_slots;
}
if (!group_entry->slots[slot])
{
group_entry->slots[slot] =
g_hash_table_new_full (clutter_color_transform_key_hash,
clutter_color_transform_key_equal,
g_free,
g_object_unref);
}
clutter_color_transform_key_init (&key,
source_color_state,
target_color_state);
g_hash_table_replace (group_entry->slots[slot],
g_memdup2 (&key, sizeof (key)),
g_object_ref (pipeline));
}
/**
* clutter_pipeline_cache_unset_pipeline: (skip)
*/
void
clutter_pipeline_cache_unset_pipeline (ClutterPipelineCache *pipeline_cache,
ClutterPipelineGroup group,
int slot,
ClutterColorState *source_color_state,
ClutterColorState *target_color_state)
{
PipelineGroupEntry *group_entry;
ClutterColorTransformKey key;
group_entry = g_hash_table_lookup (pipeline_cache->groups, group);
if (!group_entry)
return;
if (slot >= group_entry->n_slots)
return;
if (!group_entry->slots[slot])
return;
clutter_color_transform_key_init (&key,
source_color_state,
target_color_state);
g_hash_table_remove (group_entry->slots[slot], &key);
}
/**
* clutter_pipeline_cache_unset_all_pipeline: (skip)
*/
void
clutter_pipeline_cache_unset_all_pipelines (ClutterPipelineCache *pipeline_cache,
ClutterPipelineGroup group)
{
g_hash_table_remove (pipeline_cache->groups, group);
}