app: parallelize gimppaintcore-loops.cc

Ditto.
This commit is contained in:
Ell 2018-04-04 17:02:34 -04:00
parent e8a14deecf
commit 3df757ffd7
1 changed files with 233 additions and 205 deletions

View File

@ -27,6 +27,7 @@ extern "C"
#include "operations/layer-modes/gimp-layer-modes.h"
#include "core/gimp-parallel.h"
#include "core/gimptempbuf.h"
#include "operations/layer-modes/gimpoperationlayermode.h"
@ -34,6 +35,10 @@ extern "C"
#include "gimppaintcore-loops.h"
#define MIN_PARALLEL_SUB_SIZE 64
#define MIN_PARALLEL_SUB_AREA (MIN_PARALLEL_SUB_SIZE * MIN_PARALLEL_SUB_SIZE)
void
combine_paint_mask_to_canvas_mask (const GimpTempBuf *paint_mask,
gint mask_x_offset,
@ -44,8 +49,7 @@ combine_paint_mask_to_canvas_mask (const GimpTempBuf *paint_mask,
gfloat opacity,
gboolean stipple)
{
GeglRectangle roi;
GeglBufferIterator *iter;
GeglRectangle roi;
const gint mask_stride = gimp_temp_buf_get_width (paint_mask);
const gint mask_start_offset = mask_y_offset * mask_stride + mask_x_offset;
@ -61,126 +65,132 @@ combine_paint_mask_to_canvas_mask (const GimpTempBuf *paint_mask,
roi.width = width - mask_x_offset;
roi.height = height - mask_y_offset;
iter = gegl_buffer_iterator_new (canvas_buffer, &roi, 0,
babl_format ("Y float"),
GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE);
if (stipple)
gimp_parallel_distribute_area (&roi, MIN_PARALLEL_SUB_AREA,
[=] (const GeglRectangle *area)
{
if (mask_format == babl_format ("Y u8"))
GeglBufferIterator *iter;
iter = gegl_buffer_iterator_new (canvas_buffer, area, 0,
babl_format ("Y float"),
GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE);
if (stipple)
{
const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask);
mask_data += mask_start_offset;
while (gegl_buffer_iterator_next (iter))
if (mask_format == babl_format ("Y u8"))
{
gfloat *out_pixel = (gfloat *)iter->data[0];
int iy, ix;
const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask);
mask_data += mask_start_offset;
for (iy = 0; iy < iter->roi[0].height; iy++)
while (gegl_buffer_iterator_next (iter))
{
int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
const guint8 *mask_pixel = &mask_data[mask_offset];
gfloat *out_pixel = (gfloat *)iter->data[0];
int iy, ix;
for (ix = 0; ix < iter->roi[0].width; ix++)
for (iy = 0; iy < iter->roi[0].height; iy++)
{
out_pixel[0] += (1.0 - out_pixel[0]) * (*mask_pixel / 255.0f) * opacity;
int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
const guint8 *mask_pixel = &mask_data[mask_offset];
mask_pixel += 1;
out_pixel += 1;
for (ix = 0; ix < iter->roi[0].width; ix++)
{
out_pixel[0] += (1.0 - out_pixel[0]) * (*mask_pixel / 255.0f) * opacity;
mask_pixel += 1;
out_pixel += 1;
}
}
}
}
}
else if (mask_format == babl_format ("Y float"))
{
const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask);
mask_data += mask_start_offset;
while (gegl_buffer_iterator_next (iter))
else if (mask_format == babl_format ("Y float"))
{
gfloat *out_pixel = (gfloat *)iter->data[0];
int iy, ix;
const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask);
mask_data += mask_start_offset;
for (iy = 0; iy < iter->roi[0].height; iy++)
while (gegl_buffer_iterator_next (iter))
{
int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
const gfloat *mask_pixel = &mask_data[mask_offset];
gfloat *out_pixel = (gfloat *)iter->data[0];
int iy, ix;
for (ix = 0; ix < iter->roi[0].width; ix++)
for (iy = 0; iy < iter->roi[0].height; iy++)
{
out_pixel[0] += (1.0 - out_pixel[0]) * (*mask_pixel) * opacity;
int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
const gfloat *mask_pixel = &mask_data[mask_offset];
mask_pixel += 1;
out_pixel += 1;
for (ix = 0; ix < iter->roi[0].width; ix++)
{
out_pixel[0] += (1.0 - out_pixel[0]) * (*mask_pixel) * opacity;
mask_pixel += 1;
out_pixel += 1;
}
}
}
}
else
{
g_warning("Mask format not supported: %s", babl_get_name (mask_format));
}
}
else
{
g_warning("Mask format not supported: %s", babl_get_name (mask_format));
}
}
else
{
if (mask_format == babl_format ("Y u8"))
{
const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask);
mask_data += mask_start_offset;
while (gegl_buffer_iterator_next (iter))
if (mask_format == babl_format ("Y u8"))
{
gfloat *out_pixel = (gfloat *)iter->data[0];
int iy, ix;
const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask);
mask_data += mask_start_offset;
for (iy = 0; iy < iter->roi[0].height; iy++)
while (gegl_buffer_iterator_next (iter))
{
int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
const guint8 *mask_pixel = &mask_data[mask_offset];
gfloat *out_pixel = (gfloat *)iter->data[0];
int iy, ix;
for (ix = 0; ix < iter->roi[0].width; ix++)
for (iy = 0; iy < iter->roi[0].height; iy++)
{
if (opacity > out_pixel[0])
out_pixel[0] += (opacity - out_pixel[0]) * (*mask_pixel / 255.0f) * opacity;
int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
const guint8 *mask_pixel = &mask_data[mask_offset];
mask_pixel += 1;
out_pixel += 1;
for (ix = 0; ix < iter->roi[0].width; ix++)
{
if (opacity > out_pixel[0])
out_pixel[0] += (opacity - out_pixel[0]) * (*mask_pixel / 255.0f) * opacity;
mask_pixel += 1;
out_pixel += 1;
}
}
}
}
}
else if (mask_format == babl_format ("Y float"))
{
const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask);
mask_data += mask_start_offset;
while (gegl_buffer_iterator_next (iter))
else if (mask_format == babl_format ("Y float"))
{
gfloat *out_pixel = (gfloat *)iter->data[0];
int iy, ix;
const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask);
mask_data += mask_start_offset;
for (iy = 0; iy < iter->roi[0].height; iy++)
while (gegl_buffer_iterator_next (iter))
{
int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
const gfloat *mask_pixel = &mask_data[mask_offset];
gfloat *out_pixel = (gfloat *)iter->data[0];
int iy, ix;
for (ix = 0; ix < iter->roi[0].width; ix++)
for (iy = 0; iy < iter->roi[0].height; iy++)
{
if (opacity > out_pixel[0])
out_pixel[0] += (opacity - out_pixel[0]) * (*mask_pixel) * opacity;
int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x;
const gfloat *mask_pixel = &mask_data[mask_offset];
mask_pixel += 1;
out_pixel += 1;
for (ix = 0; ix < iter->roi[0].width; ix++)
{
if (opacity > out_pixel[0])
out_pixel[0] += (opacity - out_pixel[0]) * (*mask_pixel) * opacity;
mask_pixel += 1;
out_pixel += 1;
}
}
}
}
else
{
g_warning("Mask format not supported: %s", babl_get_name (mask_format));
}
}
else
{
g_warning("Mask format not supported: %s", babl_get_name (mask_format));
}
}
});
}
void
@ -191,7 +201,6 @@ canvas_buffer_to_paint_buf_alpha (GimpTempBuf *paint_buf,
{
/* Copy the canvas buffer in rect to the paint buffer's alpha channel */
GeglRectangle roi;
GeglBufferIterator *iter;
const guint paint_stride = gimp_temp_buf_get_width (paint_buf);
gfloat *paint_data = (gfloat *) gimp_temp_buf_get_data (paint_buf);
@ -201,29 +210,35 @@ canvas_buffer_to_paint_buf_alpha (GimpTempBuf *paint_buf,
roi.width = gimp_temp_buf_get_width (paint_buf);
roi.height = gimp_temp_buf_get_height (paint_buf);
iter = gegl_buffer_iterator_new (canvas_buffer, &roi, 0,
babl_format ("Y float"),
GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
while (gegl_buffer_iterator_next (iter))
gimp_parallel_distribute_area (&roi, MIN_PARALLEL_SUB_AREA,
[=] (const GeglRectangle *area)
{
gfloat *canvas_pixel = (gfloat *)iter->data[0];
int iy, ix;
GeglBufferIterator *iter;
for (iy = 0; iy < iter->roi[0].height; iy++)
iter = gegl_buffer_iterator_new (canvas_buffer, &roi, 0,
babl_format ("Y float"),
GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
while (gegl_buffer_iterator_next (iter))
{
int paint_offset = (iy + iter->roi[0].y - roi.y) * paint_stride + iter->roi[0].x - roi.x;
float *paint_pixel = &paint_data[paint_offset * 4];
gfloat *canvas_pixel = (gfloat *)iter->data[0];
int iy, ix;
for (ix = 0; ix < iter->roi[0].width; ix++)
for (iy = 0; iy < iter->roi[0].height; iy++)
{
paint_pixel[3] *= *canvas_pixel;
int paint_offset = (iy + iter->roi[0].y - roi.y) * paint_stride + iter->roi[0].x - roi.x;
float *paint_pixel = &paint_data[paint_offset * 4];
canvas_pixel += 1;
paint_pixel += 4;
for (ix = 0; ix < iter->roi[0].width; ix++)
{
paint_pixel[3] *= *canvas_pixel;
canvas_pixel += 1;
paint_pixel += 4;
}
}
}
}
});
}
void
@ -240,51 +255,56 @@ paint_mask_to_paint_buffer (const GimpTempBuf *paint_mask,
const gint mask_start_offset = mask_y_offset * mask_stride + mask_x_offset;
const Babl *mask_format = gimp_temp_buf_get_format (paint_mask);
int iy, ix;
gfloat *paint_pixel = (gfloat *)gimp_temp_buf_get_data (paint_buf);
/* Validate that the paint buffer is withing the bounds of the paint mask */
g_return_if_fail (width <= gimp_temp_buf_get_width (paint_mask) - mask_x_offset);
g_return_if_fail (height <= gimp_temp_buf_get_height (paint_mask) - mask_y_offset);
if (mask_format == babl_format ("Y u8"))
gimp_parallel_distribute_range (height, MIN_PARALLEL_SUB_SIZE,
[=] (gint y, gint height)
{
const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask);
mask_data += mask_start_offset;
int iy, ix;
gfloat *paint_pixel = (gfloat *)gimp_temp_buf_get_data (paint_buf) +
y * width * 4;
for (iy = 0; iy < height; iy++)
if (mask_format == babl_format ("Y u8"))
{
int mask_offset = iy * mask_stride;
const guint8 *mask_pixel = &mask_data[mask_offset];
const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask);
mask_data += mask_start_offset + y * mask_stride;
for (ix = 0; ix < width; ix++)
for (iy = 0; iy < height; iy++)
{
paint_pixel[3] *= (((gfloat)*mask_pixel) / 255.0f) * paint_opacity;
int mask_offset = iy * mask_stride;
const guint8 *mask_pixel = &mask_data[mask_offset];
mask_pixel += 1;
paint_pixel += 4;
for (ix = 0; ix < width; ix++)
{
paint_pixel[3] *= (((gfloat)*mask_pixel) / 255.0f) * paint_opacity;
mask_pixel += 1;
paint_pixel += 4;
}
}
}
}
else if (mask_format == babl_format ("Y float"))
{
const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask);
mask_data += mask_start_offset;
for (iy = 0; iy < height; iy++)
else if (mask_format == babl_format ("Y float"))
{
int mask_offset = iy * mask_stride;
const gfloat *mask_pixel = &mask_data[mask_offset];
const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask);
mask_data += mask_start_offset + y * mask_stride;
for (ix = 0; ix < width; ix++)
for (iy = 0; iy < height; iy++)
{
paint_pixel[3] *= (*mask_pixel) * paint_opacity;
int mask_offset = iy * mask_stride;
const gfloat *mask_pixel = &mask_data[mask_offset];
mask_pixel += 1;
paint_pixel += 4;
for (ix = 0; ix < width; ix++)
{
paint_pixel[3] *= (*mask_pixel) * paint_opacity;
mask_pixel += 1;
paint_pixel += 4;
}
}
}
}
});
}
void
@ -300,10 +320,7 @@ do_layer_blend (GeglBuffer *src_buffer,
GimpLayerMode paint_mode)
{
GeglRectangle roi;
GeglRectangle mask_roi;
GeglRectangle process_roi;
const Babl *iterator_format;
GeglBufferIterator *iter;
guint paint_stride;
gfloat *paint_data;
GimpOperationLayerMode layer_mode;
@ -330,65 +347,71 @@ do_layer_blend (GeglBuffer *src_buffer,
roi.width = gimp_temp_buf_get_width (paint_buf);
roi.height = gimp_temp_buf_get_height (paint_buf);
mask_roi.x = roi.x - mask_x_offset;
mask_roi.y = roi.y - mask_y_offset;
mask_roi.width = roi.width;
mask_roi.height = roi.height;
g_return_if_fail (gimp_temp_buf_get_format (paint_buf) == iterator_format);
iter = gegl_buffer_iterator_new (dst_buffer, &roi, 0,
iterator_format,
GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
gegl_buffer_iterator_add (iter, src_buffer, &roi, 0,
iterator_format,
GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
if (mask_buffer)
gimp_parallel_distribute_area (&roi, MIN_PARALLEL_SUB_AREA,
[=] (const GeglRectangle *area)
{
gegl_buffer_iterator_add (iter, mask_buffer, &mask_roi, 0,
babl_format ("Y float"),
GeglBufferIterator *iter;
GeglRectangle mask_area = *area;
mask_area.x -= mask_x_offset;
mask_area.y -= mask_y_offset;
iter = gegl_buffer_iterator_new (dst_buffer, area, 0,
iterator_format,
GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
gegl_buffer_iterator_add (iter, src_buffer, area, 0,
iterator_format,
GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
}
while (gegl_buffer_iterator_next (iter))
{
gfloat *out_pixel = (gfloat *) iter->data[0];
gfloat *in_pixel = (gfloat *) iter->data[1];
gfloat *mask_pixel = NULL;
gfloat *paint_pixel;
gint iy;
paint_pixel = paint_data + ((iter->roi[0].y - roi.y) * paint_stride + iter->roi[0].x - roi.x) * 4;
if (mask_buffer)
mask_pixel = (gfloat *)iter->data[2];
process_roi.x = iter->roi[0].x;
process_roi.width = iter->roi[0].width;
process_roi.height = 1;
for (iy = 0; iy < iter->roi[0].height; iy++)
{
process_roi.y = iter->roi[0].y + iy;
layer_mode.function ((GeglOperation*) &layer_mode,
in_pixel,
paint_pixel,
mask_pixel,
out_pixel,
iter->roi[0].width,
&process_roi,
0);
in_pixel += iter->roi[0].width * 4;
out_pixel += iter->roi[0].width * 4;
if (mask_buffer)
mask_pixel += iter->roi[0].width;
paint_pixel += paint_stride * 4;
gegl_buffer_iterator_add (iter, mask_buffer, &mask_area, 0,
babl_format ("Y float"),
GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
}
}
while (gegl_buffer_iterator_next (iter))
{
GeglRectangle process_roi;
gfloat *out_pixel = (gfloat *) iter->data[0];
gfloat *in_pixel = (gfloat *) iter->data[1];
gfloat *mask_pixel = NULL;
gfloat *paint_pixel;
gint iy;
paint_pixel = paint_data + ((iter->roi[0].y - roi.y) * paint_stride + iter->roi[0].x - roi.x) * 4;
if (mask_buffer)
mask_pixel = (gfloat *)iter->data[2];
process_roi.x = iter->roi[0].x;
process_roi.width = iter->roi[0].width;
process_roi.height = 1;
for (iy = 0; iy < iter->roi[0].height; iy++)
{
process_roi.y = iter->roi[0].y + iy;
layer_mode.function ((GeglOperation*) &layer_mode,
in_pixel,
paint_pixel,
mask_pixel,
out_pixel,
iter->roi[0].width,
&process_roi,
0);
in_pixel += iter->roi[0].width * 4;
out_pixel += iter->roi[0].width * 4;
if (mask_buffer)
mask_pixel += iter->roi[0].width;
paint_pixel += paint_stride * 4;
}
}
});
}
void
@ -399,45 +422,50 @@ mask_components_onto (GeglBuffer *src_buffer,
GimpComponentMask mask,
gboolean linear_mode)
{
GeglBufferIterator *iter;
const Babl *iterator_format;
const Babl *iterator_format;
if (linear_mode)
iterator_format = babl_format ("RGBA float");
else
iterator_format = babl_format ("R'G'B'A float");
iter = gegl_buffer_iterator_new (dst_buffer, roi, 0,
iterator_format,
GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
gegl_buffer_iterator_add (iter, src_buffer, roi, 0,
iterator_format,
GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
gegl_buffer_iterator_add (iter, aux_buffer, roi, 0,
iterator_format,
GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
while (gegl_buffer_iterator_next (iter))
gimp_parallel_distribute_area (roi, MIN_PARALLEL_SUB_AREA,
[=] (const GeglRectangle *area)
{
gfloat *dest = (gfloat *)iter->data[0];
gfloat *src = (gfloat *)iter->data[1];
gfloat *aux = (gfloat *)iter->data[2];
glong samples = iter->length;
GeglBufferIterator *iter;
while (samples--)
iter = gegl_buffer_iterator_new (dst_buffer, area, 0,
iterator_format,
GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
gegl_buffer_iterator_add (iter, src_buffer, area, 0,
iterator_format,
GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
gegl_buffer_iterator_add (iter, aux_buffer, area, 0,
iterator_format,
GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
while (gegl_buffer_iterator_next (iter))
{
dest[RED] = (mask & GIMP_COMPONENT_MASK_RED) ? aux[RED] : src[RED];
dest[GREEN] = (mask & GIMP_COMPONENT_MASK_GREEN) ? aux[GREEN] : src[GREEN];
dest[BLUE] = (mask & GIMP_COMPONENT_MASK_BLUE) ? aux[BLUE] : src[BLUE];
dest[ALPHA] = (mask & GIMP_COMPONENT_MASK_ALPHA) ? aux[ALPHA] : src[ALPHA];
gfloat *dest = (gfloat *)iter->data[0];
gfloat *src = (gfloat *)iter->data[1];
gfloat *aux = (gfloat *)iter->data[2];
glong samples = iter->length;
src += 4;
aux += 4;
dest += 4;
while (samples--)
{
dest[RED] = (mask & GIMP_COMPONENT_MASK_RED) ? aux[RED] : src[RED];
dest[GREEN] = (mask & GIMP_COMPONENT_MASK_GREEN) ? aux[GREEN] : src[GREEN];
dest[BLUE] = (mask & GIMP_COMPONENT_MASK_BLUE) ? aux[BLUE] : src[BLUE];
dest[ALPHA] = (mask & GIMP_COMPONENT_MASK_ALPHA) ? aux[ALPHA] : src[ALPHA];
src += 4;
aux += 4;
dest += 4;
}
}
}
});
}
} /* extern "C" */