[gimp] app: in gimppaintcore-loops, add [Temp]CompBuffer algorithm helper-classes
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: in gimppaintcore-loops, add [Temp]CompBuffer algorithm helper-classes
- Date: Sat, 16 Feb 2019 15:05:20 +0000 (UTC)
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]