/* * 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 . * */ #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); }