[gimp] app: in gimppaintcore-loops, add [Temp]CompBuffer algorithm helper-classes



commit 858f30a609e40ceffd5129a5547f549aeda7d60d
Author: Ell <ell_se yahoo com>
Date:   Sat Feb 16 08:56:11 2019 -0500

    app: in gimppaintcore-loops, add [Temp]CompBuffer algorithm helper-classes
    
    In gimppaintcore-loops, add a CompBuffer algorithm helper-class,
    which provides access to the output buffer used for compositing,
    to be used by the DO_LAYER_BLEND algorithm instead of the
    destination buffer.
    
    CompVuffer itself doesn't provide the storage for the buffer; this
    is rather the responsibility of the algorithms that use it.  The
    TempCompBuffer algorithm helper-class provides temporary storage
    for the compositing buffer, and can be used by algorithms that need
    a temporary buffer.

 app/paint/gimppaintcore-loops.cc | 168 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 156 insertions(+), 12 deletions(-)
---
diff --git a/app/paint/gimppaintcore-loops.cc b/app/paint/gimppaintcore-loops.cc
index 9d7892a5e2..06a39fefd1 100644
--- a/app/paint/gimppaintcore-loops.cc
+++ b/app/paint/gimppaintcore-loops.cc
@@ -102,7 +102,9 @@ enum
   ALGORITHM_STIPPLE              = 1u << 29,
   ALGORITHM_COMP_MASK            = 1u << 28,
   ALGORITHM_TEMP_COMP_MASK       = 1u << 27,
-  ALGORITHM_MASK_BUFFER_ITERATOR = 1u << 26
+  ALGORITHM_COMP_BUFFER          = 1u << 26,
+  ALGORITHM_TEMP_COMP_BUFFER     = 1u << 25,
+  ALGORITHM_MASK_BUFFER_ITERATOR = 1u << 24
 };
 
 
@@ -813,6 +815,130 @@ static BasicDispatch<
dispatch_temp_comp_mask;
 
 
+/* CompBuffer, dispatch_comp_buffer(), has_comp_buffer(), comp_buffer_data():
+ *
+ * An algorithm helper class, providing access to the output buffer used for
+ * compositing.  When this class is part of the hierarchy, 'DoLayerBlend' uses
+ * this buffer as the output buffer, instead of the input parameters'
+ * 'dest_buffer'.  Algorithms that use the compositing buffer should specify
+ * 'dispatch_comp_buffer()' as a dependency, and access 'CompBuffer' members
+ * through their base type/subobject.
+ *
+ * Note that 'CompBuffer' only provides *access* to the compositing buffer, but
+ * doesn't provide its actual *storage*.  This is the responsibility of the
+ * algorithms that use 'CompBuffer'.  Algorithms that need temporary storage
+ * for the compositing buffer can use 'TempCompBuffer'.
+ *
+ * The 'has_comp_buffer()' constexpr function determines if a given algorithm
+ * hierarchy uses the compositing buffer.
+ *
+ * The 'comp_buffer_data()' function returns a pointer to the compositing
+ * buffer data for the current row if the hierarchy uses the compositing
+ * buffer, or NULL otherwise.
+ */
+
+template <class Base>
+struct CompBuffer : Base
+{
+  /* Component type of the compositing buffer. */
+  using comp_buffer_type = gfloat;
+
+  static constexpr guint filter = Base::filter | ALGORITHM_COMP_BUFFER;
+
+  using Base::Base;
+
+  template <class Derived>
+  struct State : Base::template State<Derived>
+  {
+    /* Pointer to the compositing buffer data for the current row. */
+    comp_buffer_type *comp_buffer_data;
+  };
+};
+
+static BasicDispatch<CompBuffer, ALGORITHM_COMP_BUFFER> dispatch_comp_buffer;
+
+template <class Base>
+static constexpr gboolean
+has_comp_buffer (const CompBuffer<Base> *algorithm)
+{
+  return TRUE;
+}
+
+static constexpr gboolean
+has_comp_buffer (const AlgorithmBase *algorithm)
+{
+  return FALSE;
+}
+
+template <class Base,
+          class State>
+static gfloat *
+comp_buffer_data (const CompBuffer<Base> *algorithm,
+                  State                  *state)
+{
+  return state->comp_buffer_data;
+}
+
+template <class State>
+static gfloat *
+comp_buffer_data (const AlgorithmBase *algorithm,
+                  State               *state)
+{
+  return NULL;
+}
+
+
+/* TempCompBuffer, dispatch_temp_comp_buffer():
+ *
+ * An algorithm helper class, providing temporary storage for the compositing
+ * buffer.  Algorithms that need a temporary compositing buffer should specify
+ * 'dispatch_temp_comp_buffer()' as a dependency, which itself includes
+ * 'dispatch_comp_buffer()' as a dependency.
+ */
+
+template <class Base>
+struct TempCompBuffer : Base
+{
+  static constexpr guint filter = Base::filter | ALGORITHM_TEMP_COMP_BUFFER;
+
+  using Base::Base;
+
+  template <class Derived>
+  using State = typename Base::template State<Derived>;
+
+  template <class Derived>
+  void
+  init_step (const GimpPaintCoreLoopsParams *params,
+             State<Derived>                 *state,
+             GeglBufferIterator             *iter,
+             const GeglRectangle            *roi,
+             const GeglRectangle            *area,
+             const GeglRectangle            *rect) const
+  {
+    Base::init_step (params, state, iter, roi, area, rect);
+
+    state->comp_buffer_data = gegl_scratch_new (gfloat, 4 * rect->width);
+  }
+
+
+  template <class Derived>
+  void
+  finalize_step (const GimpPaintCoreLoopsParams *params,
+                 State<Derived>                 *state) const
+  {
+    gegl_scratch_free (state->comp_buffer_data);
+
+    Base::finalize_step (params, state);
+  }
+};
+
+static BasicDispatch<
+  TempCompBuffer,
+  ALGORITHM_TEMP_COMP_BUFFER,
+  decltype (dispatch_comp_buffer)
+> dispatch_temp_comp_buffer;
+
+
 /* MaskBufferIterator, mask_buffer_iterator_dispatch(),
  * has_mask_buffer_iterator():
  *
@@ -1783,17 +1909,20 @@ struct DoLayerBlend : Base
         const GeglRectangle            *roi,
         const GeglRectangle            *area) const
   {
-    state->iterator_base = gegl_buffer_iterator_add (iter, params->dest_buffer,
+    state->iterator_base = gegl_buffer_iterator_add (iter, params->src_buffer,
                                                      area, 0, iterator_format,
-                                                     GEGL_ACCESS_WRITE,
+                                                     GEGL_ACCESS_READ,
                                                      GEGL_ABYSS_NONE);
 
-    gegl_buffer_iterator_add (iter, params->src_buffer, area, 0,
-                              iterator_format,
-                              GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+    if (! has_comp_buffer ((const Derived *) this))
+      {
+        gegl_buffer_iterator_add (iter, params->dest_buffer, area, 0,
+                                  iterator_format,
+                                  GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
+      }
 
     /* initialize the base class *after* initializing the iterator, to make
-     * sure that dest_buffer is the primary buffer of the iterator, if no
+     * sure that src_buffer is the primary buffer of the iterator, if no
      * subclass added an iterator first.
      */
     Base::init (params, state, iter, roi, area);
@@ -1810,8 +1939,7 @@ struct DoLayerBlend : Base
   {
     Base::init_step (params, state, iter, roi, area, rect);
 
-    state->out_pixel  = (gfloat *) iter->items[state->iterator_base + 0].data;
-    state->in_pixel   = (gfloat *) iter->items[state->iterator_base + 1].data;
+    state->in_pixel = (gfloat *) iter->items[state->iterator_base + 0].data;
 
     state->paint_pixel = this->paint_data                        +
                          (rect->y - roi->y) * this->paint_stride +
@@ -1823,6 +1951,9 @@ struct DoLayerBlend : Base
           (gfloat *) iter->items[mask_buffer_iterator (this, state)].data;
       }
 
+    if (! has_comp_buffer ((const Derived *) this))
+      state->out_pixel = (gfloat *) iter->items[state->iterator_base + 1].data;
+
     state->process_roi.x      = rect->x;
     state->process_roi.width  = rect->width;
     state->process_roi.height = 1;
@@ -1841,6 +1972,7 @@ struct DoLayerBlend : Base
     Base::process_row (params, state, iter, roi, area, rect, y);
 
     gfloat *mask_pixel;
+    gfloat *out_pixel;
 
     if (has_comp_mask (this))
       mask_pixel = comp_mask_data (this, state);
@@ -1849,22 +1981,34 @@ struct DoLayerBlend : Base
     else
       mask_pixel = NULL;
 
+    if (! has_comp_buffer ((const Derived *) this))
+      {
+        out_pixel = state->out_pixel;
+      }
+    else
+      {
+        out_pixel = comp_buffer_data (
+          (const Derived *) this,
+          (typename Derived::template State<Derived> *) state);
+      }
+
     state->process_roi.y = y;
 
     layer_mode.function ((GeglOperation*) &layer_mode,
                          state->in_pixel,
                          state->paint_pixel,
                          mask_pixel,
-                         state->out_pixel,
+                         out_pixel,
                          rect->width,
                          &state->process_roi,
                          0);
 
     state->in_pixel     += rect->width * 4;
-    state->out_pixel    += rect->width * 4;
+    state->paint_pixel  += this->paint_stride;
     if (! has_comp_mask (this) && has_mask_buffer_iterator (this))
       state->mask_pixel += rect->width;
-    state->paint_pixel  += this->paint_stride;
+    if (! has_comp_buffer ((const Derived *) this))
+      state->out_pixel  += rect->width * 4;
   }
 };
 


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