[gegl] buffer: clear hot tile when removing a tile from the cache



commit cd98e944f5c30a8549f9cc22d5eb7f50a9dca334
Author: Ell <ell_se yahoo com>
Date:   Tue May 31 18:03:00 2016 +0000

    buffer: clear hot tile when removing a tile from the cache
    
    When removing a tile from the cache in gegl_tile_handler_cache_void()
    and gegl_tile_handler_cache_invalidate(), check if it's the
    associated tile storage's hot tile, and clear the hot tile if it is.
    
    Failing to do so keeps the hot tile pointing to an outdated tile,
    which can cause the 1x1 buffer access functions (_get_pixel(),
    _set_pixel(), NN sampling) to return wrong results.
    
    See the next commit for a test case.

 gegl/buffer/gegl-tile-handler-cache.c |   32 ++++++++++++++++++++++++--------
 1 files changed, 24 insertions(+), 8 deletions(-)
---
diff --git a/gegl/buffer/gegl-tile-handler-cache.c b/gegl/buffer/gegl-tile-handler-cache.c
index 12bb60d..d49f7d4 100644
--- a/gegl/buffer/gegl-tile-handler-cache.c
+++ b/gegl/buffer/gegl-tile-handler-cache.c
@@ -372,6 +372,27 @@ gegl_tile_handler_cache_has_tile (GeglTileHandlerCache *cache,
   return FALSE;
 }
 
+static void
+drop_hot_tile (GeglTile *tile)
+{
+  GeglTileStorage *storage = tile->tile_storage;
+
+  if (storage)
+    {
+      if (gegl_config_threads()>1)
+        g_rec_mutex_lock (&storage->mutex);
+
+      if (storage->hot_tile == tile)
+        {
+          gegl_tile_unref (storage->hot_tile);
+          storage->hot_tile = NULL;
+        }
+
+      if (gegl_config_threads()>1)
+        g_rec_mutex_unlock (&storage->mutex);
+    }
+}
+
 static gboolean
 gegl_tile_handler_cache_trim (GeglTileHandlerCache *cache)
 {
@@ -383,18 +404,11 @@ gegl_tile_handler_cache_trim (GeglTileHandlerCache *cache)
     {
       CacheItem *last_writable = LINK_GET_ITEM (link);
       GeglTile *tile = last_writable->tile;
-      GeglTileStorage *storage = tile->tile_storage;
 
       last_writable->handler->items = g_slist_remove (last_writable->handler->items, last_writable);
       g_hash_table_remove (cache_ht, last_writable);
       cache_total -= tile->size;
-
-      if (storage && storage->hot_tile == tile)
-        {
-          storage->hot_tile = NULL;
-          gegl_tile_unref (tile);
-        }
-
+      drop_hot_tile (tile);
       gegl_tile_unref (tile);
       g_slice_free (CacheItem, last_writable);
       return TRUE;
@@ -416,6 +430,7 @@ gegl_tile_handler_cache_invalidate (GeglTileHandlerCache *cache,
   if (item)
     {
       cache_total -= item->tile->size;
+      drop_hot_tile (item->tile);
       item->tile->tile_storage = NULL;
       gegl_tile_mark_as_stored (item->tile); /* to cheat it out of being stored */
       gegl_tile_unref (item->tile);
@@ -452,6 +467,7 @@ gegl_tile_handler_cache_void (GeglTileHandlerCache *cache,
 
   if (item)
     {
+      drop_hot_tile (item->tile);
       gegl_tile_void (item->tile);
       gegl_tile_unref (item->tile);
     }


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