
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>
227 lines
6.5 KiB
C
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);
|
|
}
|