... and gimp_gegl_mask_combine_buffer()
Allow the functions to work with buffers whose top-left corner is
not at (0, 0).
(cherry picked from commit 24534338e7)
In gimp_tile_handler_validate_buffer_set_extent(), suspend tile
validation while calling gimp_gegl_buffer_set_extent(), so that if
the call triggers clearing of partial tiles, these tiles don't get
unnecessarily validated.
(cherry picked from commit fcc1c3d380)
In gimp_tile_handler_validate_validate_tile(), when validating a
partial tile with negative coordinates, make sure to adjust the
result of the modulo when calculating the tile-realtive coordinates
so that they're non-negative, to fix the tile-data pointer offset.
(cherry picked from commit d39822bcd7)
Add a new GimpTileHandlerValidate::invalidated signal, which is
emitted when a region of the buffer is invalidated. This would
allow us to properly invalidate the graph in response; this
normally happens in response to GeglBuffer::changed, but this
signal is not emitted when a region is merely invalidated.
(cherry picked from commit 3ea391602e)
In gimp_gegl_apply_cached_operation(), use gint64 for storing the
total and processed pixel counts used for reporting progress, to
avoid overflowing when applying an operation to a large image.
(cherry picked from commit f1c448e0f4)
Restore the behavior of gimp_gegl_apply_operation() prior to
11629fde66 when src_buffer is NULL:
keep the existing operation-node input, instead of using an empty
input. Unlike gimp_gegl_apply_cached_operation(),
gimp_gegl_apply_operation() doesn't have an explicit
connect_src_buffer parameter.
This fixes empty output when merging layers.
(cherry picked from commit 076d9b2a28)
In gimp_gegl_apply_cached_operation(), add a boolean
connect_src_buffer parameter, which determines whether to connect
the source buffer to the operation-node's input, or to use its
existing input. In gimp_drawable_merge_filter(), pass FALSE for
connect_src_buffer, so that the existing filter-node input is used.
This produces an equivalent result, however, it avoids invalidating
the filter node, and dropping cached data as a result. In
operations that cache larger areas than the ROI, this avoids
reprocessing already-cached data when processing the rest of the
operation.
Additionally, in gimp_gegl_apply_cached_operation(), use an empty
input for the operation if src_buffer is NULL and
connect_src_buffer is TRUE; previously, we'd use the operation-
node's existing input when src_buffer was NULL. Furthermore, crop
the operation-node's input to the destination rect when crop_input
is TRUE, even if connect_src_buffer is FALSE.
(cherry picked from commit 11629fde66)
In gimp_gegl_apply_cached_operation(), when applying a non-point
filter with the same source and destination buffers, render the
result to a temporary buffer to avoid chunking artifacts. We'd
previously duplicate the source buffer instead (with commit
35729ee02a erroneously copying the
cached results to the source/destination buffer before duplicating
it, causing this bug), but we now use a temporary result buffer
instead; this has roughly the same overhead, but would allow us to
keep the original operation-node input when committing a drawable
filter in a future commit, which would avoid dropping any cached
data.
(cherry picked from commit 88c6f8296d)
Add a new "Swap compression" option to the preferences, allowing
explicit control over the tile-swap compression algorithm.
Previously, control over swap compression was only possible through
GEGL command-line options/environment variables. Since the GEGL
API to list all available compression algorithms is still private
for now, we currently only list the three predefined compression
levels -- "best performance" (the default), "balanced", and "best
compression" -- and a "none" option, to disable compression
altogether. Selecting a custom compression algorithm is possible
by entering its name manually.
(cherry picked from commit 1664ecbf1d)
In gimp_gegl_buffer_set_extent(), clear the full now-out-of-bounds
region of the buffer, instead of only full out-of-bounds tiles;
however, we still make sure to clear full tiles, instead of partial
tiles, as much as possible. This prevents (parts of) the old
content of the buffer from showing when it's enlarged again. This
is especially relevant for the image projection, once we add
support for a dynamically-expanding canvas in the following
commits, since the projection of a reexpanded buffer can be
temporarily rendered to the display before it's fully
reconstructed, exposing parts of the old content.
... which sets the extent of a buffer with an assigned
GimpTileHandlerValidate, clipping the dirty region to the new
extent.
(cherry picked from commit b4ee9ff055)
.... as a drop-in replacement for gegl_buffer_set_extent(), which,
in addition to setting the buffer's extent, clears any now-out-of-
bounds tiles, to free memory.
(cherry picked from commit 90610ac87e)
In gimp_gegl_apply_cached_operation(), copy the cached results to
the destination buffer *before* reconnecting the operation node, as
this may cause the cache to be cleared (see commit
gegl@4347255cd9d5031e6757c70fdde5c63539d5f508).
(cherry picked from commit 35729ee02a)
... as a drop-in replacement for gegl_buffer_dup(), which COWs all
tiles of the source buffer, including ones that aren't fully
included within buffer's extent.
(cherry picked from commit 5798cefe1b)
In gimp_gegl_buffer_copy(), assume that the area outside the abyss
is empty, and so, when the abyss policy is NONE, allow data otuside
the source/destination abyss to be copied, by temporarily modifying
the abyss. This allows tiles that aren't fully contained within
the abyss to be COWed, unlike gegl_buffer_copy(), which has to be
more general.
(cherry picked from commit 69ce5e7e02)
In gimp_gegl_apply_[cached_]operation(), use a longer iteration
interval (resulying in bigger chunks) when processing the op, than
the iteration interval used for rendering the projection. In
particular, use an even longer interval when processing area
filters, since their may be particularly sensitive to the chunk
size (see, for example, issue #3711). Likewise, use the asme
longer interval when not showing progress indication, since we
don't need to stay responsive in this case (but don't avoid
chunking altogether, to reduce the space required for intermediate
results).
This allows us to process an op faster when committing a filter,
while still remaining responsive (if overall slower) during
preview.
(cherry picked from commit 5a500b4a12)
... which determines if a node is an area filter operation. If the
node is a meta op, we conservatively return TRUE, as it may involve
an area-filter op.
(cherry picked from commit f6c4e4912a)
Add a "gboolean edge_lock" parameter to GimpChannel::feather() and a
"Selected areas continue outside the image" toggle to the "Feather
Selection" dialog, just like they exist for shrink selection and
border selection. At the end, convert the boolean to the right abyss
policy for gegl:gaussian-blur.
(cherry picked from commit aace6b179b)
In gimp_gegl_apply_[cached_]operation(), add support for output
buffers whose extent's top-left corner is not (0, 0). This is
needed by the previous commit.
(cherry picked from commit a6393e6c55)
In gimp_layer_mode_get_format(), disregard the requested composite
space when selecting the format, if the input layer mode is alpha-
only, and the requested composite mode is not UNION, since, in this
case, the layer mode doesn't combine the layer/backdrop colors, and
rather only modifies the alpha of one of them. This allows us to
use the preferred format, avoiding gamma conversion.
This particularly improves the performance of the Eraser tool in
perceptual images.
(cherry picked from commit a5962e4049)
In the vairous gimp_gegl_create_foo_node() functions, set the
parent node's underlying operation node, so that
gimp_gegl_apply_cached_operation() avoids duplicating the source
buffer when applying these nodes (all underlying operations are
currently point ops.)
(cherry picked from commit 928e5957e3)
In gimp_gegl_apply_cached_operation(), use the underlying
operation, as returned from
gimp_gegl_node_get_underlying_operation(), for testing whether the
operation is a point operation, for the purpose of avoiding
duplicating the input buffer. Likewise, avoid duplicating the
buffer when the underlying operation is a source operation.
(cherry picked from commit 213b126c6e)
... which allow setting/getting the "underlying operation" node of
a graph node. For example, GimpDrawableFilter constructs a complex
graph around a given operation node, which would be the underlying
operation of the graph. This allows querying the properties of the
underlying operation, given only the graph.
In recursive cases, gimp_gegl_node_get_underlying_operation()
returns the most-nested underlying operation; when no underlying
operation has been set, gimp_gegl_node_get_underlying_operation()
returns the input node.
(cherry picked from commit eb5e473665)
In gimp_drawable_merge_filter(), disable the filter applicator's
cache and output-format conversion nodes before processing the
uncached region of the filter, so that the result is written
directly to the drawable's buffer.
(cherry picked from commit 733a6ec01c)
Simplify code, use gimp_gegl_buffer_copy() for CHANNEL_OP_REPLACE
when possible, improve value clipping, and parallelize processing.
(cherry picked from commit a227c8e94d)
Improve gimp_gegl_mask_combine_ellipse_rect() -- the funciton
responsible for rendering ellipse/rounded-rectangle selections.
Most notably, this commit significantly improves the function's
performance, by identifying whole tiles, whole rows, or parts of a
row, that are fully inside, or fully outside, the ellipse, and
filling them in bulk, instead of calculating the anti-aliasing
value at each pixel, which is now only done along the
circumference.
This commit also improves anti-aliasing, by more accurately
approximating the distance from a pixel to the ellipse, and by
normalizing the distance according to the pixel's cross-section
length in the direction of the said point. In particular, we
guarantee that pixels that are fully inside/outside the ellipse
have a value of 1/0, respectively, facilitating the aforementioned
optimization.
Additionally, this commit fixes various edge cases where several
primitives coincide at a single pixel (in the rounded-rectangle
case), adds support for CHANNEL_OP_INTERSECT, and parallelizes
processing.
(cherry picked from commit 1044342393)
... which takes a GimpPrecision, and determines if its values are
bounded to the [0,1] range (which is currently only true for
integer precisions).
(cherry picked from commit d7f12c9d26)
In gimp_gegl_create_flatten_node(), explicitly set the output
format of the background gegl:color node according to the composite
space, so that no conversion is required during compositing.
(cherry picked from commit ebf2c2fef1)
In gimp_gegl_apply_cached_operation(), when the source and
destination buffers are the same, avoid duplicating the source
buffer when the applied operation is a point operation, since
applying it in chunks from/to the same buffer is not a problem in
this case.
(cherry picked from commit 0d21f2469b)
... which takes a GeglNode, and determines if the associated
operation is a point operation.
Use in GimpFilterTool, instead of performing the same check
manually.
(cherry picked from commit 918f2e75bd)
Remove gimp_gegl_replace(), which is not used anywhere since the
last commit. It's redundant with the rest of our compositing code,
in particular, gimp:replace and gimp:mask-components.
(cherry picked from commit d2f8413173)
Plug-ins are not prepared to handle high-precision brushes/
patterns, even when they're otherwise aware of high-precision
drawables, so make sure to always use compat formats when
communicating brush/pattern data to plug-ins.
Allowing plug-ins to handle high-precision brush/pattern data would
require some additional API.
(cherry picked from commit 82c449496e)
In gimp_tile_handler_validate_buffer_copy(), temporarily remove the
source buffer's validate handler, is exists, so that the subsequent
gegl_buffer_copy() can use fast tile copying, using the TILE_COPY
command. GEGL currently only uses TILE_COPY when the source buffer
doesn't have any user-provided tile handlers.
(cherry picked from commit f4750a0ae7)
In gimp_gegl_apply_cached_operation(), replace the use of
GeglProcessor with GimpChunkIterator, so that we use the same
chunking logic as for rendering projections. This has the
advantage of better chunk alignment to the tile grid and dynamic
chunk sizing, which improve performance.
Use chunking even when there's no progress indication, since it
generally results in better cache locality.
(cherry picked from commit 4110f7b7b1)
In GimpTileHandlerValidate, when rendering a whole tile in respone
to a TILE_GET command, use gegl_tile_handler_get_tile() to get the
tile without preserving its data, so that we avoid unnecessarily
fetching the tile from storage, or copying its data during
uncloning.
(cherry picked from commit 78ed038fca)