gegl r2178 - in trunk: . gegl gegl/buffer



Author: ok
Date: Wed Apr 16 21:24:57 2008
New Revision: 2178
URL: http://svn.gnome.org/viewvc/gegl?rev=2178&view=rev

Log:
Made the tile caching in GeglBuffer work more correctly, earlier
completely fresh tiles as well as generated zoom tiles needed to
be written to backend/swap before being re-read into the cache.
Now the code uses a global queue for the tile cache, this can later
be changed to properly gauge the amount of memory used by the cache
(shared data should be taken into account then).
* gegl/buffer/gegl-buffer-load.c:
* gegl/buffer/gegl-buffer-save.c: fixed includes.
* gegl/buffer/gegl-buffer-private.h: makde GeglBuffer be a subclass
of GeglHandler not GeglHandlers.
* gegl/buffer/gegl-buffer.c: do not create buffers via gegl-allocator
but create a new storage for each toplevel buffer.
* gegl/buffer/gegl-handler-cache.[ch]: made all tile caches share a
global queue.
* gegl/buffer/gegl-handler-zoom.c: (get_tile):
* gegl/buffer/gegl-handler-empty.c: (get_tile): add capability to add
newly created tiles to the relevant tile cache. (for now the cache
is fetched via g_object_get_data (empty. "cache")
* gegl/buffer/gegl-storage.c: (gegl_storage_constructor): set cache
data on empty and zoom handlers.
* gegl/buffer/gegl-tile.c: (gegl_tile_void): set storage to NULL so
that a voided tile will not be written to storage.
* gegl/gegl-init.c: (gegl_exit): call gegl_tile_cache_destroy to
destroy the global cache queue upon GEGL shutdown.
* gegl/buffer/gegl-buffer-allocator.c: removed
* gegl/buffer/gegl-buffer-allocator.h: removed
* gegl/buffer/Makefile.am:  removed reference to
gegl-buffer-allocator.*


Removed:
   trunk/gegl/buffer/gegl-buffer-allocator.c
   trunk/gegl/buffer/gegl-buffer-allocator.h
Modified:
   trunk/ChangeLog
   trunk/gegl/buffer/Makefile.am
   trunk/gegl/buffer/gegl-buffer-load.c
   trunk/gegl/buffer/gegl-buffer-private.h
   trunk/gegl/buffer/gegl-buffer-save.c
   trunk/gegl/buffer/gegl-buffer.c
   trunk/gegl/buffer/gegl-handler-cache.c
   trunk/gegl/buffer/gegl-handler-cache.h
   trunk/gegl/buffer/gegl-handler-empty.c
   trunk/gegl/buffer/gegl-handler-zoom.c
   trunk/gegl/buffer/gegl-storage.c
   trunk/gegl/buffer/gegl-tile.c
   trunk/gegl/gegl-init.c

Modified: trunk/gegl/buffer/Makefile.am
==============================================================================
--- trunk/gegl/buffer/Makefile.am	(original)
+++ trunk/gegl/buffer/Makefile.am	Wed Apr 16 21:24:57 2008
@@ -1,7 +1,6 @@
 noinst_LTLIBRARIES = libbuffer.la
 
 BUFFER_sources = \
-    gegl-buffer-allocator.c	\
     gegl-buffer-save.c		\
     gegl-buffer-load.c		\
     gegl-buffer.c		\
@@ -28,7 +27,6 @@
     gegl-source.c
 
 BUFFER_headers = \
-    gegl-buffer-allocator.h	\
     gegl-buffer.h		\
     gegl-buffer-private.h	\
     gegl-buffer-save.h		\

Modified: trunk/gegl/buffer/gegl-buffer-load.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-load.c	(original)
+++ trunk/gegl/buffer/gegl-buffer-load.c	Wed Apr 16 21:24:57 2008
@@ -45,7 +45,6 @@
 #include "gegl-handler-cache.h"
 #include "gegl-handler-log.h"
 #include "gegl-handler-empty.h"
-#include "gegl-buffer-allocator.h"
 #include "gegl-types.h"
 #include "gegl-utils.h"
 #include "gegl-buffer-save.h"

Modified: trunk/gegl/buffer/gegl-buffer-private.h
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-private.h	(original)
+++ trunk/gegl/buffer/gegl-buffer-private.h	Wed Apr 16 21:24:57 2008
@@ -20,7 +20,7 @@
 #define __GEGL_BUFFER_PRIVATE_H__
 
 #include "gegl-buffer.h"
-#include "gegl-handlers.h"
+#include "gegl-handler.h"
 
 #define GEGL_BUFFER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  GEGL_TYPE_BUFFER, GeglBufferClass))
 #define GEGL_IS_BUFFER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEGL_TYPE_BUFFER))
@@ -29,7 +29,7 @@
 
 struct _GeglBuffer
 {
-  GeglHandlers      parent_instance; /* which is a GeglHandler which has a
+  GeglHandler       parent_instance; /* which is a GeglHandler which has a
                                         source field which is used for chaining
                                         sub buffers with their anchestors */
 
@@ -62,7 +62,7 @@
 
 struct _GeglBufferClass
 {
-  GeglHandlersClass parent_class;
+  GeglHandlerClass parent_class;
 };
 
 
@@ -83,4 +83,9 @@
 
 const gchar *  gegl_swap_dir          (void);
 
+
+void           gegl_tile_cache_init    (void);
+
+void           gegl_tile_cache_destroy (void);
+
 #endif

Modified: trunk/gegl/buffer/gegl-buffer-save.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-save.c	(original)
+++ trunk/gegl/buffer/gegl-buffer-save.c	Wed Apr 16 21:24:57 2008
@@ -43,6 +43,7 @@
 
 #include "gegl-buffer-types.h"
 #include "gegl-buffer.h"
+#include "gegl-buffer-private.h"
 #include "gegl-storage.h"
 #include "gegl-tile-backend.h"
 #include "gegl-handler.h"
@@ -50,7 +51,6 @@
 #include "gegl-handler-cache.h"
 #include "gegl-handler-log.h"
 #include "gegl-handler-empty.h"
-#include "gegl-buffer-allocator.h"
 #include "gegl-types.h"
 #include "gegl-utils.h"
 #include "gegl-buffer-save.h"

Modified: trunk/gegl/buffer/gegl-buffer.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer.c	(original)
+++ trunk/gegl/buffer/gegl-buffer.c	Wed Apr 16 21:24:57 2008
@@ -20,22 +20,40 @@
 
 #include <math.h>
 #include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef G_OS_WIN32
+#include <process.h>
+#define getpid() _getpid()
+#endif
 
 #include <glib-object.h>
+#include <glib/gstdio.h>
+#include <glib/gprintf.h>
 
 #include "gegl-types.h"
 
 #include "gegl-buffer-types.h"
 #include "gegl-buffer.h"
-#include "gegl-buffer-allocator.h"
+#include "gegl-buffer-private.h"
+#include "gegl-handler.h"
 #include "gegl-storage.h"
 #include "gegl-tile-backend.h"
-#include "gegl-handler.h"
 #include "gegl-tile.h"
 #include "gegl-handler-cache.h"
 #include "gegl-handler-log.h"
 #include "gegl-handler-empty.h"
-#include "gegl-buffer-allocator.h"
 #include "gegl-sampler-nearest.h"
 #include "gegl-sampler-linear.h"
 #include "gegl-sampler-cubic.h"
@@ -44,7 +62,7 @@
 #include "gegl-id-pool.h"
 
 
-G_DEFINE_TYPE (GeglBuffer, gegl_buffer, GEGL_TYPE_HANDLERS)
+G_DEFINE_TYPE (GeglBuffer, gegl_buffer, GEGL_TYPE_HANDLER)
 
 #if ENABLE_MP
 GStaticRecMutex mutex = G_STATIC_REC_MUTEX_INIT;
@@ -70,6 +88,11 @@
   PROP_PIXELS
 };
 
+static GeglBuffer * gegl_buffer_new_from_format (const void *babl_format,
+                                                 gint        x,
+                                                 gint        y,
+                                                 gint        width,
+                                                 gint        height);
 
 static inline gint needed_tiles (gint w,
                                  gint stride)
@@ -234,10 +257,11 @@
   gegl_buffer_sample_cleanup (buffer);
 
   if (handler->source &&
-      GEGL_IS_BUFFER_ALLOCATOR (handler->source))
+      GEGL_IS_STORAGE (handler->source))
     {
       gegl_buffer_void (buffer);
 #if 0
+      g_object_unref (handler->source);
       handler->source = NULL; /* this might be a dangerous way of marking that we have already voided */
 #endif
     }
@@ -297,7 +321,6 @@
 {
   GObject         *object;
   GeglBuffer      *buffer;
-  GeglHandlers    *handlers;
   GeglTileBackend *backend;
   GeglHandler     *handler;
   GeglSource    *source;
@@ -307,7 +330,6 @@
   object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
 
   buffer    = GEGL_BUFFER (object);
-  handlers  = GEGL_HANDLERS (object);
   handler   = GEGL_HANDLER (object);
   source  = handler->source;
   backend   = gegl_buffer_backend (buffer);
@@ -330,10 +352,10 @@
       g_assert (buffer->format);
 
       source = GEGL_SOURCE (gegl_buffer_new_from_format (buffer->format,
-                                                             buffer->extent.x,
-                                                             buffer->extent.y,
-                                                             buffer->extent.width,
-                                                             buffer->extent.height));
+                                                         buffer->extent.x,
+                                                         buffer->extent.y,
+                                                         buffer->extent.width,
+                                                         buffer->extent.height));
       /* after construction,. x and y should be set to reflect
        * the top level behavior exhibited by this buffer object.
        */
@@ -441,66 +463,47 @@
 
   buffer->storage = gegl_buffer_storage (buffer);
 
-  if (0) gegl_handlers_add (handlers, g_object_new (GEGL_TYPE_HANDLER_EMPTY,
-                                                     "backend", backend,
-                                                     NULL));
-
-  /* add a full width (should probably add height as well) sized cache for
-   * this gegl_buffer only if the width is < 16384. The huge buffers used
-   * by the allocator are thus not affected, but all other buffers should
-   * have a enough tiles to be scanline iteratable.
-   */
-
-  if (0 && buffer->extent.width < 1 << 14)
-    gegl_handlers_add (handlers, g_object_new (GEGL_TYPE_HANDLER_CACHE,
-                                                "size",
-                                                needed_tiles (buffer->extent.width, tile_width) + 1,
-                                                NULL));
-
   return object;
 }
 
 static GeglTile *
-get_tile (GeglSource *buffer,
+get_tile (GeglSource *source,
           gint        x,
           gint        y,
           gint        z)
 {
-  GeglHandlers *handlers = (GeglHandlers*)(buffer);
-  GeglSource *source = ((GeglHandler*)buffer)->source;
-  GeglTile     *tile   = NULL;
-
-  if (handlers->chain != NULL)
-    tile = gegl_source_get_tile ((GeglSource*)(handlers->chain->data),
-                                     x, y, z);
-  else if (source)
+  GeglHandler *handler = GEGL_HANDLER (source);
+  GeglTile    *tile   = NULL;
+  source = handler->source;
+
+  if (source) 
     tile = gegl_source_get_tile (source, x, y, z);
   else
     g_assert (0);
 
   if (tile)
     {
-      GeglBuffer *buf = (GeglBuffer*)(buffer);
+      GeglBuffer *buffer = GEGL_BUFFER (handler);
       tile->x = x;
       tile->y = y;
       tile->z = z;
 
-      if (x < buf->min_x)
-        buf->min_x = x;
-      if (y < buf->min_y)
-        buf->min_y = y;
-      if (x > buf->max_x)
-        buf->max_x = x;
-      if (y > buf->max_y)
-        buf->max_y = y;
-      if (z > buf->max_z)
-        buf->max_z = z;
+      if (x < buffer->min_x)
+        buffer->min_x = x;
+      if (y < buffer->min_y)
+        buffer->min_y = y;
+      if (x > buffer->max_x)
+        buffer->max_x = x;
+      if (y > buffer->max_y)
+        buffer->max_y = y;
+      if (z > buffer->max_z)
+        buffer->max_z = z;
 
       /* storing information in tile, to enable the dispose function of the
        * tile instance to "hook" back to the storage with correct coordinates.
        */
       {
-        tile->storage   = buf->storage;
+        tile->storage   = buffer->storage;
         tile->storage_x = x;
         tile->storage_y = y;
         tile->storage_z = z;
@@ -512,16 +515,21 @@
 
 
 static gpointer
-command (GeglSource   *buffer,
+command (GeglSource     *source,
          GeglTileCommand command,
          gint            x,
          gint            y,
          gint            z,
          gpointer        data)
 {
-  if (command == GEGL_TILE_GET)
-    return get_tile (buffer, x, y, z);
-  return gegl_handler_chain_up (GEGL_HANDLER(buffer), command, x, y, z, data);
+  GeglHandler *handler = GEGL_HANDLER (source);
+  switch (command)
+    {
+      case GEGL_TILE_GET:
+        return get_tile (source, x, y, z);
+      default:
+        return gegl_handler_chain_up (handler, command, x, y, z, data);
+    }
 }
 
 static void
@@ -692,12 +700,6 @@
   }
 }
 
-
-/*
- * babl conversion should probably be done on a tile by tile, or even scanline by
- * scanline basis instead of allocating large temporary buffers. (using babl for "memcpy")
- */
-
 #ifdef BABL
 #undef BABL
 #endif
@@ -749,9 +751,9 @@
         gint      tiledx = buffer_x + buffer->shift_x + x;
 
         GeglTile *tile = gegl_source_get_tile ((GeglSource *) (buffer),
-                                                   gegl_tile_indice (tiledx, tile_width),
-                                                   gegl_tile_indice (tiledy, tile_height),
-                                                   0);
+                                                gegl_tile_indice (tiledx, tile_width),
+                                                gegl_tile_indice (tiledy, tile_height),
+                                                0);
 
         if (tile)
           {
@@ -1937,7 +1939,6 @@
   return id;
 }
 
-#include <glib/gprintf.h>
 
 void
 gegl_buffer_make_uri (gchar       *buf_128,
@@ -2004,3 +2005,95 @@
   g_warning ("don't know how to handle buffer path: %s", uri);
   return NULL;
 }
+
+
+
+static GeglBuffer *
+gegl_buffer_new_from_format (const void *babl_format,
+                             gint        x,
+                             gint        y,
+                             gint        width,
+                             gint        height)
+{
+  GeglStorage *storage;
+  GeglBuffer  *buffer;
+  gchar       *filename;
+  gchar       *path;
+  static       gint no=1;
+
+  filename = g_strdup_printf ("GEGL-%i-%s-%i.swap",
+                              getpid (),
+                              babl_name ((Babl *) babl_format),
+                              no++);
+
+  filename = g_strdup_printf ("%i-%i", getpid(), no++);
+
+  path = g_build_filename (gegl_swap_dir (), filename, NULL);
+  g_free (filename);
+
+  if (gegl_swap_dir ())
+    {
+      storage = g_object_new (GEGL_TYPE_STORAGE,
+                              "format", babl_format,
+                              "path",   path,
+                              NULL);
+    }
+  else
+    {
+      storage = g_object_new (GEGL_TYPE_STORAGE,
+                              "format", babl_format,
+                              NULL);
+    }
+  buffer = g_object_new (GEGL_TYPE_BUFFER,
+                                    "source", storage,
+                                    "x", x,
+                                    "y", y,
+                                    "width", width,
+                                    "height", height,
+                                    NULL);
+
+  g_object_unref (storage);
+  return buffer;
+}
+
+
+/* if this function is made to return NULL swapping is disabled */
+const gchar *
+gegl_swap_dir (void)
+{
+  static gchar *swapdir = "";
+
+  if (swapdir && swapdir[0] == '\0')
+    {
+      if (g_getenv ("GEGL_SWAP"))
+        {
+          if (g_str_equal (g_getenv ("GEGL_SWAP"), "RAM"))
+            swapdir = NULL;
+          else
+            swapdir = g_strdup (g_getenv ("GEGL_SWAP"));
+        }
+      else
+        {
+          swapdir = g_build_filename (g_get_home_dir(),
+                                      "." GEGL_LIBRARY,
+                                      "swap",
+                                      NULL);
+        }
+
+      /* Fall back to "swapping to RAM" if not able to create swap dir
+       */
+      if (swapdir &&
+          ! g_file_test (swapdir, G_FILE_TEST_IS_DIR) &&
+          g_mkdir_with_parents (swapdir, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
+        {
+          gchar *name = g_filename_display_name (swapdir);
+
+          g_warning ("unable to create swapdir '%s': %s",
+                     name, g_strerror (errno));
+          g_free (name);
+
+          swapdir = NULL;
+        }
+    }
+  return swapdir;
+};

Modified: trunk/gegl/buffer/gegl-handler-cache.c
==============================================================================
--- trunk/gegl/buffer/gegl-handler-cache.c	(original)
+++ trunk/gegl/buffer/gegl-handler-cache.c	Wed Apr 16 21:24:57 2008
@@ -23,9 +23,30 @@
 
 #include "../gegl-types.h"
 #include "gegl-buffer.h"
+#include "gegl-buffer-private.h"
 #include "gegl-tile.h"
 #include "gegl-handler-cache.h"
 
+/* FIXME: this global cache should have configurable size and wash percentage */
+
+static GQueue *cache_queue = NULL;
+static gint    cache_size = 512;
+static gint    cache_wash_percentage = 20;
+static gint    cache_hits = 0;
+static gint    cache_misses = 0;
+
+void gegl_tile_cache_init (void)
+{
+  if (cache_queue == NULL)
+    cache_queue = g_queue_new ();
+}
+
+void gegl_tile_cache_destroy (void)
+{
+  if (cache_queue)
+    g_queue_free (cache_queue);
+  cache_queue = NULL;
+}
 
 static gboolean    gegl_handler_cache_wash     (GeglHandlerCache *cache);
 
@@ -38,7 +59,7 @@
                                                 gint              x,
                                                 gint              y,
                                                 gint              z);
-static void        gegl_handler_cache_insert   (GeglHandlerCache *cache,
+       void        gegl_handler_cache_insert   (GeglHandlerCache *cache,
                                                 GeglTile         *tile,
                                                 gint              x,
                                                 gint              y,
@@ -50,27 +71,23 @@
 
 G_DEFINE_TYPE (GeglHandlerCache, gegl_handler_cache, GEGL_TYPE_HANDLER)
 
-enum
-{
-  PROP_0,
-  PROP_SIZE,
-  PROP_WASH_PERCENTAGE
-};
-
 typedef struct CacheItem
 {
+  GeglHandlerCache *handler; /* identify the handler as well, thus allowing
+                              * all buffers to share a common cache
+                              */
   GeglTile *tile;
   gint      x;
   gint      y;
   gint      z;
 } CacheItem;
 
+
 static void
 finalize (GObject *object)
 {
-  GeglHandlerCache *cache = (GeglHandlerCache *) object;
-
-  g_queue_free (cache->queue);
+  GeglHandlerCache *cache;
+  cache = (GeglHandlerCache *) object;
 
   G_OBJECT_CLASS (gegl_handler_cache_parent_class)->finalize (object);
 }
@@ -78,40 +95,45 @@
 static void
 dispose (GObject *object)
 {
-  GeglHandlerCache *cache = (GeglHandlerCache *) object;
+  GeglHandlerCache *cache;
   CacheItem        *item;
+  cache = (GeglHandlerCache *) object;
 
   if (0)
     g_printerr ("Disposing tile-cache of size %i, hits: %i misses: %i  hit percentage:%f)\n",
-                cache->size, cache->hits, cache->misses,
-                cache->hits * 100.0 / (cache->hits + cache->misses));
+                cache_size, cache_hits, cache_misses,
+                cache_hits * 100.0 / (cache_hits + cache_misses));
 
-  while ((item = g_queue_pop_head (cache->queue)))
+  /* FIXME: only throw out this cache's items */
+  while ((item = g_queue_pop_head (cache_queue)))
     {
       g_object_unref (item->tile);
       g_slice_free (CacheItem, item);
     }
+  /* FIXME: if queue is empty destroy global queue */
 
   G_OBJECT_CLASS (gegl_handler_cache_parent_class)->dispose (object);
 }
 
 static GeglTile *
 get_tile (GeglSource *tile_store,
-          gint           x,
-          gint           y,
-          gint           z)
+          gint        x,
+          gint        y,
+          gint        z)
 {
   GeglHandlerCache *cache    = GEGL_HANDLER_CACHE (tile_store);
-  GeglSource     *source = GEGL_HANDLER (tile_store)->source;
+  GeglSource       *source = GEGL_HANDLER (tile_store)->source;
   GeglTile         *tile     = NULL;
 
+  if(0)g_print ("%f%% hit:%i miss:%i  \r", cache_hits*100.0/(cache_hits+cache_misses), cache_hits, cache_misses);
+
   tile = gegl_handler_cache_get_tile (cache, x, y, z);
   if (tile)
     {
-      cache->hits++;
+      cache_hits++;
       return tile;
     }
-  cache->misses++;
+  cache_misses++;
 
   if (source)
     tile = gegl_source_get_tile (source, x, y, z);
@@ -135,86 +157,33 @@
   GeglHandlerCache *cache   = GEGL_HANDLER_CACHE (handler);
 
   /* FIXME: replace with switch */
-
-  if (command == GEGL_TILE_GET)
-    {
-      return get_tile (tile_store, x, y, z);
-    }
-  
-  if (command == GEGL_TILE_IS_CACHED)
-    {
-      return (gpointer)gegl_handler_cache_has_tile (cache, x, y, z);
-    }
-  if (command == GEGL_TILE_EXIST)
-    {
-      gboolean is_cached = gegl_handler_cache_has_tile (cache, x, y, z);
-      if (is_cached)
-        return (gpointer)TRUE; /* XXX: perhaps we could return an integer/pointer
-                      * value over the bus instead of a boolean?
-                      */
-      /* otherwise pass on the request */
-    }
-
-  if (command == GEGL_TILE_IDLE)
-    {
-      gboolean action = gegl_handler_cache_wash (cache);
-      if (action)
-        return (gpointer)action;
-    }
-  if (command == GEGL_TILE_VOID)
-    {
-      gegl_handler_cache_void (cache, x, y, z);
-      return NULL;
-    }
-  return gegl_handler_chain_up (handler, command, x, y, z, data);
-}
-
-static void
-get_property (GObject    *gobject,
-              guint       property_id,
-              GValue     *value,
-              GParamSpec *pspec)
-{
-  GeglHandlerCache *cache = GEGL_HANDLER_CACHE (gobject);
-
-  switch (property_id)
-    {
-      case PROP_SIZE:
-        g_value_set_int (value, cache->size);
-        break;
-
-      case PROP_WASH_PERCENTAGE:
-        g_value_set_int (value, cache->wash_percentage);
-        break;
-
-      default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
-        break;
-    }
-}
-
-static void
-set_property (GObject      *gobject,
-              guint         property_id,
-              const GValue *value,
-              GParamSpec   *pspec)
-{
-  GeglHandlerCache *cache = GEGL_HANDLER_CACHE (gobject);
-
-  switch (property_id)
+  switch (command)
     {
-      case PROP_SIZE:
-        cache->size = g_value_get_int (value);
-        return;
-
-      case PROP_WASH_PERCENTAGE:
-        cache->wash_percentage = g_value_get_int (value);
-        return;
-
+      case GEGL_TILE_GET:
+        return get_tile (tile_store, x, y, z);
+      case GEGL_TILE_IS_CACHED:
+        return (gpointer)gegl_handler_cache_has_tile (cache, x, y, z);
+      case GEGL_TILE_EXIST:
+        {
+          gboolean exist = gegl_handler_cache_has_tile (cache, x, y, z);
+          if (exist)
+            return (gpointer)TRUE;
+        }
+        break; /* chain up */
+      case GEGL_TILE_IDLE:
+        {
+          gboolean action = gegl_handler_cache_wash (cache);
+          if (action)
+            return (gpointer)action;
+          break;
+        }
+      case GEGL_TILE_VOID:
+        gegl_handler_cache_void (cache, x, y, z);
+        /* fallthrough */
       default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
         break;
     }
+  return gegl_handler_chain_up (handler, command, x, y, z, data);
 }
 
 static void
@@ -223,37 +192,18 @@
   GObjectClass      *gobject_class  = G_OBJECT_CLASS (class);
   GeglSourceClass *source_class = GEGL_SOURCE_CLASS (class);
 
-  gobject_class->set_property = set_property;
-  gobject_class->get_property = get_property;
   gobject_class->finalize     = finalize;
   gobject_class->dispose      = dispose;
 
   source_class->command  = command;
-
-  g_object_class_install_property (gobject_class, PROP_SIZE,
-                                   g_param_spec_int ("size",
-                                                     "size",
-                                                     "Number of tiles in cache",
-                                                     0, G_MAXINT, 32,
-                                                     G_PARAM_READWRITE |
-                                                     G_PARAM_CONSTRUCT_ONLY));
-
-  g_object_class_install_property (gobject_class, PROP_WASH_PERCENTAGE,
-                                   g_param_spec_int ("wash-percentage",
-                                                     "wash percentage",
-                                                     "(integer 0..100, percentage to wash)",
-                                                     0, 100, 20,
-                                                     G_PARAM_READWRITE |
-                                                     G_PARAM_CONSTRUCT_ONLY));
 }
 
 static void
 gegl_handler_cache_init (GeglHandlerCache *cache)
 {
-  cache->queue = g_queue_new ();
+  gegl_tile_cache_init ();
 }
 
-
 /* write the least recently used dirty tile to disk if it
  * is in the wash_percentage (20%) least recently used tiles,
  * calling this function in an idle handler distributes the
@@ -264,10 +214,10 @@
 {
   GeglTile  *last_dirty = NULL;
   guint      count      = 0;
-  gint       wash_tiles = cache->wash_percentage * cache->size / 100;
+  gint       wash_tiles = cache_wash_percentage * cache_size / 100;
   GList     *link;
 
-  for (link = g_queue_peek_head_link (cache->queue); link; link = link->next)
+  for (link = g_queue_peek_head_link (cache_queue); link; link = link->next)
     {
       CacheItem *item = link->data;
       GeglTile  *tile = item->tile;
@@ -275,7 +225,7 @@
       count++;
       if (!gegl_tile_is_stored (tile))
         {
-          if (count > cache->size - wash_tiles)
+          if (count > cache_size - wash_tiles)
             {
               last_dirty = tile;
             }
@@ -300,12 +250,13 @@
 {
   GList *link;
 
-  for (link = g_queue_peek_head_link (cache->queue); link; link = link->next)
+  for (link = g_queue_peek_head_link (cache_queue); link; link = link->next)
     {
       CacheItem *item = link->data;
       GeglTile  *tile = item->tile;
 
       if (tile != NULL &&
+          item->handler == cache &&
           item->x == x &&
           item->y == y &&
           item->z == z)
@@ -313,8 +264,8 @@
           /* move the link to the front of the queue */
           if (link->prev != NULL)
             {
-              g_queue_unlink (cache->queue, link);
-              g_queue_push_head_link (cache->queue, link);
+              g_queue_unlink (cache_queue, link);
+              g_queue_push_head_link (cache_queue, link);
             }
 
           return g_object_ref (tile);
@@ -345,7 +296,7 @@
 static gboolean
 gegl_handler_cache_trim (GeglHandlerCache *cache)
 {
-  CacheItem *last_writable = g_queue_pop_tail (cache->queue);
+  CacheItem *last_writable = g_queue_pop_tail (cache_queue);
 
   if (last_writable != NULL)
     {
@@ -366,7 +317,7 @@
 {
   GList *link;
 
-  for (link = g_queue_peek_head_link (cache->queue); link; link = link->next)
+  for (link = g_queue_peek_head_link (cache_queue); link; link = link->next)
     {
       CacheItem *item = link->data;
       GeglTile  *tile = item->tile;
@@ -374,12 +325,13 @@
       if (tile != NULL &&
           item->x == x &&
           item->y == y &&
-          item->z == z)
+          item->z == z &&
+          item->handler == cache)
         {
           gegl_tile_void (tile);
           g_object_unref (tile);
           g_slice_free (CacheItem, item);
-          g_queue_delete_link (cache->queue, link);
+          g_queue_delete_link (cache_queue, link);
           return;
         }
     }
@@ -395,18 +347,19 @@
   CacheItem *item = g_slice_new (CacheItem);
   guint      count;
 
-  item->tile = g_object_ref (tile);
-  item->x    = x;
-  item->y    = y;
-  item->z    = z;
+  item->handler = cache;
+  item->tile    = g_object_ref (tile);
+  item->x       = x;
+  item->y       = y;
+  item->z       = z;
 
-  g_queue_push_head (cache->queue, item);
+  g_queue_push_head (cache_queue, item);
 
-  count = g_queue_get_length (cache->queue);
+  count = g_queue_get_length (cache_queue);
 
-  if (count > cache->size)
+  if (count > cache_size)
     {
-      gint to_remove = count - cache->size;
+      gint to_remove = count - cache_size;
 
       while (--to_remove && gegl_handler_cache_trim (cache)) ;
     }

Modified: trunk/gegl/buffer/gegl-handler-cache.h
==============================================================================
--- trunk/gegl/buffer/gegl-handler-cache.h	(original)
+++ trunk/gegl/buffer/gegl-handler-cache.h	Wed Apr 16 21:24:57 2008
@@ -36,11 +36,11 @@
 {
   GeglHandler parent_instance;
 
-  GQueue     *queue;
+/*  GQueue     *queue;
   gint        size;
   gint        wash_percentage;
   gint        hits;
-  gint        misses;
+  gint        misses;*/
 };
 
 struct _GeglHandlerCacheClass

Modified: trunk/gegl/buffer/gegl-handler-empty.c
==============================================================================
--- trunk/gegl/buffer/gegl-handler-empty.c	(original)
+++ trunk/gegl/buffer/gegl-handler-empty.c	Wed Apr 16 21:24:57 2008
@@ -21,6 +21,7 @@
 
 #include "gegl-handler.h"
 #include "gegl-handler-empty.h"
+#include "gegl-handler-cache.h"
 
 G_DEFINE_TYPE (GeglHandlerEmpty, gegl_handler_empty, GEGL_TYPE_HANDLER)
 
@@ -41,6 +42,12 @@
   G_OBJECT_CLASS (gegl_handler_empty_parent_class)->finalize (object);
 }
 
+void gegl_handler_cache_insert (GeglHandlerCache *cache,
+                                GeglTile         *tile,
+                                gint              x,
+                                gint              y,
+                                gint              z);
+
 static GeglTile *
 get_tile (GeglSource *gegl_source,
           gint        x,
@@ -57,6 +64,14 @@
     return tile;
 
   tile = gegl_tile_dup (empty->tile);
+  tile->x = x;
+  tile->y = y;
+  tile->z = z;
+  {
+    GeglHandlerCache *cache = g_object_get_data (G_OBJECT (gegl_source), "cache");
+    if (cache)
+      gegl_handler_cache_insert (cache, tile, x, y, z);
+  }
 
   return tile;
 }

Modified: trunk/gegl/buffer/gegl-handler-zoom.c
==============================================================================
--- trunk/gegl/buffer/gegl-handler-zoom.c	(original)
+++ trunk/gegl/buffer/gegl-handler-zoom.c	Wed Apr 16 21:24:57 2008
@@ -21,6 +21,8 @@
 
 #include "gegl-handler.h"
 #include "gegl-handler-zoom.h"
+#include "gegl-handler-cache.h"
+
 
 G_DEFINE_TYPE (GeglHandlerZoom, gegl_handler_zoom, GEGL_TYPE_HANDLER)
 
@@ -34,6 +36,11 @@
 #include <babl/babl.h>
 #include "gegl-tile-backend.h"
 
+void gegl_handler_cache_insert (GeglHandlerCache *cache,
+                                GeglTile         *tile,
+                                gint              x,
+                                gint              y,
+                                gint              z);
 static inline void set_blank (GeglTile *dst_tile,
                               gint      width,
                               gint      height,
@@ -296,8 +303,16 @@
         tile->y          = y;
         tile->z          = z;
         tile->storage    = zoom->storage;
-        tile->stored_rev = 0;
+        tile->stored_rev = 1;
         tile->rev        = 1;
+
+        {
+          GeglHandlerCache *cache = g_object_get_data (G_OBJECT (gegl_source), "cache");
+          if (cache)
+            {
+              gegl_handler_cache_insert (cache, tile, x, y, z);
+            }
+        }
       }
     gegl_tile_lock (tile);
     data = gegl_tile_get_data (tile);

Modified: trunk/gegl/buffer/gegl-storage.c
==============================================================================
--- trunk/gegl/buffer/gegl-storage.c	(original)
+++ trunk/gegl/buffer/gegl-storage.c	Wed Apr 16 21:24:57 2008
@@ -175,6 +175,8 @@
   GeglStorage    *storage;
   GeglHandlers   *handlers;
   GeglHandler    *handler;
+  GeglHandler    *empty = NULL;
+  GeglHandler    *zoom = NULL;
   GeglHandler    *cache = NULL;
 
   object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
@@ -221,46 +223,31 @@
                 "px-size",   &storage->px_size,
                 NULL);
 
+  g_object_unref (handler->source); /* eeek */
+
   if (g_getenv("GEGL_LOG_TILE_BACKEND"))
     gegl_handlers_add (handlers, g_object_new (GEGL_TYPE_HANDLER_LOG, NULL));
 
 
-  /* FIXME: the cache should be made shared between all GeglStorages,
-   * to get a better gauge of memory use (ideally we would want to make
-   * to adapt to an approximate number of bytes to be allocated)
-   */
-
-  if (1) 
-    cache = gegl_handlers_add (handlers, g_object_new (GEGL_TYPE_HANDLER_CACHE,
-                                                       "size", 128,
-                                                       NULL));
-  if (g_getenv("GEGL_LOG_TILE_CACHE"))
-    gegl_handlers_add (handlers, g_object_new (GEGL_TYPE_HANDLER_LOG, NULL));
-
-  if (1) gegl_handlers_add (handlers, g_object_new (GEGL_TYPE_HANDLER_ZOOM,
-                                                  "backend", handler->source,
-                                                  "storage", storage,
-                                                  NULL));
-  if (g_getenv("GEGL_LOG_TILE_ZOOM"))
-    gegl_handlers_add (handlers, g_object_new (GEGL_TYPE_HANDLER_LOG, NULL));
+  cache = gegl_handlers_add (handlers, g_object_new (GEGL_TYPE_HANDLER_CACHE,
+                                                     NULL));
 
+  zoom = gegl_handlers_add (handlers, g_object_new (GEGL_TYPE_HANDLER_ZOOM,
+                                                    "backend", handler->source,
+                                                    "storage", storage,
+                                                    NULL));
+  empty = gegl_handlers_add (handlers, g_object_new (GEGL_TYPE_HANDLER_EMPTY,
+                                                     "backend", handler->source,
+                                                     NULL));
 
-  /* moved here to allow sharing between buffers (speeds up, but only
-   * allows nulled (transparent) blank tiles, or we would need a separate
-   * gegl-storage for each tile.
-   */
-  if (1) gegl_handlers_add (handlers, g_object_new (GEGL_TYPE_HANDLER_EMPTY,
-                                                  "backend", handler->source,
-                                                   NULL));
-  if (g_getenv("GEGL_LOG_TILE_EMPTY"))
+  if (g_getenv("GEGL_LOG_TILE_CACHE"))
     gegl_handlers_add (handlers, g_object_new (GEGL_TYPE_HANDLER_LOG, NULL));
+  g_object_set_data (G_OBJECT (empty), "cache", cache);
+  g_object_set_data (G_OBJECT (zoom), "cache", cache);
 
-  /* it doesn't really matter that empty tiles are not cached, since they
-   * are Copy on Write.
-   */
 
   storage->idle_swapper = g_timeout_add_full (G_PRIORITY_LOW,
-                                              500,
+                                              250,
                                               storage_idle,
                                               storage,
                                               NULL);

Modified: trunk/gegl/buffer/gegl-tile.c
==============================================================================
--- trunk/gegl/buffer/gegl-tile.c	(original)
+++ trunk/gegl/buffer/gegl-tile.c	Wed Apr 16 21:24:57 2008
@@ -344,6 +344,7 @@
 gegl_tile_void (GeglTile *tile)
 {
   tile->stored_rev = tile->rev;
+  tile->storage = NULL;
   /* FIXME: make sure the tile is evicted from any storage/buffer caches
    * as well
    */

Modified: trunk/gegl/gegl-init.c
==============================================================================
--- trunk/gegl/gegl-init.c	(original)
+++ trunk/gegl/gegl-init.c	Wed Apr 16 21:24:57 2008
@@ -39,8 +39,6 @@
 #include "module/geglmodule.h"
 #include "module/geglmoduledb.h"
 
-#include "buffer/gegl-buffer-allocator.h"
-
 #include "operation/gegl-operation.h"
 #include "operation/gegl-operations.h"
 #include "operation/gegl-extension-handler.h"
@@ -141,9 +139,9 @@
 {
   glong timing = gegl_ticks ();
 
+  gegl_tile_cache_destroy ();
   gegl_operation_gtype_cleanup ();
   gegl_extension_handler_cleanup ();
-  gegl_buffer_allocators_free ();
 
   if (module_db != NULL)
     {
@@ -172,6 +170,7 @@
 
   if (gegl_buffer_leaks ())
     g_print ("  buffer-leaks: %i", gegl_buffer_leaks ());
+  gegl_tile_cache_destroy ();
 
   if (gegl_swap_dir())
     {



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