feat: grade a sparse window's polyline by slope, so phosphor does not switch off on zoom

Intensity grading was gated on the column reduction, which is gated on a
density whose only job is killing the moire beat. Dwell has nothing to do
with that, so narrowing a window past the threshold turned the whole
phosphor model off and a discontinuity went from a third of a flat top's
ink to all of it in one pixel of zoom.

stage_trace_slopes() grades each segment by its own slope instead, with a
measure that agrees with the dense path at the boundary, and reports
itself as FrameStats::slope_traces -- disjoint from column_traces, so a
host asserting graded_traces == column_traces reads the same as before.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-10-08 16:56:10 +02:00
1 parent cc908efa36
commit 37e414bcc5
8 files changed
+442 -13

No files matched your search

+10 -3
View File
@@ -41,11 +41,18 @@ ctest --test-dir build/debug --output-on-failure
ctest registers four tests: `plot_tests` (the test binary), the two header/umbrella build
checks (`plot_headers_self_contained`, `plot_umbrella_covers_public_headers`) and
`plot_umbrella_check`. The `plot_tests` binary itself runs **350 cases** in the `linux-debug`
preset; its harness prints one line per case and a final `350 cases, 0 failed` summary line.
`plot_umbrella_check`. The `plot_tests` binary itself runs **377 cases** in the `linux-debug`
preset; its harness prints one line per case and a final `377 cases, 0 failed` summary line.
The case counts per file are the `PLOT_TEST(...)` declarations under `tests/` — recount them
(`grep -c '^PLOT_TEST(' tests/test_*.cpp`) after adding or removing cases.
`PLOT_TEST_FILTER=<substring>` runs only the cases whose name contains that substring, and
is for working *on* a case rather than for checking the library: most of the render cases
create their own EGL context and read pixels back, so the whole binary is far slower than
the one case being edited and its one line of measured output scrolls past 376 others. The
summary line still counts the whole suite, so a filtered run says `377 cases, 0 failed`
having run one — it is never evidence that the suite passes. Unset, every case runs.
## Install layout
`cmake --install` follows `GNUInstallDirs`, so every path honours the standard cache
@@ -119,7 +126,7 @@ per-file table and the floor verdict live in [docs/coverage.md](coverage.md), wh
`tools/coverage.sh` rewrites from the very run that measured them. Re-run the command for the
live numbers.
**One thing to know about the coverage preset:** it builds **333 of the 350 cases**. The 17
**One thing to know about the coverage preset:** it builds **360 of the 377 cases**. The 17
that are missing are the adapter cases that need an adapter target to exist — 11 in
`test_imgui_widget.cpp` and 6 in `test_glfw_host.cpp` — and the coverage preset turns the
adapters off. The toolkit-free adapter seams still run there: `test_qt_pointer.cpp` (5 cases)