[gegl] buffer: add gegl_buffer_foreach_tile(); use in gegl_buffer_clear()



commit a9a09b95d126c6c5ae69e7718887854a994df304
Author: Ell <ell_se yahoo com>
Date:   Thu Nov 29 10:08:18 2018 -0500

    buffer: add gegl_buffer_foreach_tile(); use in gegl_buffer_clear()
    
    Factor the logic for iterating over whole-tiles contained in a
    given rect, and over the remaining "edge" rects, out of
    gegl_buffer_clear(), and into a new gegl_buffer_foreach_tile()
    internal function, which takes a pair of functions: one which
    performs the per-tile action, and one which performs the per-rect
    action, and calls them for each tile/edge-rect in the given region.
    
    Modify gegl_buffer_clear() to use the new function.
    
    Additionally, when voiding the tiles, call
    gegl_tile_handler_cache_remove() directly, to avoid voiding the
    tile pyramid at each base tile.  Instead, have
    gegl_buffer_foreach_tile() void the entire region in a single step.

 gegl/buffer/gegl-buffer-access.c      | 215 +++++++++++++++++++++-------------
 gegl/buffer/gegl-tile-handler-cache.c |   2 +-
 gegl/buffer/gegl-tile-handler-cache.h |   4 +
 3 files changed, 136 insertions(+), 85 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index 8a8b7865e..2637478b2 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -2579,144 +2579,191 @@ gegl_buffer_copy (GeglBuffer          *src,
   gegl_buffer_emit_changed_signal (dst, dst_rect);
 }
 
-static void
-gegl_buffer_clear2 (GeglBuffer          *dst,
-                    const GeglRectangle *dst_rect)
-{
-  GeglBufferIterator *i;
-  gint                pxsize;
-
-  pxsize = babl_format_get_bytes_per_pixel (dst->soft_format);
-
-  if (gegl_buffer_ext_invalidate)
-    {
-      gegl_buffer_ext_invalidate (dst, dst_rect);
-    }
-
-  i = gegl_buffer_iterator_new (dst, dst_rect, 0, dst->soft_format,
-                                GEGL_ACCESS_WRITE | GEGL_ITERATOR_NO_NOTIFY,
-                                GEGL_ABYSS_NONE, 1);
-  while (gegl_buffer_iterator_next (i))
-    {
-      memset (((guchar*)(i->items[0].data)), 0, i->length * pxsize);
-    }
-}
+typedef void (* GeglBufferTileFunc) (GeglBuffer          *buffer,
+                                     gint                 tile_x,
+                                     gint                 tile_y,
+                                     gpointer             data);
+typedef void (* GeglBufferRectFunc) (GeglBuffer          *buffer,
+                                     const GeglRectangle *rect,
+                                     gpointer             data);
 
-void
-gegl_buffer_clear (GeglBuffer          *dst,
-                   const GeglRectangle *dst_rect)
+static void
+gegl_buffer_foreach_tile (GeglBuffer          *buffer,
+                          const GeglRectangle *rect,
+                          GeglBufferTileFunc   tile_func,
+                          GeglBufferRectFunc   rect_func,
+                          gpointer             data)
 {
-  g_return_if_fail (GEGL_IS_BUFFER (dst));
+  if (! rect)
+    rect = gegl_buffer_get_extent (buffer);
 
-  if (!dst_rect)
-    {
-      dst_rect = gegl_buffer_get_extent (dst);
-    }
-  if (dst_rect->width <= 0 ||
-      dst_rect->height <= 0)
+  if (rect->width <= 0 || rect->height <= 0)
     return;
 
 #if 1
   /* cow for clearing is currently broken */
-  if (dst_rect->width >= dst->tile_width &&
-      dst_rect->height >= dst->tile_height &&
-      !g_object_get_data (G_OBJECT (dst), "is-linear"))
+  if (rect->width  >= buffer->tile_width  &&
+      rect->height >= buffer->tile_height &&
+      ! g_object_get_data (G_OBJECT (buffer), "is-linear"))
     {
-      gint tile_width  = dst->tile_width;
-      gint tile_height = dst->tile_height;
+      gint tile_width  = buffer->tile_width;
+      gint tile_height = buffer->tile_height;
 
-      GeglRectangle cow_rect = *dst_rect;
+      GeglRectangle tile_rect = *rect;
       gint          rem;
 
+      /* shift rect to tile coordinate system */
+      tile_rect.x += buffer->shift_x;
+      tile_rect.y += buffer->shift_y;
+
       /* adjust origin to match the start of tile alignment */
-      rem = (cow_rect.x + dst->shift_x) % tile_width;
+      rem = tile_rect.x % tile_width;
       if (rem > 0)
         rem -= tile_width;
-      cow_rect.x      -= rem;
-      cow_rect.width  += rem;
+      tile_rect.x      -= rem;
+      tile_rect.width  += rem;
 
-      rem = (cow_rect.y + dst->shift_y) % tile_height;
+      rem = tile_rect.y % tile_height;
       if (rem > 0)
         rem -= tile_height;
-      cow_rect.y      -= rem;
-      cow_rect.height += rem;
+      tile_rect.y      -= rem;
+      tile_rect.height += rem;
 
       /* adjust size of rect to match multiple of tiles */
-      cow_rect.width  -= cow_rect.width  % tile_width;
-      cow_rect.height -= cow_rect.height % tile_height;
+      tile_rect.width  -= tile_rect.width  % tile_width;
+      tile_rect.height -= tile_rect.height % tile_height;
 
-      if (cow_rect.width > 0 && cow_rect.height > 0)
+      if (tile_rect.width > 0 && tile_rect.height > 0)
         {
           GeglRectangle top, bottom, left, right;
 
-          /* iterate over rectangle that can be cow copied, duplicating
-           * one and one tile
-           */
+          /* iterate over the tile rectangle */
           {
-            /* first we do a dumb copy,. but with fetched tiles */
-
-            gint dst_x, dst_y;
+            gint x, y;
 
-            g_rec_mutex_lock (&dst->tile_storage->mutex);
+            g_rec_mutex_lock (&buffer->tile_storage->mutex);
 
-            for (dst_y = cow_rect.y + dst->shift_y; dst_y < cow_rect.y + dst->shift_y + cow_rect.height; 
dst_y += tile_height)
-            for (dst_x = cow_rect.x + dst->shift_x; dst_x < cow_rect.x + dst->shift_x + cow_rect.width; 
dst_x += tile_width)
+            for (y = tile_rect.y;
+                 y < tile_rect.y + tile_rect.height;
+                 y += tile_height)
               {
-                gint dtx, dty;
+                for (x = tile_rect.x;
+                     x < tile_rect.x + tile_rect.width;
+                     x += tile_width)
+                  {
+                    gint tile_x, tile_y;
 
-                dtx = gegl_tile_indice (dst_x, tile_width);
-                dty = gegl_tile_indice (dst_y, tile_height);
+                    tile_x = gegl_tile_indice (x, tile_width);
+                    tile_y = gegl_tile_indice (y, tile_height);
 
-                gegl_tile_source_void ((GeglTileSource*)dst, dtx, dty, 0);
+                    tile_func (buffer, tile_x, tile_y, data);
+                  }
               }
 
-            g_rec_mutex_unlock (&dst->tile_storage->mutex);
+            gegl_tile_handler_damage_rect (
+              GEGL_TILE_HANDLER (buffer->tile_storage),
+              &tile_rect);
+
+            g_rec_mutex_unlock (&buffer->tile_storage->mutex);
           }
 
-          top = *dst_rect;
-          top.height = (cow_rect.y - dst_rect->y);
+          /* shift rect to buffer coordinate system */
+          tile_rect.x -= buffer->shift_x;
+          tile_rect.y -= buffer->shift_y;
 
+          top = *rect;
+          top.height = (tile_rect.y - rect->y);
 
-          left = *dst_rect;
-          left.y = cow_rect.y;
-          left.height = cow_rect.height;
-          left.width = (cow_rect.x - dst_rect->x);
 
-          bottom = *dst_rect;
-          bottom.y = (cow_rect.y + cow_rect.height);
-          bottom.height = (dst_rect->y + dst_rect->height) -
-                          (cow_rect.y  + cow_rect.height);
+          left = *rect;
+          left.y = tile_rect.y;
+          left.height = tile_rect.height;
+          left.width = (tile_rect.x - rect->x);
+
+          bottom = *rect;
+          bottom.y = (tile_rect.y + tile_rect.height);
+          bottom.height = (rect->y + rect->height) -
+                          (tile_rect.y  + tile_rect.height);
 
           if (bottom.height < 0)
             bottom.height = 0;
 
-          right  =  *dst_rect;
-          right.x = (cow_rect.x + cow_rect.width);
-          right.width = (dst_rect->x + dst_rect->width) -
-                          (cow_rect.x  + cow_rect.width);
-          right.y = cow_rect.y;
-          right.height = cow_rect.height;
+          right  =  *rect;
+          right.x = (tile_rect.x + tile_rect.width);
+          right.width = (rect->x + rect->width) -
+                          (tile_rect.x  + tile_rect.width);
+          right.y = tile_rect.y;
+          right.height = tile_rect.height;
 
           if (right.width < 0)
             right.width = 0;
 
-          if (top.height)                  gegl_buffer_clear2 (dst, &top);
-          if (bottom.height)               gegl_buffer_clear2 (dst, &bottom);
-          if (left.width && left.height)   gegl_buffer_clear2 (dst, &left);
-          if (right.width && right.height) gegl_buffer_clear2 (dst, &right);
+          if (top.height)                  rect_func (buffer, &top,    data);
+          if (bottom.height)               rect_func (buffer, &bottom, data);
+          if (left.width && left.height)   rect_func (buffer, &left,   data);
+          if (right.width && right.height) rect_func (buffer, &right,  data);
         }
       else
         {
-          gegl_buffer_clear2 (dst, dst_rect);
+          rect_func (buffer, rect, data);
         }
     }
   else
 #endif
     {
-      gegl_buffer_clear2 (dst, dst_rect);
+      rect_func (buffer, rect, data);
     }
 
-  gegl_buffer_emit_changed_signal (dst, dst_rect);
+  gegl_buffer_emit_changed_signal (buffer, rect);
+}
+
+static void
+gegl_buffer_clear_tile (GeglBuffer *dst,
+                        gint        tile_x,
+                        gint        tile_y,
+                        gpointer    data)
+{
+  gegl_tile_handler_cache_remove (dst->tile_storage->cache,
+                                  tile_x, tile_y, 0);
+
+  gegl_tile_handler_source_command (dst->tile_storage->cache, GEGL_TILE_VOID,
+                                    tile_x, tile_y, 0, NULL);
+}
+
+static void
+gegl_buffer_clear_rect (GeglBuffer          *dst,
+                        const GeglRectangle *dst_rect,
+                        gpointer             data)
+{
+  GeglBufferIterator *i;
+  gint                pxsize;
+
+  pxsize = babl_format_get_bytes_per_pixel (dst->soft_format);
+
+  if (gegl_buffer_ext_invalidate)
+    {
+      gegl_buffer_ext_invalidate (dst, dst_rect);
+    }
+
+  i = gegl_buffer_iterator_new (dst, dst_rect, 0, dst->soft_format,
+                                GEGL_ACCESS_WRITE | GEGL_ITERATOR_NO_NOTIFY,
+                                GEGL_ABYSS_NONE, 1);
+  while (gegl_buffer_iterator_next (i))
+    {
+      memset (((guchar*)(i->items[0].data)), 0, i->length * pxsize);
+    }
+}
+
+void
+gegl_buffer_clear (GeglBuffer          *dst,
+                   const GeglRectangle *dst_rect)
+{
+  g_return_if_fail (GEGL_IS_BUFFER (dst));
+
+  gegl_buffer_foreach_tile (dst, dst_rect,
+                            gegl_buffer_clear_tile,
+                            gegl_buffer_clear_rect,
+                            NULL);
 }
 
 void
diff --git a/gegl/buffer/gegl-tile-handler-cache.c b/gegl/buffer/gegl-tile-handler-cache.c
index 37e030c87..f25c222d7 100644
--- a/gegl/buffer/gegl-tile-handler-cache.c
+++ b/gegl/buffer/gegl-tile-handler-cache.c
@@ -765,7 +765,7 @@ gegl_tile_handler_cache_remove_item (GeglTileHandlerCache *cache,
   g_slice_free (CacheItem, item);
 }
 
-static void
+void
 gegl_tile_handler_cache_remove (GeglTileHandlerCache *cache,
                                 gint                  x,
                                 gint                  y,
diff --git a/gegl/buffer/gegl-tile-handler-cache.h b/gegl/buffer/gegl-tile-handler-cache.h
index b027974d8..60ef7146a 100644
--- a/gegl/buffer/gegl-tile-handler-cache.h
+++ b/gegl/buffer/gegl-tile-handler-cache.h
@@ -64,6 +64,10 @@ void              gegl_tile_handler_cache_insert             (GeglTileHandlerCac
                                                               gint                  x,
                                                               gint                  y,
                                                               gint                  z);
+void              gegl_tile_handler_cache_remove             (GeglTileHandlerCache *cache,
+                                                              gint                  x,
+                                                              gint                  y,
+                                                              gint                  z);
 void              gegl_tile_handler_cache_tile_uncloned      (GeglTileHandlerCache *cache,
                                                               GeglTile             *tile);
 


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