mirror of https://github.com/GNOME/gimp.git
app: refactor gimppaintcore-loops to coalesce iteration
The gimppaintcore-loops functions perform very little actual computational work (in case of do_layer_blend(), at least for simple blend modes), which makes the cost of buffer iteration, and memory bandwidth, nonnegligible factors. Since these functions are usually called in succession, acessing the same region of the same buffers, using the same foramts, coalescing them into a single function, which performs all the necessary processing in a single step, can improve performance when these functions are the bottleneck. Add a gimp_paint_core_loops_process() function, which does just that: it takes a set of algorithms to run, and a set of parameters, and performs all of them in one go. The individual functions are kept for convenience, but are merely wrappers around gimp_paint_core_loops_process(). Be warned: the implementation uses unholy C++ from outer space, in order to make this (sort of) managable. See the comments for more details.
This commit is contained in:
parent
76eedf2198
commit
f2a1fd5bf0
File diff suppressed because it is too large
Load Diff
|
@ -19,6 +19,48 @@
|
|||
#define __GIMP_PAINT_CORE_LOOPS_H__
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GIMP_PAINT_CORE_LOOPS_ALGORITHM_NONE = 0,
|
||||
|
||||
GIMP_PAINT_CORE_LOOPS_ALGORITHM_COMBINE_PAINT_MASK_TO_CANVAS_MASK = 1 << 0,
|
||||
GIMP_PAINT_CORE_LOOPS_ALGORITHM_CANVAS_BUFFER_TO_PAINT_BUF_ALPHA = 1 << 1,
|
||||
GIMP_PAINT_CORE_LOOPS_ALGORITHM_PAINT_MASK_TO_PAINT_BUFFER = 1 << 2,
|
||||
GIMP_PAINT_CORE_LOOPS_ALGORITHM_DO_LAYER_BLEND = 1 << 3
|
||||
} GimpPaintCoreLoopsAlgorithm;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GeglBuffer *canvas_buffer;
|
||||
|
||||
GimpTempBuf *paint_buf;
|
||||
gint paint_buf_offset_x;
|
||||
gint paint_buf_offset_y;
|
||||
|
||||
const GimpTempBuf *paint_mask;
|
||||
gint paint_mask_offset_x;
|
||||
gint paint_mask_offset_y;
|
||||
|
||||
gboolean stipple;
|
||||
|
||||
GeglBuffer *src_buffer;
|
||||
GeglBuffer *dest_buffer;
|
||||
|
||||
GeglBuffer *mask_buffer;
|
||||
gint mask_offset_x;
|
||||
gint mask_offset_y;
|
||||
|
||||
gdouble paint_opacity;
|
||||
gdouble image_opacity;
|
||||
|
||||
GimpLayerMode paint_mode;
|
||||
} GimpPaintCoreLoopsParams;
|
||||
|
||||
|
||||
void gimp_paint_core_loops_process (const GimpPaintCoreLoopsParams *params,
|
||||
GimpPaintCoreLoopsAlgorithm algorithms);
|
||||
|
||||
void combine_paint_mask_to_canvas_mask (const GimpTempBuf *paint_mask,
|
||||
gint mask_x_offset,
|
||||
gint mask_y_offset,
|
||||
|
|
|
@ -864,77 +864,78 @@ gimp_paint_core_paste (GimpPaintCore *core,
|
|||
}
|
||||
else
|
||||
{
|
||||
GimpTempBuf *paint_buf = gimp_gegl_buffer_get_temp_buf (core->paint_buffer);
|
||||
GeglBuffer *dest_buffer;
|
||||
GeglBuffer *src_buffer;
|
||||
GimpPaintCoreLoopsParams params = {};
|
||||
GimpPaintCoreLoopsAlgorithm algorithms = GIMP_PAINT_CORE_LOOPS_ALGORITHM_NONE;
|
||||
|
||||
if (! paint_buf)
|
||||
params.paint_buf = gimp_gegl_buffer_get_temp_buf (core->paint_buffer);
|
||||
params.paint_buf_offset_x = core->paint_buffer_x;
|
||||
params.paint_buf_offset_y = core->paint_buffer_y;
|
||||
|
||||
if (! params.paint_buf)
|
||||
return;
|
||||
|
||||
if (core->comp_buffer)
|
||||
dest_buffer = core->comp_buffer;
|
||||
params.dest_buffer = core->comp_buffer;
|
||||
else
|
||||
dest_buffer = gimp_drawable_get_buffer (drawable);
|
||||
params.dest_buffer = gimp_drawable_get_buffer (drawable);
|
||||
|
||||
if (mode == GIMP_PAINT_CONSTANT)
|
||||
{
|
||||
params.canvas_buffer = core->canvas_buffer;
|
||||
|
||||
/* This step is skipped by the ink tool, which writes
|
||||
* directly to canvas_buffer
|
||||
*/
|
||||
if (paint_mask != NULL)
|
||||
{
|
||||
/* Mix paint mask and canvas_buffer */
|
||||
combine_paint_mask_to_canvas_mask (paint_mask,
|
||||
paint_mask_offset_x,
|
||||
paint_mask_offset_y,
|
||||
core->canvas_buffer,
|
||||
core->paint_buffer_x,
|
||||
core->paint_buffer_y,
|
||||
paint_opacity,
|
||||
GIMP_IS_AIRBRUSH (core));
|
||||
params.paint_mask = paint_mask;
|
||||
params.paint_mask_offset_x = paint_mask_offset_x;
|
||||
params.paint_mask_offset_y = paint_mask_offset_y;
|
||||
params.stipple = GIMP_IS_AIRBRUSH (core);
|
||||
params.paint_opacity = paint_opacity;
|
||||
|
||||
algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_COMBINE_PAINT_MASK_TO_CANVAS_MASK;
|
||||
}
|
||||
|
||||
/* Write canvas_buffer to paint_buf */
|
||||
canvas_buffer_to_paint_buf_alpha (paint_buf,
|
||||
core->canvas_buffer,
|
||||
core->paint_buffer_x,
|
||||
core->paint_buffer_y);
|
||||
algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_CANVAS_BUFFER_TO_PAINT_BUF_ALPHA;
|
||||
|
||||
/* undo buf -> paint_buf -> dest_buffer */
|
||||
src_buffer = core->undo_buffer;
|
||||
params.src_buffer = core->undo_buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_return_if_fail (paint_mask);
|
||||
|
||||
/* Write paint_mask to paint_buf, does not modify canvas_buffer */
|
||||
paint_mask_to_paint_buffer (paint_mask,
|
||||
paint_mask_offset_x,
|
||||
paint_mask_offset_y,
|
||||
paint_buf,
|
||||
paint_opacity);
|
||||
params.paint_mask = paint_mask;
|
||||
params.paint_mask_offset_x = paint_mask_offset_x;
|
||||
params.paint_mask_offset_y = paint_mask_offset_y;
|
||||
params.paint_opacity = paint_opacity;
|
||||
|
||||
algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_PAINT_MASK_TO_PAINT_BUFFER;
|
||||
|
||||
/* dest_buffer -> paint_buf -> dest_buffer */
|
||||
if (core->comp_buffer)
|
||||
src_buffer = gimp_drawable_get_buffer (drawable);
|
||||
params.src_buffer = gimp_drawable_get_buffer (drawable);
|
||||
else
|
||||
src_buffer = dest_buffer;
|
||||
params.src_buffer = params.dest_buffer;
|
||||
}
|
||||
|
||||
do_layer_blend (src_buffer,
|
||||
dest_buffer,
|
||||
paint_buf,
|
||||
core->mask_buffer,
|
||||
image_opacity,
|
||||
core->paint_buffer_x,
|
||||
core->paint_buffer_y,
|
||||
core->mask_x_offset,
|
||||
core->mask_y_offset,
|
||||
paint_mode);
|
||||
params.mask_buffer = core->mask_buffer;
|
||||
params.mask_offset_x = core->mask_x_offset;
|
||||
params.mask_offset_y = core->mask_y_offset;
|
||||
params.image_opacity = image_opacity;
|
||||
params.paint_mode = paint_mode;
|
||||
|
||||
algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_DO_LAYER_BLEND;
|
||||
|
||||
gimp_paint_core_loops_process (¶ms, algorithms);
|
||||
|
||||
if (core->comp_buffer)
|
||||
{
|
||||
mask_components_onto (src_buffer,
|
||||
mask_components_onto (params.src_buffer,
|
||||
core->comp_buffer,
|
||||
gimp_drawable_get_buffer (drawable),
|
||||
GEGL_RECTANGLE (core->paint_buffer_x,
|
||||
|
|
Loading…
Reference in New Issue