[babl] Limit the size of temporary buffers used by babl.



commit 632de1a4967231302b232bc1b74c97b455f1a5bd
Author: Ãyvind KolÃs <pippin gimp org>
Date:   Sat Oct 27 19:47:52 2012 +0200

    Limit the size of temporary buffers used by babl.
    
    This might fix the issue reported in Bug 686557, though more logic can be
    applied, only do this if it is a multi-step conversion and temporary buffers
    would actually be needed.

 babl/babl-fish-path.c |   71 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 69 insertions(+), 2 deletions(-)
---
diff --git a/babl/babl-fish-path.c b/babl/babl-fish-path.c
index b74f98e..0b630fa 100644
--- a/babl/babl-fish-path.c
+++ b/babl/babl-fish-path.c
@@ -379,6 +379,66 @@ babl_fish_process (Babl       *babl,
   return ret;
 }
 
+/* This size buffer needs to be possible to allocate on the stack..*/
+#define MAX_BUFFER_SIZE   65536
+
+static long
+babl_process_chunks (const Babl *cbabl,
+                     const char *source,
+                     char       *destination,
+                     long        n)
+{
+  Babl *babl = (Babl*)cbabl;
+  const Babl *babl_source;
+  const Babl *babl_dest;
+  int source_bpp = 0;
+  int dest_bpp = 0;
+
+  babl_source = babl->fish.source;
+  babl_dest = babl->fish.destination;
+
+  switch (babl_source->instance.class_type)
+    {
+      case BABL_FORMAT:
+        source_bpp = babl_source->format.bytes_per_pixel;
+        break;
+      case BABL_TYPE:
+        source_bpp = babl_source->type.bits / 8;
+        break;
+      default:
+        fprintf (stderr, "=eeek{%i}\n", babl_source->instance.class_type - BABL_MAGIC);
+    }
+
+  switch (babl_dest->instance.class_type)
+    {
+      case BABL_FORMAT:
+        dest_bpp = babl_dest->format.bytes_per_pixel;
+        break;
+      case BABL_TYPE:
+        dest_bpp = babl_dest->type.bits / 8;
+        break;
+      default:
+        fprintf (stderr, "-eeek{%i}\n", babl_dest->instance.class_type - BABL_MAGIC);
+    }
+
+  babl_assert (source_bpp);
+  babl_assert (dest_bpp);
+
+  long i;
+  for (i = 0; i < n; i += MAX_BUFFER_SIZE)
+    {
+      long c;
+      if (i + MAX_BUFFER_SIZE <= n)
+        c = MAX_BUFFER_SIZE;
+      else
+        c = n - i;
+
+      babl_process (cbabl, source + (i * source_bpp),
+                           destination + (i * dest_bpp), c);
+    }
+  return n;
+}
+
 long
 babl_process (const Babl *cbabl,
               const void *source,
@@ -394,13 +454,20 @@ babl_process (const Babl *cbabl,
     return 0;
   babl_assert (n > 0);
 
-  /* first check if it is a fish since that is out fast path */
+  if (n > MAX_BUFFER_SIZE  &&
+      babl->class_type >= BABL_FISH &&
+      babl->class_type <= BABL_FISH_PATH )
+    /* XXX: should only do the chunking if temporary buffers are needed */
+    return babl_process_chunks (cbabl, source, destination, n);
+
+  /* first check if it is a fish since that is our fast path */
   if (babl->class_type >= BABL_FISH &&
       babl->class_type <= BABL_FISH_PATH)
     {
       babl->fish.processings++;
-      return babl->fish.pixels +=
+      babl->fish.pixels +=
              babl_fish_process (babl, source, destination, n);
+      return n;
     }
 
   /* matches all conversion classes */



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