[gegl] buffer: implement bilinear dispatch along nearest



commit 2bb890d4a220808b9678762d710bef05df68e6f7
Author: Øyvind Kolås <pippin gimp org>
Date:   Sat Jan 27 01:36:54 2018 +0100

    buffer: implement bilinear dispatch along nearest
    
    The default remains boxfilter dispatch which is our highest quality, for the
    time being, bilienar dispatch for 8bit nonlinear runs at only 17% of the
    performance of the much higher quality boxfilter due to lack of fast paths.
    With fast paths it might be a tolerable loss of quality at some speed gain.

 gegl/buffer/gegl-buffer-access.c |   80 +++++++++++++++++++++++++------------
 gegl/gegl-enums.h                |    3 +-
 gegl/graph/gegl-node.c           |    8 ++--
 3 files changed, 60 insertions(+), 31 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index 4ef98a2..7400213 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -1892,6 +1892,7 @@ _gegl_buffer_get_unlocked (GeglBuffer          *buffer,
                            GeglAbyssPolicy      repeat_mode)
 {
   gboolean do_nearest = (repeat_mode & GEGL_BUFFER_NEAREST) != 0;
+  gboolean do_bilinear = (repeat_mode & GEGL_BUFFER_BILINEAR) != 0;
   repeat_mode &= 0x7;
 
   if (gegl_cl_is_accelerated ())
@@ -2008,33 +2009,60 @@ _gegl_buffer_get_unlocked (GeglBuffer          *buffer,
 
       if (!do_nearest && scale <= 1.99)
         {
-          buf_width  += 2;
-          buf_height += 2;
-          offset = (buf_width + 1) * bpp;
-          sample_buf = g_malloc0 (buf_height * buf_width * bpp);
-          /* NOTE: this iterate read dispatch could perhaps with advantage
-             be done in the buffers format - or in a well suited for
-             scaling format - rather than the target format?, right now
-             requesting 8bit from floating point causes more conversions
-             than desired */
-          gegl_buffer_iterate_read_dispatch (buffer, &sample_rect,
+          if (do_bilinear)
+            {
+              buf_width  += 1;
+              buf_height += 1;
+              sample_rect.width  += factor;
+              sample_rect.height += factor;
+
+              sample_buf = g_malloc (buf_height * buf_width * bpp);
+              gegl_buffer_iterate_read_dispatch (buffer, &sample_rect,
+                                         (guchar*)sample_buf,
+                                          buf_width * bpp,
+                                          format, level, repeat_mode);
+
+              sample_rect.x      = x1;
+              sample_rect.y      = y1;
+              sample_rect.width  = x2 - x1 + 1;
+              sample_rect.height = y2 - y1 + 1;
+
+              gegl_resample_bilinear (dest_buf,
+                                      sample_buf,
+                                      rect,
+                                      &sample_rect,
+                                      buf_width * bpp,
+                                      scale,
+                                      format,
+                                      rowstride);
+            }
+          else /* boxfilter */
+            {
+              buf_width  += 2;
+              buf_height += 2;
+              offset = (buf_width + 1) * bpp;
+
+              sample_buf = g_malloc (buf_height * buf_width * bpp);
+              gegl_buffer_iterate_read_dispatch (buffer, &sample_rect,
                                          (guchar*)sample_buf + offset,
-                                         buf_width * bpp,
-                                         format, level, repeat_mode);
+                                          buf_width * bpp,
+                                          format, level, repeat_mode);
+
+              sample_rect.x      = x1 - 1;
+              sample_rect.y      = y1 - 1;
+              sample_rect.width  = x2 - x1 + 2;
+              sample_rect.height = y2 - y1 + 2;
+
+              gegl_resample_boxfilter (dest_buf,
+                                       sample_buf,
+                                       rect,
+                                       &sample_rect,
+                                       buf_width * bpp,
+                                       scale,
+                                       format,
+                                       rowstride);
+            }
 
-          sample_rect.x      = x1 - 1;
-          sample_rect.y      = y1 - 1;
-          sample_rect.width  = x2 - x1 + 2;
-          sample_rect.height = y2 - y1 + 2;
-
-          gegl_resample_boxfilter (dest_buf,
-                                   sample_buf,
-                                   rect,
-                                   &sample_rect,
-                                   buf_width * bpp,
-                                   scale,
-                                   format,
-                                   rowstride);
           g_free (sample_buf);
         }
       else if (buf_height && buf_width)
diff --git a/gegl/gegl-enums.h b/gegl/gegl-enums.h
index d333627..9fcee42 100644
--- a/gegl/gegl-enums.h
+++ b/gegl/gegl-enums.h
@@ -42,7 +42,8 @@ typedef enum {
   GEGL_ABYSS_LOOP  = 2,
   GEGL_ABYSS_BLACK = 3,
   GEGL_ABYSS_WHITE = 4,
-  GEGL_BUFFER_NEAREST = 32
+  GEGL_BUFFER_NEAREST = 32,
+  GEGL_BUFFER_BILINEAR = 64
 } GeglAbyssPolicy;
 
 GType gegl_abyss_policy_get_type (void) G_GNUC_CONST;
diff --git a/gegl/graph/gegl-node.c b/gegl/graph/gegl-node.c
index 0b6bb2b..20dab0f 100644
--- a/gegl/graph/gegl-node.c
+++ b/gegl/graph/gegl-node.c
@@ -1136,7 +1136,7 @@ gegl_node_blit (GeglNode            *self,
                 gint                 rowstride,
                 GeglBlitFlags        flags)
 {
-  gboolean do_nearest = (flags & GEGL_BUFFER_NEAREST) != 0;
+  gint interpolation = flags & (GEGL_BUFFER_NEAREST | GEGL_BUFFER_BILINEAR);
   flags &= 0xf;
 
   g_return_if_fail (GEGL_IS_NODE (self));
@@ -1145,7 +1145,7 @@ gegl_node_blit (GeglNode            *self,
   if (rowstride == GEGL_AUTO_ROWSTRIDE && format)
     rowstride = babl_format_get_bytes_per_pixel (format) * roi->width;
 
-  if (!flags)
+  if (flags == 0) // DEFAULT, just render, caching only if graph is explicitly caching itself
     {
       GeglBuffer *buffer;
 
@@ -1161,7 +1161,7 @@ gegl_node_blit (GeglNode            *self,
           buffer = gegl_node_apply_roi (self, roi, 0);
         }
       if (buffer && destination_buf)
-        gegl_buffer_get (buffer, roi, scale, format, destination_buf, rowstride, GEGL_ABYSS_NONE | 
(do_nearest?GEGL_BUFFER_NEAREST:0));
+        gegl_buffer_get (buffer, roi, scale, format, destination_buf, rowstride, GEGL_ABYSS_NONE | 
interpolation);
 
       g_clear_object (&buffer);
     }
@@ -1197,7 +1197,7 @@ gegl_node_blit (GeglNode            *self,
         {
           gegl_buffer_get (buffer, roi, scale,
                            format, destination_buf, rowstride,
-                           GEGL_ABYSS_NONE|(do_nearest?GEGL_BUFFER_NEAREST:0));
+                           GEGL_ABYSS_NONE|interpolation);
         }
     }
 }


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