[gtk/matthiasc/color-profile-rebased: 22/47] lcmscolorspace: Implement a global transform cache




commit 42c1c20fe8c5812fedf08383ee3be61094db147a
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu May 12 19:55:07 2022 -0400

    lcmscolorspace: Implement a global transform cache
    
    Speeds up things by a factor of 10x, so seems like a good idea.
    
    The cache is never purges, we might want to fix that.

 gdk/gdkcolorspaceprivate.h |  6 ++++
 gdk/gdklcmscolorspace.c    | 80 ++++++++++++++++++++++++++++++++++++++++++++++
 gdk/gdkmemoryformat.c      | 16 ++++------
 3 files changed, 93 insertions(+), 9 deletions(-)
---
diff --git a/gdk/gdkcolorspaceprivate.h b/gdk/gdkcolorspaceprivate.h
index ec02948a71..e0a126a63b 100644
--- a/gdk/gdkcolorspaceprivate.h
+++ b/gdk/gdkcolorspaceprivate.h
@@ -2,6 +2,7 @@
 #define __GDK_COLOR_SPACE_PRIVATE_H__
 
 #include "gdkcolorspace.h"
+#include <lcms2.h>
 
 G_BEGIN_DECLS
 
@@ -25,6 +26,11 @@ struct _GdkColorSpaceClass
 
 GdkColorSpace *          gdk_color_space_get_srgb_linear            (void) G_GNUC_CONST;
 
+cmsHTRANSFORM *          gdk_color_space_lookup_transform           (GdkColorSpace          *source,
+                                                                     guint                   source_type,
+                                                                     GdkColorSpace          *dest,
+                                                                     guint                   dest_type);
+
 G_END_DECLS
 
 #endif /* __GDK_COLOR_SPACE_PRIVATE_H__ */
diff --git a/gdk/gdklcmscolorspace.c b/gdk/gdklcmscolorspace.c
index fa917dea7a..6fc463967a 100644
--- a/gdk/gdklcmscolorspace.c
+++ b/gdk/gdklcmscolorspace.c
@@ -234,3 +234,83 @@ gdk_color_space_get_srgb_linear (void)
 
   return srgb_linear_color_space;
 }
+
+typedef struct _GdkColorTransformCache GdkColorTransformCache;
+
+struct _GdkColorTransformCache
+{
+  GdkColorSpace *source;
+  guint          source_type;
+  GdkColorSpace *dest;
+  guint          dest_type;
+};
+
+static void
+gdk_color_transform_cache_free (gpointer data)
+{
+  g_free (data);
+}
+
+static guint
+gdk_color_transform_cache_hash (gconstpointer data)
+{
+  const GdkColorTransformCache *cache = data;
+
+  return g_direct_hash (cache->source) ^
+         (g_direct_hash (cache->dest) >> 2) ^
+         ((cache->source_type << 16) | (cache->source_type >> 16)) ^
+         cache->dest_type;
+}
+
+static gboolean
+gdk_color_transform_cache_equal (gconstpointer data1,
+                                 gconstpointer data2)
+{
+  const GdkColorTransformCache *cache1 = data1;
+  const GdkColorTransformCache *cache2 = data2;
+
+  return cache1->source == cache2->source &&
+         cache1->source_type == cache2->source_type &&
+         cache1->dest == cache2->dest &&
+         cache1->dest_type == cache2->dest_type;
+}
+
+cmsHTRANSFORM *
+gdk_color_space_lookup_transform (GdkColorSpace *source,
+                                  guint          source_type,
+                                  GdkColorSpace *dest,
+                                  guint          dest_type)
+{
+  GdkColorTransformCache *entry;
+  static GHashTable *cache = NULL;
+  cmsHTRANSFORM *transform;
+
+  if (cache == NULL)
+    cache = g_hash_table_new_full (gdk_color_transform_cache_hash,
+                                   gdk_color_transform_cache_equal,
+                                   gdk_color_transform_cache_free,
+                                   cmsDeleteTransform);
+
+  transform = g_hash_table_lookup (cache,
+                                   &(GdkColorTransformCache) {
+                                     source, source_type,
+                                     dest, dest_type
+                                   });
+  if (G_UNLIKELY (transform == NULL && source && dest))
+    {
+      transform = cmsCreateTransform (gdk_lcms_color_space_get_lcms_profile (source),
+                                      source_type,
+                                      gdk_lcms_color_space_get_lcms_profile (dest),
+                                      dest_type,
+                                      INTENT_PERCEPTUAL,
+                                      cmsFLAGS_COPY_ALPHA);
+      entry = g_new (GdkColorTransformCache, 1);
+      *entry = (GdkColorTransformCache) {
+                 source, source_type,
+                 dest, dest_type
+               };
+      g_hash_table_insert (cache, entry, transform);
+    }
+
+  return transform;
+}
diff --git a/gdk/gdkmemoryformat.c b/gdk/gdkmemoryformat.c
index 32e93c05aa..6c0a1bcf44 100644
--- a/gdk/gdkmemoryformat.c
+++ b/gdk/gdkmemoryformat.c
@@ -833,11 +833,11 @@ static void
 gdk_memory_convert_transform (guchar              *dest_data,
                               gsize                dest_stride,
                               GdkMemoryFormat      dest_format,
-                              GdkColorSpace       *dest_space,
+                              GdkColorSpace       *dest_color_space,
                               const guchar        *src_data,
                               gsize                src_stride,
                               GdkMemoryFormat      src_format,
-                              GdkColorSpace       *src_space,
+                              GdkColorSpace       *src_color_space,
                               gsize                width,
                               gsize                height)
 {
@@ -847,12 +847,11 @@ gdk_memory_convert_transform (guchar              *dest_data,
   guchar *src_tmp, *dest_tmp;
   gsize y;
 
-  transform = cmsCreateTransform (gdk_lcms_color_space_get_lcms_profile (src_space),
-                                  src_desc->lcms.type,
-                                  gdk_lcms_color_space_get_lcms_profile (dest_space),
-                                  dest_desc->lcms.type,
-                                  INTENT_PERCEPTUAL,
-                                  cmsFLAGS_COPY_ALPHA);
+  transform = gdk_color_space_lookup_transform (src_color_space,
+                                                src_desc->lcms.type,
+                                                dest_color_space,
+                                                dest_desc->lcms.type);
+
   if (src_desc->to_lcms)
     src_tmp = g_malloc_n (src_desc->lcms.bpp, width);
   else
@@ -881,7 +880,6 @@ gdk_memory_convert_transform (guchar              *dest_data,
 
   g_free (src_tmp);
   g_free (dest_tmp);
-  cmsDeleteTransform (transform);
 }
 
 void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]