[gimp] libgimpwidgets: cache gimp_widget_get_color_transform()'s GimpColorTransforms



commit d6ee1dc5cf5c2a8751a76abaf307910318abe527
Author: Michael Natterer <mitch gimp org>
Date:   Fri May 27 21:55:06 2016 +0200

    libgimpwidgets: cache gimp_widget_get_color_transform()'s GimpColorTransforms
    
    Now that more and more widgets are color managed, we need transforms
    for all of them. Creating them is very expensive.
    
    The new cache returns the same transform for a combination of (config,
    src_profile, src_format, dest_format) and invalidates itself
    automatically on config changes. The number of transforms goes down
    from potentially hundreds to a handful, and the cost of a config
    change from many seconds to virtually instant.

 libgimpwidgets/gimpwidgetsutils.c |  181 +++++++++++++++++++++++++++++++++----
 1 files changed, 161 insertions(+), 20 deletions(-)
---
diff --git a/libgimpwidgets/gimpwidgetsutils.c b/libgimpwidgets/gimpwidgetsutils.c
index 659e7bd..0f5e4e4 100644
--- a/libgimpwidgets/gimpwidgetsutils.c
+++ b/libgimpwidgets/gimpwidgetsutils.c
@@ -479,6 +479,87 @@ get_display_profile (GtkWidget       *widget,
   return profile;
 }
 
+typedef struct _TransformCache TransformCache;
+
+struct _TransformCache
+{
+  GimpColorTransform *transform;
+
+  GimpColorConfig    *config;
+  GimpColorProfile   *src_profile;
+  const Babl         *src_format;
+  GimpColorProfile   *dest_profile;
+  const Babl         *dest_format;
+  GimpColorProfile   *proof_profile;
+
+  gulong              notify_id;
+};
+
+static GList    *transform_caches = NULL;
+static gboolean  debug_cache      = FALSE;
+
+static gboolean
+profiles_equal (GimpColorProfile *profile1,
+                GimpColorProfile *profile2)
+{
+  return ((profile1 == NULL && profile2 == NULL) ||
+          (profile1 != NULL && profile2 != NULL &&
+           gimp_color_profile_is_equal (profile1, profile2)));
+}
+
+static TransformCache *
+transform_cache_get (GimpColorConfig  *config,
+                     GimpColorProfile *src_profile,
+                     const Babl       *src_format,
+                     GimpColorProfile *dest_profile,
+                     const Babl       *dest_format,
+                     GimpColorProfile *proof_profile)
+{
+  GList *list;
+
+  for (list = transform_caches; list; list = g_list_next (list))
+    {
+      TransformCache *cache = list->data;
+
+      if (config      == cache->config                        &&
+          src_format  == cache->src_format                    &&
+          dest_format == cache->dest_format                   &&
+          profiles_equal (src_profile,   cache->src_profile)  &&
+          profiles_equal (dest_profile,  cache->dest_profile) &&
+          profiles_equal (proof_profile, cache->proof_profile))
+        {
+          if (debug_cache)
+            g_printerr ("found cache %p\n", cache);
+
+          return cache;
+        }
+    }
+
+  return NULL;
+}
+
+static void
+transform_cache_config_notify (GObject          *config,
+                               const GParamSpec *pspec,
+                               TransformCache   *cache)
+{
+  transform_caches = g_list_remove (transform_caches, cache);
+
+  g_signal_handler_disconnect (config, cache->notify_id);
+
+  g_object_unref (cache->transform);
+  g_object_unref (cache->src_profile);
+  g_object_unref (cache->dest_profile);
+
+  if (cache->proof_profile)
+    g_object_unref (cache->proof_profile);
+
+  g_free (cache);
+
+  if (debug_cache)
+    g_printerr ("deleted cache %p\n", cache);
+}
+
 GimpColorTransform *
 gimp_widget_get_color_transform (GtkWidget        *widget,
                                  GimpColorConfig  *config,
@@ -486,17 +567,24 @@ gimp_widget_get_color_transform (GtkWidget        *widget,
                                  const Babl       *src_format,
                                  const Babl       *dest_format)
 {
-  GimpColorTransform *transform     = NULL;
+  static gboolean     initialized   = FALSE;
   GimpColorProfile   *dest_profile  = NULL;
   GimpColorProfile   *proof_profile = NULL;
-  cmsUInt16Number     alarmCodes[cmsMAXCHANNELS] = { 0, };
+  TransformCache     *cache;
 
   g_return_val_if_fail (widget == NULL || GTK_IS_WIDGET (widget), NULL);
-  g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (src_profile), NULL);
   g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), NULL);
+  g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (src_profile), NULL);
   g_return_val_if_fail (src_format != NULL, NULL);
   g_return_val_if_fail (dest_format != NULL, NULL);
 
+  if (G_UNLIKELY (! initialized))
+    {
+      initialized = TRUE;
+
+      debug_cache = g_getenv ("GIMP_DEBUG_TRANSFORM_CACHE") != NULL;
+    }
+
   switch (config->mode)
     {
     case GIMP_COLOR_MANAGEMENT_OFF:
@@ -511,7 +599,54 @@ gimp_widget_get_color_transform (GtkWidget        *widget,
       break;
     }
 
-  if (proof_profile)
+  cache = transform_cache_get (config,
+                               src_profile,
+                               src_format,
+                               dest_profile,
+                               dest_format,
+                               proof_profile);
+
+  if (cache)
+    {
+      g_object_unref (dest_profile);
+
+      if (proof_profile)
+        g_object_unref (proof_profile);
+
+      if (cache->transform)
+        return g_object_ref (cache->transform);
+
+      return NULL;
+    }
+
+  if (! proof_profile &&
+      gimp_color_profile_is_equal (src_profile, dest_profile))
+    {
+      g_object_unref (dest_profile);
+
+      return NULL;
+    }
+
+  cache = g_new0 (TransformCache, 1);
+
+  if (debug_cache)
+    g_printerr ("creating cache %p\n", cache);
+
+  cache->config        = g_object_ref (config);
+  cache->src_profile   = g_object_ref (src_profile);
+  cache->src_format    = src_format;
+  cache->dest_profile  = dest_profile;
+  cache->dest_format   = dest_format;
+  cache->proof_profile = proof_profile;
+
+  cache->notify_id =
+    g_signal_connect (cache->config, "notify",
+                      G_CALLBACK (transform_cache_config_notify),
+                      cache);
+
+  transform_caches = g_list_prepend (transform_caches, cache);
+
+  if (cache->proof_profile)
     {
       GimpColorTransformFlags flags = 0;
 
@@ -522,7 +657,8 @@ gimp_widget_get_color_transform (GtkWidget        *widget,
 
       if (config->simulation_gamut_check)
         {
-          guchar r, g, b;
+          cmsUInt16Number alarmCodes[cmsMAXCHANNELS] = { 0, };
+          guchar          r, g, b;
 
           flags |= GIMP_COLOR_TRANSFORM_FLAGS_GAMUT_CHECK;
 
@@ -535,16 +671,17 @@ gimp_widget_get_color_transform (GtkWidget        *widget,
           cmsSetAlarmCodes (alarmCodes);
         }
 
-      transform = gimp_color_transform_new_proofing (src_profile,  src_format,
-                                                     dest_profile, dest_format,
-                                                     proof_profile,
-                                                     config->simulation_intent,
-                                                     config->display_intent,
-                                                     flags);
-
-      g_object_unref (proof_profile);
+      cache->transform =
+        gimp_color_transform_new_proofing (cache->src_profile,
+                                           cache->src_format,
+                                           cache->dest_profile,
+                                           cache->dest_format,
+                                           cache->proof_profile,
+                                           config->simulation_intent,
+                                           config->display_intent,
+                                           flags);
     }
-  else if (! gimp_color_profile_is_equal (src_profile, dest_profile))
+  else
     {
       GimpColorTransformFlags flags = 0;
 
@@ -553,13 +690,17 @@ gimp_widget_get_color_transform (GtkWidget        *widget,
           flags |= GIMP_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION;
         }
 
-      transform = gimp_color_transform_new (src_profile,  src_format,
-                                            dest_profile, dest_format,
-                                            config->display_intent,
-                                            flags);
+      cache->transform =
+        gimp_color_transform_new (cache->src_profile,
+                                  cache->src_format,
+                                  cache->dest_profile,
+                                  cache->dest_format,
+                                  config->display_intent,
+                                  flags);
     }
 
-  g_object_unref (dest_profile);
+  if (cache->transform)
+    return g_object_ref (cache->transform);
 
-  return transform;
+  return NULL;
 }


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