Commit Graph
281 Commits
Author SHA1 Message Date
FredApps b63c6e00a6 Merge approved PhotoCraft PR #4711: Treat Dissolve as a per-pixel choice
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Current modular compositors already implement spatial Dissolve for adjustments and finished effects. Preserve equivalent implementations and newer Fill/HDR behavior, append approved missing CPU/GPU regression coverage.
2026-10-29 06:11:42 +01:00
FredApps 2ab2348adf Merge approved PhotoCraft PR #4992: Preserve Dissolve coverage when compositing clipped layers
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Current CPU and GPU already implement binary clipped Dissolve at document coordinates. Preserve current equivalent implementation and stronger negative-origin/depth regression; retain original named regression and added GPU parity coverage.
2026-10-29 06:08:48 +01:00
FredApps 8323688e1f Merge approved PhotoCraft PR #5453: Shapes: independent fill and stroke paints (solid, gradient, pattern), part 1
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Integrated independent exact shape paints and atomic pattern clipboard snapshots into current modules, preserving current soft-mask coverage, shape cache keys and gradient stop caps. Shared bounded COW pattern sampling now retains minification filtering; shapes/clipboards resolve lazy catalog entries to full pixels. Preserved CPU/GPU/depth/model regression matrices; also corrected missing glow-test enum imports found by the 80-head check.
2026-10-29 05:53:29 +01:00
FredApps 78f9c137b3 Merge approved PhotoCraft PR #6621: Crop: right-click on the pending crop opens the crop menu (#6561)
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Extended current crop menu with Reset and shield toggles, preserving newer preset management, overlays, ownership checks and no-menu-during-gesture logic. Ported reset-frame no-op/undo semantics into current CropState/release and crop commit; retained original regression cases in split modules.
2026-10-29 05:29:44 +01:00
FredApps 55bcfaed35 Keep one registered copy of the preserved outer glow regression 2026-10-29 05:25:00 +01:00
FredApps f369874ddb Merge approved PhotoCraft PR #8039: Compose: Extend Softer outer glows past Size (#7899)
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Added bounded Softer outer-glow tail in current CPU paint and GPU glow-builder modules, retaining original tent convolution and current program dispatch; registered exact tail/kernel regression and expanded render margin only for outer Softer glows.
2026-10-29 05:24:44 +01:00
FredApps d98e419542 Merge approved PhotoCraft PR #5176: Play CopyCat, AJ and Line and Color action sets; keep patterns across restarts; Shift Edge scale
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Ported mappings and smart Save into current modules, preserving bounded authorized playback; migrated legacy PAT by committing validated per-pattern assets before atomic authoritative index; preserved same-ID replacements and builtin edits; added temporary-store interruption, corruption, duplicate ID/name and restart regression coverage. Current all-target compilation passed before final ownership guard refinement; focused tests pending.
2026-10-29 05:15:28 +01:00
FredApps e0bca6baf6 Use explicit float mask format in combined Fill parity regression 2026-10-29 05:02:27 +01:00
FredApps 6c225b13c3 Merge approved PhotoCraft PR #5010: Layer Style: Photoshop's layout (three columns, OK/Cancel/New Style/Preview on the right, one-line rows) [depends on #4938]
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Port responsive three-column Layer Style with owned right-side actions, preserve saved defaults/Blend If and current Curves/modal routing, and keep all original layout/Cancel tests registered.
2026-10-29 04:36:06 +01:00
FredApps 31ce2208b8 Merge approved PhotoCraft PR #9589: fix(compose, gpu): an adjustment layer's This Layer range judges its result before Opacity
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Judge Blend If using the adjustment result before Opacity and masks in CPU/GPU, with the original regression in the current test module.
2026-10-29 03:55:55 +01:00
FredApps 29804c5221 Merge approved PhotoCraft PR #9512: fix(compose, gpu): adjustment layers apply Fill inside the special eight blend modes
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Combine Fill-aware adjustment blending with stable HDR coverage and add cross-feature CPU/GPU regression matrix.
2026-10-29 03:54:31 +01:00
FredApps 369abd15c9 Merge approved PhotoCraft PR #9595: fix(compose, gpu): a Pass Through group with Blend If renders isolated
Port unchanged PR hunks to their unique current module locations after upstream file splits.
2026-10-29 03:37:02 +01:00
FredApps 23a0d5b662 Merge approved PhotoCraft PR #9584: fix(compose, gpu): Blend If hard points match Photoshop at 16 bits and for Gray
Port unchanged PR hunks to their unique current module locations after upstream file splits.
2026-10-29 03:36:59 +01:00
FredApps cfc24243aa Merge approved PhotoCraft PR #8903: Box-filter minified patterns in the CPU and GPU samplers (#8831)
Port unchanged PR hunks to their unique current module locations after upstream file splits.
2026-10-29 03:36:41 +01:00
FredApps e4e75d0e2b Merge approved PhotoCraft PR #9110: test: GPU tests honour WGPU_BACKEND, so they run on Windows with an Intel GPU (#4) 2026-10-29 03:29:47 +01:00
aiongg 2b1c6b93c3 Merge main into split-filter-adjust-crop-fx-builders
crop_ui.rs moved to tools/; the PR's builders replace main's Clippy extractions of the same code; #6723's Color Lookup save carried into the moved encoder.
2026-10-28 04:22:40 +00:00
Dylan M. Taylor ab9b27b80d Restore rationale comments dropped by the Clippy refactors 2026-10-28 02:13:42 +00:00
Dylan M. Taylor 6ebc0180da Refactor gpu for strict Clippy checks 2026-10-27 23:47:06 +00:00
aiongg 6e9fb30dbc Merge #6723: Color Lookup: PSD save keeps a .3dl/.look LUT file as loaded (#6544) 2026-10-27 17:44:05 +00:00
aiongg 01594f1f25 Merge #5890: PSD: Frame layers keep their stroke (#4381) 2026-10-27 17:44:01 +00:00
David Mann 3e15ea9eb9 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/compose/src/adjust.rs
#	crates/gpu/src/plan.rs
#	crates/io/src/adjust_map.rs
2026-10-27 14:19:34 +01:00
David Mann 2363c475c0 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/compose/src/lib.rs
#	crates/gpu/src/plan.rs
2026-10-27 14:17:25 +01:00
David MannandClaude Opus 5.5 c81e15cd24 Merge main into fix/5692-tsl-off-blend
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 03:07:51 +01:00
aiongg 7ba8fdc79f refactor(gpu): split plan.rs into plan/ 2026-10-26 22:54:56 +00:00
aiongg 81c83b124f refactor(gpu): split lib.rs into batch, cells, consts, convert, encode, fx_passes, kit, paging, readback, setup, textures 2026-10-26 22:54:56 +00:00
aiongg 2d248b9ade refactor(gpu): move fx.rs tests to fx/tests.rs 2026-10-26 22:30:14 +00:00
aiongg 78d947d51a refactor(gpu): move lib.rs tests to tests.rs 2026-10-26 22:30:14 +00:00
aiongg bfb3ca12f2 refactor(gpu): move plan.rs tests to plan/tests.rs 2026-10-26 22:30:14 +00:00
David Mann 7e4ceba5df Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/cms/src/lutfile.rs
2026-10-26 14:26:50 +01:00
Hector VillarrealandClaude Opus 5.5 75fa71a4f5 fix(compose, gpu): a Pass Through group with Blend If renders isolated (#9554)
A Pass Through group composites its children straight into the
backdrop, so an Invert inside it changed the layer beneath even when
the group had Blend If. Photoshop renders such a group isolated, as it
does below 100% Fill: the backdrop stays (64,128,192) under a group
holding an Invert with Red Underlying white at 110. The CPU and GPU
pass-through shortcuts are now skipped for a group with Blend If.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 21:20:48 -06:00
Hector VillarrealandClaude Opus 5.5 da15794507 fix(compose, gpu): an adjustment layer's This Layer range judges its result before Opacity (#9542)
Blend If on an adjustment layer judged This Layer by the composite after
Opacity and the mask had mixed the result into the backdrop. Photoshop
judges the adjustment's result itself: Invert at 40% over (64,128,192)
with Red This Layer black 150 keeps the effect, (115,128,140), as
Invert's red 191 passes 150. The CPU and the GPU now apply the
adjustment to the backdrop and judge that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 20:48:06 -06:00
Hector VillarrealandClaude Opus 5.5 fc0f7b1132 fix(compose, gpu): Blend If Gray uses Photoshop's weights and rounding (#9522)
Gray was Rec. 601 luma, unrounded, so mixed 8-bit colours near a hard
Gray point landed on the wrong side: (123,126,151) read 127.95 and was
hidden by a black point at 128. Photoshop's Gray, measured on pure
channels at three cutoffs, is (30R + 59G + 11B) / 100 rounded half down
on whole levels; it keeps both of the reporter's colours.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 20:20:50 -06:00
bf3ff9ce60 Integration: Camera Raw GPU tests fail on a shader that doesn't build (#6923)
The tests' setup returned None, without a message, when the device
request or the pipeline build failed, so every test passed early: with
a type error appended to camera_raw.wgsl all 13 tests still passed on a
machine with a GPU. A pipeline that doesn't build on a supported adapter
now fails the tests, a missing device skips with a message (and fails
with WGPU_BACKEND set, as in parity.rs), and a naga validation of the
shader fails on runners without a GPU too.

Found by CodeRabbit on #9386.

Co-authored-by: p0rps <134095787+fjamesprice@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 21:56:01 +01:00
Hector VillarrealandClaude Opus 5.5 d6a1f7cbc5 fix(compose, gpu): Blend If compares 16-bit values on Photoshop's 0..32768 steps (#9521)
A hard Blend If point at level c sits on Photoshop's 16-bit step
round(c * 32768 / 255), inclusive for black and white points (measured
at 1, 64, 128 and 200). blend_if_level snapped only within 1e-4 of a
whole level, so RGB16 32895 (level 128's step) read 127.996 and was
hidden by a black point at 128. A value on its nearest level's step is
now that level, on the CPU and the GPU; 8-bit levels are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 13:39:24 -06:00
Hector VillarrealandClaude Opus 5.5 6c55561128 GPU: a clipped adjustment takes Fill as coverage, as on the CPU
CodeRabbit on #9512 (inline 4371923258): the planner's clipped path
(atop_any) took the special eight's separate Fill too, while compose's
clipped branch (composite_atop) uses opacity × Fill as coverage, so a
clipped adjustment at partial Fill rendered differently on the GPU (53
levels off at 30% Fill). The clipped path now uses combined coverage.

Test: special_eight_fill_on_adjustment_layers_matches_cpu (adds a clipped
adjustment for each mode and Fill)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 12:48:03 -06:00
Hector VillarrealandClaude Opus 5.5 cd39cdc75c fix(compose, gpu): adjustment layers apply Fill inside the special eight blend modes (#9501)
Below 100% Fill, Photoshop blends Color Burn, Linear Burn, Color Dodge,
Linear Dodge, Vivid Light, Linear Light, Hard Mix and Difference with
the source pulled toward the mode's neutral colour, at Opacity. Pixel
layers already did (psblend::composite_fill); adjustment layers used
Fill as coverage on the CPU (blend_back) and the GPU (AdjMix), so a
40% Fill Color Dodge gave (90,179,217) instead of (80,160,240).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 12:24:50 -06:00
David MannandClaude Opus 5.5 14693eb085 Integration: merge main 528491f9a, resolve conflicts
- crates/engine/src/edit_cmds.rs: copy_mask keeps #3297's filter-mask target and takes main's
  clipboard `source` (#8945).
- crates/cms/src/lutfile.rs: #9183's shaper doc comment next to main's UTF-16 decode_text (#9129).
- contributors/people.toml, docs: unions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 16:26:06 +01:00
05246233b6 Kept composites follow the text gamma and free their memory; GPU timing survives an OOM retry (#8520, #8521) (#8522)
* Background redraw: key kept composites on the text gamma, trim them every frame (#8520)

Two gaps in the kept background redraws:

- Color Settings > "Blend Text Colors Using Gamma" is an application
  setting that type layers composite with, but it wasn't part of the key.
  After toggling it, going back to a kept state (an Alt-click solo and
  again, undo/redo) uploaded type edges drawn with the old gamma. The key
  now holds the gamma, and a redraw that ran while the gamma changed
  (even if changed back, and also while another document was shown)
  isn't kept. Every running redraw is checked every frame; two changes
  within one frame aren't seen.
- Kept composites were trimmed only when the next deferred redraw
  started. A state History dropped (or purged) kept its texels, and
  lowering Memory Usage or a small edit that grew a kept document didn't
  release them. Each frame now drops dead entries, and the cap is taken
  again when Memory Usage or the revision of any kept document changes.

Tests (each fails without its part of the fix):
a_state_drawn_before_the_text_gamma_changed_is_composited_again,
a_redraw_across_a_text_gamma_change_is_not_kept,
a_redraw_across_a_text_gamma_change_and_back_is_not_kept,
a_hidden_documents_redraw_across_a_text_gamma_change_and_back_is_not_kept,
kept_composites_go_when_memory_usage_drops_between_redraws,
kept_composites_go_when_a_small_edit_grows_the_document_past_the_cap,
an_older_kept_composite_goes_when_its_document_grows_past_the_cap,
a_kept_state_history_purged_goes_at_the_next_frame.

Co-authored-by: Michael Higgins <55243596+Higgs32584@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* GPU compositor: test the layer page out-of-memory paths, keep GPU timing after one (#8521)

The PR's tests passed with its fix reverted: main's after-cell evict()
already meets every assert of the zero-budget test, so the out-of-memory
fallback had no test. A test hook (Compositor::fail_layer_allocs) now makes
the next n page textures fail as out of memory, and a parity test covers
the in-place retry, the submit-and-retry, the CPU fallback with a healthy
device, and the next refresh back on the GPU. Each of those fails when its
part of the fix is removed.

A retry that failed after its submit also switched GPU timing off for the
rest of the session: the submit marks the measurement flushed, and
cancelling a flushed measurement stops timing for good. The retry waits
for the GPU, so it now clears that mark (GpuTimer::drained);
an_out_of_memory_refresh_does_not_stop_gpu_timing fails without it.

Co-authored-by: Michael Higgins <55243596+Higgs32584@users.noreply.github.com>
Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Address CodeRabbit review: serialise the OOM timing test with GPU_LOCK

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Michael Higgins <55243596+Higgs32584@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
2026-10-25 10:19:25 -04:00
David Mann 42b17b1836 Merge PR #6923: perf(camera-raw): develop the preview's per-pixel stages on the GPU (#6916) 2026-10-25 10:14:10 +01:00
David Mann 23d8f053cb Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/compose/src/shape_split.rs
2026-10-24 03:12:55 +02:00
David Mann feb20ebc60 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/gpu/src/plan.rs
#	crates/io/src/adjust_map.rs
2026-10-24 02:59:10 +02:00
Kushagra Sharma 2e716f93b2 test: GPU tests honour WGPU_BACKEND, so they run on Windows with an Intel GPU (#4)
Loading the Intel Vulkan driver on Windows (igvk64.dll) crashes the process
with STATUS_ACCESS_VIOLATION (#4). The app leaves Vulkan out on Intel, but
the tests use wgpu's defaults, so on such a machine `cargo test` dies in the
first GPU test (ui-egui's background_redraw, adjust_preview_gpu, ...).

WGPU_BACKEND=dx12 avoids it for the kittest harnesses, but seven tests and
four benches built their instance with wgpu::Instance::default(), which takes
every backend and ignores the environment. They now use
InstanceDescriptor::new_without_display_handle_from_env(): the same defaults
with WGPU_BACKEND and friends applied, so nothing changes where it is unset.

Document the workaround in docs/development.md and the testkit driver notes.
2026-10-23 17:43:05 -05:00
David Mann 8c04b175ec Merge remote-tracking branch 'origin/main' into integration-batch-7
# Conflicts:
#	crates/automation/src/rpc.rs
#	crates/automation/src/server.rs
#	crates/gpu/src/health.rs
#	crates/text/src/tests.rs
#	crates/ui-egui/src/i18n/zh-hans.tsv
#	crates/ui-egui/src/panels.rs
#	docs/control-protocol.md
#	docs/ui-parity.md
2026-10-24 00:23:15 +02:00
FinnNkandClaude Opus 5.5 89d127d259 fix(curves): 32-bit Curves continue past 0..1 like Photoshop (#8782)
* fix(curves): 32-bit Curves continue past 0..1 like Photoshop

In a 32-bit RGB document an edited Curves clipped every sample to the
curve's table, so HDR values above 1 (and negative ones) were flattened.
Photoshop extends the curve beyond its end points along its end segments:
the straight curve [[0,0],[255,128]] maps -0.5, 0.5 and 2 to
-0.250980407, 0.250980407 and 1.003921628 (measured in Photoshop 27.11 on
the issue). The CPU compositor, Image > Adjustments and the GPU kernel
now do the same, with the end slopes measured over 16 table steps.
8/16-bit documents and unedited curves are unchanged.

Fixes #7157

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(curves): extend 32-bit curves in RGB documents only

The curve's space is not the document's: a grayscale, CMYK or Lab
32-bit document with an RGB-space curve keeps the table's ends. The
document mode now reaches the decision on the CPU (apply_in, the
compositor) and the GPU (adjustment_program).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:40:56 -04:00
HEOJUNFOandClaude Opus 5.5 44db720b22 Black & White: keep 32-bit superwhites (#8537) (#8748)
The grey was clamped to 0..1 at every depth, so a 32-bit (2, 2, 2) came
out as (1, 1, 1). In 32-bit documents it now clamps to 0..16, as
Photoshop 27.11 does; 8 and 16-bit still clip at 1. CPU and GPU both.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-23 17:40:00 -04:00
FinnNkandClaude Opus 5.5 c06dd9c27c fix(gpu): rebuild the GPU canvas after an out-of-memory error (#8774)
* fix(gpu): rebuild the GPU canvas after an out-of-memory error

An uncaptured wgpu error of any kind dropped the GPU canvas for the rest
of the session, so one recoverable Out of Memory on a working device
left every redraw on the CPU until Retry GPU. Dropping the canvas frees
its memory, so after an out-of-memory error a new GPU canvas is now
built at once on the same device, with a fresh health flag and no
dialog, up to three times a session; past that the CPU renderer and the
Retry GPU dialog stay as before. Validation errors and device losses
are unchanged.

Fixes #6564

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(gpu): only wgpu's out-of-memory error is retried

The fault is classified by wgpu's Error::OutOfMemory variant and recorded
as exactly "Out of Memory", so a validation error that mentions memory
keeps its fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(gpu): a later out-of-memory error replaces an earlier error

So the canvas still rebuilds itself when memory ran out after a
validation error in the same frame; a device loss still wins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:39:50 -04:00
Gert Pellin - GPE 10a20743ea Soft Light: dark backdrops follow Photoshop's W3C curve (#8804) (#8817)
* fix(blend): Soft Light uses the W3C curve over dark backdrops (#8804)

Photoshop's Soft Light moves the backdrop towards D(cb) in the upper half,
and D(cb) is the cubic ((16·cb − 12)·cb + 4)·cb below a quarter, not
sqrt(cb). With sqrt the Soft Light cell of psd-tools rgb-blend-modes.psd
was up to 20 levels too light over the dark rainbow; with the cubic it is
within 4 of Photoshop's merged image.

Same change in compose.wgsl so the GPU compositor stays at CPU parity.
Krita's own soft_light (the sqrt curve) now opens as the approximation and
svg:soft-light / krita:soft_light_svg as the exact match, without warning.

Fixes #8804

* compose: the see-through Soft Light test expects the W3C curve over a dark backdrop (#8804)

The #6232 test computed Photoshop's Soft Light of yellow as sqrt(b) for red and
green. Its backdrop #04170F is below a quarter in both channels, where the W3C
curve (Photoshop's, measured in #8804) uses ((16b - 12)b + 4)b instead.
2026-10-23 17:39:40 -04:00
kotulskyandkotulsky 8d1926433f Reuse filled-shape effect maps while moving styled groups (#8993)
* perf(gpu): reuse filled-shape effect maps during translation

Hash filled-shape outlines in local coordinates so whole-pixel movement can use the existing effect-map translation reuse path. Keep its region-size and exact coverage checks, and invalidate the key when the outline deforms.

Add a shape-key regression and a synchronized styled-shape group benchmark with fresh-render parity verification. On RTX 4070 Laptop, the 1600x1200 fixture improves from 61.336 to 33.120 ms median; a 24 MP full-canvas fixture improves from 223.018 to 184.289 ms. Warm frames rebuild zero effect programs, and the quick fixture matches fresh rendering exactly.

* fix(gpu): stabilize fractional shape effect fingerprints

Quantize only origin-normalized fingerprint coordinates to a 1/65536 pixel grid and canonicalize signed zero. Preserve the render path and exact coverage guard.

Cover fractional anchors and handles, positive and negative integer translations and handle deformation. Exercise fractional origins in the benchmark and document its entry points. All 40 GPU tests, Clippy and WASM checks pass; reused output matches a fresh compositor exactly.

---------

Co-authored-by: kotulsky <7805437+kotulsky@users.noreply.github.com>
2026-10-23 17:37:56 -04:00
aiongg 7aaa59712a Merge main into integration-batch-7 2026-10-23 20:37:05 +00:00
Dylan M. Taylor a09c0ce85f test(gpu): match the planning error instead of err().expect() 2026-10-23 15:21:47 -04:00