[gimp/high-bit-depths-REBASED: 2/2] app: Support arbitrary tile sizes for GIMP GeglBuffer backend



commit 5dc047c455acb27543776989e41cc1a2d312617f
Author: Martin Nordholts <martinn src gnome org>
Date:   Tue Oct 11 07:45:58 2011 +0200

    app: Support arbitrary tile sizes for GIMP GeglBuffer backend
    
    Requires GEGL git master.

 app/gegl/gimptilebackendtilemanager.c       |   90 ++++++++++++++++--
 app/tests/test-gimptilebackendtilemanager.c |  141 ++++++++++++++++++++++++---
 2 files changed, 210 insertions(+), 21 deletions(-)
---
diff --git a/app/gegl/gimptilebackendtilemanager.c b/app/gegl/gimptilebackendtilemanager.c
index b457c4d..e24e388 100644
--- a/app/gegl/gimptilebackendtilemanager.c
+++ b/app/gegl/gimptilebackendtilemanager.c
@@ -71,6 +71,12 @@ static gpointer gimp_tile_backend_tile_manager_command      (GeglTileSource  *ti
                                                              gint             z,
                                                              gpointer         data);
 
+static void       tile_unlock_notify
+                                    (GeglTile                   *tile,
+                                     gpointer                    unlock_notify_data);
+static void       tile_destroy_notify
+                                    (gpointer                    pixel_data,
+                                     gpointer                    user_data);
 static void       dbg_alloc         (int                         size);
 static void       dbg_dealloc       (int                         size);
 static RamEntry * lookup_entry      (GimpTileBackendTileManager *self,
@@ -183,16 +189,50 @@ gimp_tile_backend_tile_manager_command (GeglTileSource  *tile_store,
 
         g_return_val_if_fail (gimp_tile != NULL, NULL);
 
-        if (tile_ewidth (gimp_tile)  != TILE_WIDTH ||
-            tile_eheight (gimp_tile) != TILE_HEIGHT)
+        tile = gegl_tile_new_bare ();
+        if (tile_ewidth (gimp_tile)  == TILE_WIDTH &&
+            tile_eheight (gimp_tile) == TILE_HEIGHT)
           {
-            g_warning ("GimpTileBackendTileManager does not support != %dx%d tiles yet",
-                       TILE_WIDTH, TILE_HEIGHT);
+            /* We can use the GIMP tile data directly */
+            gegl_tile_set_data (tile,
+                                tile_data_pointer (gimp_tile, 0, 0),
+                                tile_size (gimp_tile));
+          }
+        else
+          {
+            guchar *tile_data;
+            gint    size;
+            int     y;
+
+            /* GEGL expects full tile data, so allocate tile data of
+             * the size GEGL expects.
+             */
+            size = TILE_WIDTH * TILE_HEIGHT * tile_bpp (gimp_tile);
+            tile_data = g_new(guchar, size);
+
+            /* Copy over the GIMP Tile data to the GeglTile data */
+            for (y = 0; y < tile_eheight (gimp_tile); y++)
+              {
+                memcpy (tile_data + y * TILE_WIDTH * tile_bpp (gimp_tile),
+                        tile_data_pointer (gimp_tile, 0, y),
+                        tile_ewidth (gimp_tile) * tile_bpp (gimp_tile));
+              }
+
+            /* Whenever the GeglTile data changes, copy it over to the
+             * GIMP Tile
+             *
+             * TODO: Whenever the GIMP Tile data changes, copy it over
+             * to the GeglTile again
+             */
+            gegl_tile_set_unlock_notify (tile,
+                                         tile_unlock_notify,
+                                         gimp_tile);
+            gegl_tile_set_data_full (tile,
+                                     tile_data,
+                                     size,
+                                     tile_destroy_notify,
+                                     NULL);
           }
-        tile = gegl_tile_new_bare ();
-        gegl_tile_set_data (tile,
-                            tile_data_pointer (gimp_tile, 0, 0),
-                            tile_size (gimp_tile));
 
         return tile;
       }
@@ -252,6 +292,40 @@ static gint peak_allocs            = 0;
 static gint peak_tile_manager_size = 0;
 
 static void
+tile_unlock_notify (GeglTile *tile,
+                    gpointer  unlock_notify_data)
+{
+  Tile     *gimp_tile      = (Tile *) unlock_notify_data;
+  guchar   *gegl_tile_data = gegl_tile_get_data (tile);
+  int       y;
+
+  if (tile_ewidth (gimp_tile) == TILE_WIDTH)
+    {
+      memcpy (tile_data_pointer (gimp_tile, 0, 0),
+              gegl_tile_data,
+              (TILE_WIDTH *
+               tile_eheight (gimp_tile) *
+               tile_bpp (gimp_tile)));
+    }
+  else
+    {
+      for (y = 0; y < tile_eheight (gimp_tile); y++)
+        {
+          memcpy (tile_data_pointer (gimp_tile, 0, y),
+                  gegl_tile_data + y * TILE_WIDTH * tile_bpp (gimp_tile),
+                  tile_ewidth (gimp_tile) * tile_bpp (gimp_tile));
+        }
+    }
+}
+
+static void
+tile_destroy_notify (gpointer pixel_data,
+                     gpointer user_data)
+{
+  g_free (pixel_data);
+}
+
+static void
 dbg_alloc (gint size)
 {
   allocs++;
diff --git a/app/tests/test-gimptilebackendtilemanager.c b/app/tests/test-gimptilebackendtilemanager.c
index bd23b30..4fa3e35 100644
--- a/app/tests/test-gimptilebackendtilemanager.c
+++ b/app/tests/test-gimptilebackendtilemanager.c
@@ -24,9 +24,10 @@
 
 #include "widgets/widgets-types.h"
 
-#include "base/tile-manager.h"
 #include "base/pixel-region.h"
 #include "base/tile-cache.h"
+#include "base/tile-manager.h"
+#include "base/tile.h"
 
 #include "gegl/gimptilebackendtilemanager.h"
 
@@ -40,33 +41,34 @@
   g_test_add_func ("/gimptilebackendtilemanager/" #function, function);
 
 
+static void basic_read  (GeglRectangle rect);
+static void basic_write (GeglRectangle rect);
+
+
 static const guchar  opaque_magenta8[4]    = { 0xff,   0x00,   0xff,   0xff   };
 static const guchar  transparent_black8[4] = { 0x00,   0x00,   0x00,   0x00   };
 
 static const guint16 opaque_magenta16[4]   = { 0xffff, 0x0000, 0xffff, 0xffff };
 
-/* FIXME: Add tests for non-tile sized rects, they currently won't
- * pass
- */
-static const GeglRectangle rect            = { 0, 0, 64, 64 };
-static const GeglRectangle center_pixel    = { 5, 5, 1,  1  };
-
 
 /**
  * basic_read:
- * @data:
+ * @rect: The rect to use. Vary this to vary number of tiles and their
+ *        effective sizes used for the test.
  *
  * Test that the backend can be used for basic reading of TileManager
  * data.
  **/
 static void
-basic_read (void)
+basic_read (GeglRectangle rect)
 {
   PixelRegion      pr;
   TileManager     *tm;
   GeglTileBackend *backend;
   GeglBuffer      *buffer;
   guint16          actual_data[4];
+  GeglRectangle    center_pixel = { rect.width / 2, rect.height / 2, 1,  1  };
+
 
   /* Write some pixels to the tile manager */
   tm = tile_manager_new (rect.width, rect.height, 4);
@@ -89,13 +91,14 @@ basic_read (void)
 
 /**
  * basic_write:
- * @data:
+ * @rect: The rect to use. Vary this to vary number of tiles and their
+ *        effective sizes used for the test.
  *
  * Test that the backend can be used for basic writing of TileManager
  * data.
  **/
 static void
-basic_write (void)
+basic_write (GeglRectangle rect)
 {
   PixelRegion      pr;
   TileManager     *tm;
@@ -103,6 +106,7 @@ basic_write (void)
   GeglBuffer      *buffer;
   guchar           actual_data[4];
   gint             x, y;
+  GeglRectangle    center_pixel = { rect.width / 2, rect.height / 2, 1,  1  };
 
   /* Clear the TileManager */
   tm = tile_manager_new (rect.width, rect.height, 4);
@@ -132,6 +136,105 @@ basic_write (void)
                                   sizeof (actual_data)));
 }
 
+static void
+basic_read_1x1 (void)
+{
+  GeglRectangle rect = { 0, 0, 1, 1 };
+  basic_read (rect);
+}
+
+static void
+basic_write_1x1 (void)
+{
+  GeglRectangle rect = { 0, 0, 1, 1 };
+  basic_write (rect);
+}
+
+static void
+basic_read_10x10 (void)
+{
+  GeglRectangle rect = { 0, 0, 10, 10 };
+  basic_read (rect);
+}
+
+static void
+basic_write_10x10 (void)
+{
+  GeglRectangle rect = { 0, 0, 10, 10 };
+  basic_write (rect);
+
+}
+
+static void
+basic_read_TILE_WIDTHxTILE_HEIGHT (void)
+{
+  GeglRectangle rect = { 0, 0, TILE_WIDTH, TILE_HEIGHT };
+  basic_read (rect);
+}
+
+static void
+basic_write_TILE_WIDTHxTILE_HEIGHT (void)
+{
+  GeglRectangle rect = { 0, 0, TILE_WIDTH, TILE_HEIGHT };
+  basic_write (rect);
+}
+
+static void
+basic_read_3TILE_WIDTHx3TILE_HEIGHT (void)
+{
+  GeglRectangle rect = { 0, 0, 3 * TILE_WIDTH, 3 * TILE_HEIGHT };
+  basic_read (rect);
+}
+
+static void
+basic_write_3TILE_WIDTHx3TILE_HEIGHT (void)
+{
+  GeglRectangle rect = { 0, 0, 3 * TILE_WIDTH, 3 * TILE_HEIGHT };
+  basic_write (rect);
+}
+
+static void
+basic_read_2TILE_WIDTHx10 (void)
+{
+  GeglRectangle rect = { 0, 0, 2 * TILE_WIDTH, 10 };
+  basic_read (rect);
+}
+
+static void
+basic_write_2TILE_WIDTHx10 (void)
+{
+  GeglRectangle rect = { 0, 0, 2 * TILE_WIDTH, 10 };
+  basic_write (rect);
+}
+
+static void
+basic_read_10x2TILE_WIDTH (void)
+{
+  GeglRectangle rect = { 0, 0, 10, 2 * TILE_HEIGHT };
+  basic_read (rect);
+}
+
+static void
+basic_write_10x2TILE_WIDTH (void)
+{
+  GeglRectangle rect = { 0, 0, 10, 2 * TILE_HEIGHT };
+  basic_write (rect);
+}
+
+static void
+basic_read_100x100 (void)
+{
+  GeglRectangle rect = { 0, 0, 100, 100 };
+  basic_read (rect);
+}
+
+static void
+basic_write_100x100 (void)
+{
+  GeglRectangle rect = { 0, 0, 100, 100 };
+  basic_write (rect);
+}
+
 int
 main (int    argc,
       char **argv)
@@ -141,8 +244,20 @@ main (int    argc,
   gegl_init (&argc, &argv);
   g_test_init (&argc, &argv, NULL);
 
-  ADD_TEST (basic_read);
-  ADD_TEST (basic_write);
+  ADD_TEST (basic_read_1x1);
+  ADD_TEST (basic_write_1x1);
+  ADD_TEST (basic_read_10x10);
+  ADD_TEST (basic_write_10x10);
+  ADD_TEST (basic_read_TILE_WIDTHxTILE_HEIGHT);
+  ADD_TEST (basic_write_TILE_WIDTHxTILE_HEIGHT);
+  ADD_TEST (basic_read_3TILE_WIDTHx3TILE_HEIGHT);
+  ADD_TEST (basic_write_3TILE_WIDTHx3TILE_HEIGHT);
+  ADD_TEST (basic_read_2TILE_WIDTHx10);
+  ADD_TEST (basic_write_2TILE_WIDTHx10);
+  ADD_TEST (basic_read_10x2TILE_WIDTH);
+  ADD_TEST (basic_write_10x2TILE_WIDTH);
+  ADD_TEST (basic_read_100x100);
+  ADD_TEST (basic_write_100x100);
 
   return g_test_run ();
 }



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