The default stack size for new threads on MacOS is 512 KiB, making
our 512 KiB limit for stack-allocated buffers in
gimp_operation_layer_mode_real_process() too high. Lower it to
256 KiB.
(cherry picked from commit 367399e5c0)
Our composite modes don't correspond directly to the Porter-Duff
operators after which they're named, and these names aren't too
descriptive anyway.
Rename the composite modes as follows:
Source Over => Union
Source Atop => Clip to Backdrop
Destination Atop => Clip to Layer
Source In => Intersection
Update relevant code, including UI text, enumerator names, function
names, and action names.
which is just a #define to g_assert for now, but can now easily be
turned into something that does some nicer debugging using our new
stack trace infrastructure. This commit also reverts all constructed()
functions to use assert again.
Use gimp:buffer-source-validate, introduced in the previous commit,
for the source node of GimpDrawables. This avoids threading issues
with layer groups, or any other drawables that may use a validating
buffer, by making sure the buffer is validated before any
succeeding operations, and hence the associated graph is processed
on the same thread as the parent composition.
Restore multithreaded processing in GimpOperationLayerMode.
Temporarily disable multithreading for GimpOperationLayerMode, to
avoid the deadlock. The environment variable
GIMP_MULTITHREADED_COMPOSITING can be set to reenable it, for the
sake of debugging.
this commit changes just those which make no difference to
functionality: property and object member defaults that get overridden
anyway, return values of g_return_val_if_fail(), some other stuff.
Commit 3635cf04ab moved the special
handling of bottom-layer compositing to GimpOperationLayerMode.
This required giving the op more control over the process()
function of its subclasses. As a temporary workaround, the commit
bypassed the subclasses entirely, using "gimp:layer-mode" for all
modes. This is the reckoning :)
Add a process() virtual function to GimpOperationLayerMode, which
its subclasses should override instead of
GeglOperationPointComposer3's process() functions. Reinstate the
subclasses (by returning the correct op in
gimp_layer_mode_get_oepration()), and have them override this
function.
Improve the way gimp_operation_layer_mode_process() dispatches to
the actual process function, to slightly lower its overhead and
fix some thread-safety issues.
Remove the "function" field of the layer-mode info array, and have
gimp_layer_mode_get_function() return the
GimpOperationLayerMode::process() function of the corresponding
op's class (caching the result, to keep it cheap.) This reduces
redundancy, allows us to make the ops' process() functions private,
and simplifies SSE dispatching (only used by NORMAL mode,
currently.)
Move the blend and composite functions of the non-specialized
layer modes to gimpoperationlayermode-{blend,composite}.[hc],
respectively, to improve code organization.
Move the SSE2 composite functions to a separate file, so that they
can be built as part of libapplayermodes_sse2, allowing
libapplayermodes to be built without SSE2 compiler flags. This
allows building GIMP with SSE acceleration enabled, while running
the resulting binary on a target with no SSE accelration.
Add a "blend_function" field to the layer-mode info array, and use
it to specify the blend function for the non-specialized modes.
This replaces the separate switch() statement that we used
previously.
Remove the "affected_region" field of the layer-mode info array.
We don't need it anymore, since we can go back to using
GimpOperationLayerMode's virtual get_affected_region() function.
Last but not least, a bunch of code cleanups and consistency
adjustments.
GimpFilter's is_last_node field only reflects the item's position
within the parent stack. When a layer is contained in a pass-
through group, it can be the last layer of the group, while not
being the last layer in the graph as a whole (paticularly, if
there are visible layers below the group). In fact, when we have
nested pass-through groups, whether or not a layer is the last
node depends on which group we're considering as the root (since
we exclude the backdrop from the group's projection, resulting in
different graphs for different groups).
Instead of rolling our own graph traversal, just move the relevant
logic to GimpOperationLayerMode, and let GEGL do the work for us.
At processing time, we can tell if we're the last node by checking
if we have any input.
For this to work, GimpOperationLayerMode's process() function needs
to have control over what's going on. Replace the derived op
classes, which override process(), with a call to the layer mode's
function (as per gimp_layer_mode_get_function()) in
GimpOperationLayerMode's process() function. (Well, actually, this
commit keeps the ops around, and just hacks around them in
gimp_layer_mode_get_operation(), because laziness :P)
Keep using the layer's is_last_node property to do the invalidation.
Takes a layer mode and a composite mode, and returns the region
included in the composition.
Use this function in GimpOperationLayerMode, instead of testing
for specific composite modes directly. Will also be used by
the next commit.
Indentation cleanup in gimp_layer_modes.h
... so that we can use it for other functions that involve
compositing regions (which we do in the next commit).
Rename gimp_operation_layer_mode_get_affect_mask() and
friends to _get_affected_region().
Commit 9d4084c82f skips conversion and
blending of (some) transparent source and destination pixels. When
`blend_out == blend_layer`, it banks on the fact that the alpha values
of `blend_out` would be the same as those of `blend_layer`, and hence
the same as those of `layer`; thing is, we only copy those values from
`layer` to `blend_layer` for the pixels that we *don't* skip, so this
assumption is just wrong :P This leaves us with bogus alpha values in
`blend_out` for the skipped pixels, when the above equality holds.
For composite modes that use the alpha values of `blend_op` (aka `comp`)
even for transparent input pixels (i.e., src-atop and src-in), this may
result in artifacts.
Fix this by simply initializing the alpha values of `blend_out` for
skipped pixels unconditionally.
... since that's the color space it actually works in.
Keep the legacy "Color (HSV)" mode's name as is, wrong as it is,
since, well, that's what it used to be called...
No need to do full back and forth RGB/HSV conversions.
Change the behavior such that fully desaturated values remain
desaturated, instead of saturating towards red.
Pixels whose source or destination alpha is zero are not blended, and
therefore do not need to be converted between the composite and blend
spaces (assuming a conversion is necessary to begin with.) When there
is a large enough segment of consecutive pixels that don't need
blending, split the conversion/blending process around it, so that
we don't convert too many unblended pixels unnecessarily.
For layers with lots of transparency, this can dramatically reduce
compositing time; for layers with no transparency, the added
overhead is rather negligible.
Merge mode lays the source layer on top of the destination, same as
normal mode, however, it assumes the source and destination are two
parts of an original whole, and are therefore mutually exclusive.
This is useful for blending cut & pasted content without artifacts,
or for replacing erased content in general.
Calculates the dot product of the two input colors, and uses that
as the value for all the output color's components. Basically,
a per-pixel mono mixer.
Useful for custom desaturation, component extraction, and crazier
stuff (bump mapping!)
... possibly due to small win32 stack
Limit the number of samples processed in one go by gimp_composite_blend()
so that we don't overflow the stack when we alloca() buffers on it.
... and get rid of the dedicated op. This gives us support for all
the blend/composite options for this mode.
Rename COLOR_ERASE to COLOR_ERASE_LEGACY, with perceptual blending/
compositing and immutable everything, and add a new COLOR_ERASE
mode, defaulting to linear blending/compositing, with mutable
everything. Modify affected code.
These are more general, and more expensive, versions of the non-
subtractive compositing functions. They are used with modes that
specify the SUBTRACTIVE flag. This doesn't affect anything yet, but
the next commit ports color-erase mode to a blendfun.
Instead, add a gimp_layer_mode_get_format() function, which takes
the layer mode, composite space, and blend space, and returns the
I/O format.
Currently, we always use the composite space format as the I/O
format. This simplifies gimp_composite_blend(), and gives us
composite-space support for the "special" layer mode ops for free.
They can be affected by the same problem described in
commit 4c3a772cd8, although in the
case of SRC_ATOP, the affected pixels are always fully transparent.
When the source alpha is zero, we don't calculate the blended color,
so `comp[b]` can be infinite or NaN, in which case the expression
`in[ALPHA] * (comp[b] - layer[b])` is NaN, rather than the expected
value of zero.
and to operations/layer-modes/, respectively.
Add gimp_layer_modes_init() which asserts on the correct order of the
GimpLayerModeInfo array, and switch to accessing the array directly in
gimp_layer_mode_info().
Similar to the Photoshop mode of the same name. Assigns
either 0 or 1 to each of the channels, depending on whether the
sum of source and destination channel values is less than, or
greater than (or equals to), one, respectively.
This is equivalent to inverting the source, and using it to perform
per-pixel, per-channel threshold against the destination, which is
useful for various effects.