Commit Graph
10 Commits
Author SHA1 Message Date
RickiNano 265fedc687 Merge remote-tracking branch 'origin/main' into fix/windows-pen-eraser-end-2285
# Conflicts:
#	apps/photocraft/src/tablet.rs
#	crates/tablet/Cargo.toml
#	crates/tablet/src/lib.rs
#	crates/tablet/src/windows.rs
#	crates/ui-egui/src/lib.rs
#	crates/ui-egui/src/services.rs
#	docs/hardware-parity.md
2026-11-06 19:53:07 +01:00
RickiNano 1aa85bd796 Windows: the pen's eraser end selects the Eraser (#2285)
The pointer hooks read PEN_FLAG_INVERTED from GetPointerPenInfo and
report the pen end through Services::pen_end, so flipping the pen
switches to the Eraser and the tip restores the previous tool, as on
macOS. A WH_CALLWNDPROC hook beside WH_GETMESSAGE catches
WM_POINTERLEAVE, which Windows documents as sent, not posted.
PEN_FLAG_ERASER alone is an eraser button on the barrel and does not
switch tools.
2026-11-06 19:45:17 +01:00
f23d173933 Add an opt-in WinTab backend for pen pressure on Windows (#11331)
* Add an opt-in WinTab backend for pen pressure on Windows

Windows Ink stays the default. Preferences > Tools > Pen Tablet has a Tablet
input dropdown (Windows Ink (default) / WinTab). WinTab opens a WinTab 1.4
system context on PhotoCraft's window and polls pressure and the eraser end
(tilt on devices that report orientation axes; rotation only with a pen and
driver that report twist) into the stylus feed. The row says to turn Windows
Ink off in the tablet's software utility; the choice applies at next launch.

- crates/tablet: Windows-only wintab/wintab-sys backend. Devices with
  orientation axes use the orientation packet; pressure-only devices open a
  packet without it and report neutral tilt. Leaving is the driver's hardware
  proximity message (WT_PROXIMITY) and the packet's out-of-context status, with
  a long fallback for drivers that never report either. Overlap priority
  follows window focus, and the message hook requests a frame for each WinTab
  message so pressure-only strokes update without cursor movement.
- apps/photocraft: install the backend when the preference is on; poll it at
  the start of each frame; the installed wake repaints the UI.
- ui-egui: TabletPollFn service; the Windows-only Pen Tablet row with the
  Tablet input dropdown and the note.
- engine: tools.tabletInput (windowsInk/winTab), default windowsInk.
- docs: hardware-parity WinTab gap entry, qualifying tilt to orientation axes
  and rotation to twist-reporting pens.

Tested locally on a Wacom tablet with Windows Ink off: pressure, tilt and the
eraser end reach the brush (rotation where the pen reports twist); the default
path is unchanged.

* WinTab: a message that finds the state borrowed is skipped, not a panic in the hook

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

* WinTab: rustfmt

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

* Scorecard: count the Tablet input setting

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

---------

Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 18:39:40 +01:00
5c157e8400 Build the GPU compositor off the UI thread (#9969)
* Prepare GPU compositor in background

* Add compositor startup performance scenarios

* Generate scorecard in scratch CI

* Fix pipeline build type inference

* Address compositor startup review and document measurements

* Run startup performance checks on scratch CI

* Remove scratch performance job

* Count failed GPU attempts in frame timing

* Make shader fingerprint test portable

* Address review: run first-document scenario as a guarded group; share COMPOSITOR_BUILDING constant

* Handle compositor startup benchmark failures

* Fix frame timing after upstream merge

* Keep GPU startup failures on CPU fallback

* Record the failed GPU attempt of a deferred redraw, and bound --reps

A redraw deferred after a failed GPU composite carries that attempt's time to its end, where it is
recorded once beside the CPU time. Perf::record clears the attempt so a direct CPU refresh doesn't
inherit the last one's. perf_scenarios caps --reps.

* Refresh cached canvases after compositor build

* Expose canvas cache key to GPU completion handler

* ci: drop the GPU compositor probe job

AGENTS.md: feature and fix PRs don't add or change CI, and app workflows
only call the shared craft-common-actions workflows. The probe example
stays as a manual tool (cargo run -p photocraft-gpu --example
compositor_build_probe).

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

---------

Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 22:49:12 +01:00
a222c2aee4 Integration: Calibration keeps the Camera Raw preview on the CPU develop (#5128, #6923)
#6923 develops the Camera Raw dialog's preview on the GPU whenever no spatial stage is set,
from `per_pixel`'s stages. #5128 adds Calibration (primaries and Shadows tint) to the CPU
develop between white balance and Dehaze, which those stages don't run, so with both merged
a Calibration-only change previewed unchanged on the GPU while Open applied it. `per_pixel`
now returns None when Calibration is set, so the dialog develops on the CPU then. The
white and black points stay as they were, so the dialog's points cache is still right once
Calibration goes back to neutral. The hardware parity doc and BUG-204-3's note now say so.

Co-authored-by: Fabio Lissi <3223836+FabioLissi@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 13:12:57 +01:00
7a70220777 Integration: one gpu test binary, no GPU pass for neutral settings (#6923)
- crates/gpu/tests/camera_raw.rs was its own test binary taking
  testkit's gpu_lock; since #8644 the crate's integration tests are one
  binary (tests/it) sharing crate::GPU_LOCK, so in that binary it would
  open a device next to the other modules. Moved into tests/it with
  GPU_LOCK; the testkit dev-dependency goes.
- Default (neutral) settings uploaded, rendered and read back the proxy
  although the CPU develop returns at once. CameraRawGpu::develop now
  leaves them to the CPU; neutral_settings_skip_the_gpu_round_trip fails
  without it (backend "gpu").
- docs/hardware-parity.md: the CPU range was one backend's (21-28 ms);
  measured 11-16 ms on an RTX 5070 Ti, so 11-28 ms, machine-dependent.

Co-authored-by: p0rps <134095787+fjamesprice@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:45:52 +02:00
fjamespriceandClaude Opus 5.5 49df3fb921 perf(camera-raw): develop the preview's per-pixel stages on the GPU (#6916)
Step 1 of #6916: one wgpu fragment pass for develop's per-pixel stages
(white balance and exposure, Contrast without Texture or Clarity, Whites
and Blacks, Vibrance and Saturation, tone curves, Color Mixer, Color
Grading, vignette, grain in full-resolution coordinates).

- algo: camera_raw::per_pixel resolves those stages' constants and
  tables; the CPU develop builds its own from the same functions, so its
  output is unchanged bit for bit.
- gpu: CameraRawDevelop (camera_raw.rs, camera_raw.wgsl), curves and
  Whites/Blacks rows in one R32Float table texture, readback for the
  histogram and scopes. Built on demand, not with the compositor (#6419).
- ui-egui: the proxy worker develops on the GPU when the settings have no
  spatial stage; Rendering Mode CPU, no GPU canvas, a software adapter, a
  fault or a failed develop use the CPU develop. The pipeline builds on a
  thread at the first open. describe() reports developMs and
  developBackend.

GPU vs CPU at 8, 16 and 32 bits: at most 2.7e-5 (RTX 5060 Ti, Vulkan and
DX12), 6.7e-6 (WARP); tests hold 1/4096. 858x572 proxy, release: CPU
20.7-28.1 ms, GPU 2.7 ms.

Part of #6916.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 11:10:13 -04:00
Ernie SmithandClaude Sonnet 5.5 0e97ac4ca8 Make adapter choice Linux-only everywhere, not just the dropdown
The Preferences row was Linux-only, but PHOTOCRAFT_GPU_ADAPTER and
performance.gpuAdapter were honoured on every platform, so Windows and macOS
could pick a non-default adapter without being tested for it. Ignore the
request off Linux (and in CPU mode, as before), and don't make a launch
standalone for a variable that is ignored there.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 16:19:51 -04:00
Ernie SmithandClaude Sonnet 5.5 b892c0412e Choose the graphics adapter on multi-GPU Linux machines (#1885)
With the backend on auto, Linux installed no adapter selector, so wgpu took
the first discrete GPU the driver listed. On a machine with an eGPU, a
laptop dGPU and an iGPU that was not the one the user wanted.

- performance.gpuAdapter: a case-insensitive piece of the adapter's name
  (several words must all appear); empty is automatic.
- PHOTOCRAFT_GPU_ADAPTER overrides it for one launch.
- Preferences > Performance > Advanced > GPU adapter lists the adapters the
  instance found; a saved adapter that is absent stays listed, marked.
- A missing adapter, or one that can't present to the window, falls back to
  the automatic choice with a note in System Info. CPU mode ignores it.
- Shown on Linux only; tested on Linux only. Windows and macOS need their own
  work (the startup code honours the setting there, but it is untested).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 13:16:53 -04:00
Brandon ThomasandClaude Opus 5.5 939c8f2c70 Progress docs: target-app parity, gaps, alpha gate, readiness by audience (#2696)
Progress docs per craftrules standards/progress-docs.md: target-app parity (merges parity-estimate.md), gaps, roadmap with alpha gate, readiness by audience (full / mainstream / essentials) with Opus 5.5 hours, and UI, brush, format, hardware and localization parity docs. docs/parity.md is now docs/parity-checklist.md.

The Windows test failure (file_dialog::tests::save_dialogs_remember_where_each_document_was_last_saved) is pre-existing on main: the test hard-codes POSIX paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:09:04 -04:00