297 lines
18 KiB
Markdown
297 lines
18 KiB
Markdown
# STEP20C temporal rendering and damage probe
|
||
|
||
**Status: EXPERIMENTAL / PROTOCOL RECORDED BEFORE FIXTURE.** This probe uses
|
||
private headless binaries only. STEP20C remains **NEXT** and multi-output
|
||
Mosaic remains **NOT YET SUPPORTED**. No UX, production ABI, package or
|
||
transaction contract is changed here.
|
||
|
||
**Measured verdict: PARTIALLY_FEASIBLE for the sampled temporal matrix.**
|
||
The stabilized visual and lifecycle assertions passed in the runs below;
|
||
frame-by-frame presentation, full input/render synchronization and native
|
||
transaction generation remain unproven.
|
||
|
||
## Question and prior evidence
|
||
|
||
The [negative-origin probe](STEP20C_NEGATIVE_ORIGIN_NESTED_GRAB_PROBE.md)
|
||
found sampled popup clipping and hit testing feasible at stable positions.
|
||
It did not capture every presented frame or prove SceneFX damage sufficiency.
|
||
This probe asks whether repeated XDG lifecycle and camera transitions expose
|
||
stale pixels, wrong input targets or scene/IPC disagreement. A successful
|
||
settled screenshot cannot establish correctness during the transition.
|
||
|
||
## Fixed geometry and three configurations
|
||
|
||
HEADLESS-1 is `(-800,0,800,600)`, HEADLESS-2 is `(0,0,800,600)`, scale 1,
|
||
transform normal, global bounds `[-800,800) × [0,600)`. PNG coordinates are
|
||
output-local: HEADLESS-1 local X is global X plus 800, HEADLESS-2 local X is
|
||
global X. The virtual pointer receives `sent_x=global_x+800` with extent
|
||
`1600×600`; client enter/button events validate actual targeting.
|
||
|
||
| Mode | Binary | Layout | Camera |
|
||
| --- | --- | --- | --- |
|
||
| A | unmodified `/usr/bin/sway` | `splith` | N/A |
|
||
| B | private Mosaic with private SceneFX | `splith` | N/A |
|
||
| C | same private binary, clip and owner guard | `mosaic` | 400 ↔ 1280 |
|
||
|
||
Each run uses its own mode-0700 runtime, discovered private Wayland display,
|
||
explicit `swaymsg -s` socket, bounded children and two-output captures. The
|
||
daily session socket is excluded from the subprocess environment. The
|
||
ordinary layout controls compare common XDG creation, input and destruction;
|
||
they have no invented camera counterpart.
|
||
|
||
## Hypotheses and XDG lifecycle
|
||
|
||
H1: hiding the fully off-viewport tiled owner removes its popup pixels.
|
||
H2: camera return restores the same mapped A/B objects without old-position
|
||
pixels. H3: after B then A are destroyed, their former regions show the
|
||
underlying surfaces. H4: applied scene, clip, IPC and pointer targets agree
|
||
at observed transitions. H5: SceneFX invalidates the regions actually changed.
|
||
H6: private `splith` does not regress against unmodified SwayFX for common
|
||
XDG transitions. H7: repetition produces no crash, protocol error, surface
|
||
accumulation or ghost pixels. Each hypothesis receives its own verdict.
|
||
|
||
TOPLEVEL → POPUP_A → POPUP_B is a real parent chain with distinct `wl_surface`,
|
||
`xdg_surface` and `xdg_popup` objects. Opening A uses a fresh TOPLEVEL button
|
||
serial; opening B uses a fresh A button serial. Every popup gets role
|
||
configure, `xdg_surface` ack, then buffer map. Explicit close destroys B
|
||
first; A is destroyed after B. An outside click may deliver `popup_done`
|
||
B then A and has a different expected outcome from camera hiding without a
|
||
click. Serial values are per run, never constants.
|
||
|
||
## State and observation boundaries
|
||
|
||
The logical Mosaic `scroll_x` in IPC is distinct from Sway pending/current
|
||
container geometry and from the applied scene position. The owner applied
|
||
rectangle, clip log and sampled PNGs must corroborate scene placement. An IPC
|
||
success reply proves command acceptance, not presentation. The current
|
||
private probe exposes no native transaction generation. `SPIKE_DAMAGE`
|
||
records an output-local damage **bounding extent** before scheduling a frame
|
||
and adding to the damage ring; it is neither an exact region decomposition nor
|
||
proof of a presented frame. Any experimental counter must be labelled local.
|
||
The run preserves monotonic action/capture times, IPC trees, pointer/client
|
||
events, compositor logs and PNG hashes. `grim` produces sampled screenshots;
|
||
it cannot guarantee capture of every presented frame or a fixed achieved
|
||
frequency. Damage-to-pixel matching is **PARTIAL** unless records can be
|
||
associated with the actual presented frame and capture.
|
||
|
||
## Predefined scenarios and observations
|
||
|
||
The initial target is ten complete stable cycles per mode, bounded by a
|
||
per-run duration and capture/byte limit. Each cycle gets a unique ID and:
|
||
|
||
| Phase | Action and expected evidence |
|
||
| --- | --- |
|
||
| S0 | no popup, verified outputs, static reference, IPC, two PNGs |
|
||
| S1 | real TOPLEVEL click, A grab/configure/ack/map, two PNGs |
|
||
| S2 | real A click, B grab/configure/ack/map, two PNGs |
|
||
| S3 | visible A/B, configured/applied positions, interaction without dismissal |
|
||
| S4 | C only: `scroll_x` 400 → 1280, fully hidden owner, A/B still mapped, no popup hit |
|
||
| S5 | C only: 1280 → 400, same XDG objects, visible pixels restored |
|
||
| S6 | explicit B close, A retained, formerly covered region restored |
|
||
| S7 | explicit A close or controlled outside dismissal, underlying rendering restored |
|
||
| S8 | no old popup objects, owner/client alive, prepare fresh serials |
|
||
|
||
Separate runs cover controlled outside-click dismissal and Mosaic → `splith`
|
||
with open popups. After stable cycles pass, target 15–20 camera back-and-forth
|
||
transitions with A/B open, first with observed stabilization and then with
|
||
rapid IPC requests. Record both request and observed states; coalescing is
|
||
not automatically a failure. A reproducible crash stops the loop for minimal
|
||
reproduction. Failed and inconclusive cases remain in the evidence.
|
||
|
||
## Image and damage analysis protocol
|
||
|
||
Use the nested client's solid SHM A-yellow `(224,192,32)` and B-green
|
||
`(32,208,160)` surfaces as known foreground. Establish stable reference
|
||
images of the background and formerly covered A/B rectangles before scoring.
|
||
Avoid dynamic `wev` text regions when comparing full pixels; any mask must be
|
||
defined before looking at anomalies. Cursor, decorations, text, effects,
|
||
capture compression and IPC/capture timing can create unrelated differences.
|
||
Record each PNG's dimensions, monotonic capture timestamp, SHA-256, phase,
|
||
output-local region of interest, exact popup-color count, whole-region diff
|
||
count, diff bounding box and anomalous local coordinates. Compare formerly
|
||
covered regions with the appropriate uncovered reference, not just the
|
||
decrease of an exact color. Keep signed global conversion separate.
|
||
|
||
For each transition, compare observed changed regions with time-ordered
|
||
`SPIKE_DAMAGE` extents for that output, then with the rendered result. A broad
|
||
damage extent alone is not a correctness failure; missing or late invalidation
|
||
requires synchronized evidence. When frame association is absent, mark H5
|
||
**PARTIAL** even if stabilized images are correct.
|
||
|
||
## Verdict rules and limits
|
||
|
||
Each assertion is `PASS` only with the required geometry, XDG serial and
|
||
lifecycle traces, mapped identities, client events, PNG pixels and process
|
||
status. `FAIL` requires a demonstrated invariant violation. `PARTIAL` means
|
||
some required observation exists but coverage or synchronization is limited.
|
||
`INCONCLUSIVE` means the fixture cannot identify the behavior; `NOT TESTED`
|
||
means it was not run. A zero process exit alone is never `PASS`.
|
||
|
||
The aggregate is **FEASIBLE for the sampled temporal matrix** only when all
|
||
executed required visual/input transitions pass, controls have no blocking
|
||
regression, and damage traces support only the precise claims made. Positive
|
||
stabilized images with incomplete frame/damage association are
|
||
**PARTIALLY_FEASIBLE**. A reproducible leak, protocol violation, destruction
|
||
defect or crash is **BLOCKED**. Unusable fixture or captures are
|
||
**INCONCLUSIVE**. Untested cells stay **NOT TESTED**. Scaling, rotation,
|
||
resize, migration, complete effects and ABI/package maintenance are outside
|
||
this experiment. No result authorizes production STEP20C or daily use.
|
||
|
||
## Measured campaign and retained evidence
|
||
|
||
The final instrumented lab is `/tmp/swayfx-mosaic-nested-grab-RbwDblky/`
|
||
with build log `/tmp/mtd-prepare-Rv5kR9sm`. It contains ten runs: ten
|
||
complete cycles each in unmodified SwayFX `splith`, private `splith`, and
|
||
private Mosaic; one extra private Mosaic pilot cycle; one camera run; outside
|
||
click runs in all three configurations; a distinct hidden-owner click; and a
|
||
private Mosaic → `splith` return. The planned 30 cycles all completed.
|
||
There are **994 sampled PNGs**
|
||
on two outputs. None is labelled a complete presented-frame sequence.
|
||
The popup owner and A/B are solid SHM surfaces; supporting Kitty windows ran
|
||
with cursor blinking disabled. The predefined HEADLESS-1 ROI
|
||
`(400,90,800,310)` was empirically stable across S0 and post-close captures
|
||
in the completed cycles. `wev` on HEADLESS-2 can redraw its text, so its
|
||
whole image was not treated as a static underlay; right-output popup colors
|
||
and events were checked separately. The ROI and this exclusion were fixed
|
||
before scoring the campaign.
|
||
|
||
| Observation | Unmodified `splith` | Private `splith` | Private Mosaic |
|
||
| --- | --- | --- | --- |
|
||
| Ten A/B open → close B → click A → close A cycles | PASS sampled | PASS sampled | PASS sampled |
|
||
| A right-button delivery after B destruction | 10/10 | 10/10 | 10/10 |
|
||
| Former A/B left-output ROI restored | 10/10 exact equalities | 10/10 | 10/10 |
|
||
| B crossing color at right, cycles 1 and 10 | 15,860 green | 15,860 green | 0 green |
|
||
| Fully hidden A/B colors and camera return | N/A | N/A | 10/10 sampled: 0/0 hidden, A/B restored with equal ROI |
|
||
| Outside-click `popup_done` and child-first destruction | PASS | PASS | PASS |
|
||
| Hidden-owner click: no popup button, B/A dismissal | N/A | N/A | PASS sampled |
|
||
| Stable `splith` return with B open | N/A | N/A | 15,860 B pixels and actual B button |
|
||
| Damage/frame presentation proof | NOT TESTED | PARTIAL | PARTIAL |
|
||
|
||
The camera run requested 18 outward/return pairs in each of three pacing
|
||
modes: stabilization after every change, capture between accepted commands,
|
||
and a four-command burst without intervening captures. The owner stayed IPC
|
||
ID 8, A/B were created once each, no `popup_done` occurred before explicit
|
||
closure, and the sampled hidden/visible colors followed the observed target
|
||
values. All 109 `camera_observed` records, including initial positioning,
|
||
reported targets 400 or 1280. No sampled right-output A/B color appeared.
|
||
The runner's IPC checks do not prove which intermediate target values were
|
||
actually presented. The burst may coalesce them. Input/render consistency
|
||
during an unobserved frame is therefore **PARTIAL**, even though the sampled
|
||
pointer and pixel outcomes show no reproducible divergence.
|
||
|
||
The separate hidden-click run sent a right button to a point on HEADLESS-1
|
||
after `scroll_x=1280`. The count of popup button presses did not increase;
|
||
`popup_done` arrived B then A, and neither popup reappeared after return to
|
||
400. This is one controlled hidden point, not a universal input claim.
|
||
|
||
The private SceneFX `TEMPORAL_DAMAGE` log recorded **4,361** output-local
|
||
damage extents across the eight private runs, and the actual SwayFX repaint
|
||
path logged **1,432** accepted output commits (zero rejected). The analyzer
|
||
compared each pair of sampled captures per output against extents whose
|
||
monotonic timestamps fell in that capture interval. It found **zero changed
|
||
pixels outside their union** and zero changed intervals without an overlapping
|
||
extent. This is interval evidence only: broad bounding extents may hide
|
||
over-invalidation, and no screenshot is tied to a unique presented frame.
|
||
H5 is **PARTIAL**. The unmodified control has no private damage trace and is
|
||
**NOT TESTED** for H5.
|
||
|
||
An independent audit of the retained PNGs compared all three RGB channels,
|
||
rather than relying on the analyzer's grayscale difference. Across 784
|
||
private same-output capture intervals, 237 contained changed pixels
|
||
(57,451,528 changed pixel positions in total); zero changed positions fell
|
||
outside the union of their time-bounded logged damage extents. This confirms
|
||
the narrowly stated interval observation despite the grayscale conversion
|
||
used by the fixture analyzer. It does not establish minimal damage, exact
|
||
pixman regions, a damage-to-commit mapping or intermediate frame correctness.
|
||
|
||
`results/artifacts-sha256.txt` lists **2,133** raw and derived files, with
|
||
manifest SHA-256
|
||
`362ba5dc399383ecd7c071b56c144b8bdf9f4dc17fad53b60238a14c750bdf7c`.
|
||
The final 12-input source manifest is `temporal-source-sha256.txt`, SHA-256
|
||
`ef5596c587372388efedd9319ee0062cf1143e2a7c203ed4c579fc6346753702`.
|
||
The preceding instrumented lab
|
||
`/tmp/swayfx-mosaic-nested-grab-1u4Q8mE9/` retains its original
|
||
`temporal-source-sha256-initial.txt`: after those runs, its analyzer gained
|
||
a pixel-wise union check and final matrix. The final lab was rebuilt after
|
||
the A-input and hidden-click refinement and carries a single matching source
|
||
manifest. `sha256sum -c` passed for all 2,133
|
||
listed artifacts and all 12 final source inputs.
|
||
|
||
A fresh private lab at `/tmp/swayfx-mosaic-nested-grab-u5ZlcX0A/` rebuilt
|
||
the pinned source and patches and passed its 12-input source manifest. A
|
||
targeted replay completed one A/B open → explicit B/A close cycle in each of
|
||
the three configurations, plus private Mosaic hide/click/return, one
|
||
two-move camera run and a separate outside-click dismissal. All six runs had
|
||
no runner failure, valid XDG button serials and no failing targeted
|
||
assertions. Their 124 sampled PNGs, 1,457 private timed damage extents and
|
||
289 accepted private output commits reproduce the sampled outcome; they do
|
||
not add frame identity. This fresh lab is retained outside Git.
|
||
|
||
The independent uninstrumented lab
|
||
`/tmp/swayfx-mosaic-nested-grab-36Cbn4JP/` had the same ten-cycle sampled
|
||
outcomes in each configuration. The first instrumented lab
|
||
`/tmp/swayfx-mosaic-nested-grab-M5uSSO6U/` and the later
|
||
`/tmp/swayfx-mosaic-nested-grab-1u4Q8mE9/` also repeated them. No
|
||
probe-induced visual difference was observed in these sampled runs; timing
|
||
perturbation outside them remains possible. No compositor crash, Wayland
|
||
protocol error, failed grab, stale popup object or residual popup-colored
|
||
pixel was detected in the completed final matrix. The initial toggle
|
||
sampling failure and its correction are recorded in the history below.
|
||
|
||
This result does not settle popup UX while an owner is hidden, full
|
||
transaction-generation consistency, all presented frames, effects/decorations,
|
||
saved buffers, scaling/rotation, output migration/resize or SceneFX ABI/package
|
||
maintenance. The next bounded STEP20C experiment should instrument an actual
|
||
headless output presentation event together with applied camera/clip state
|
||
and pointer target for one repeated hide/return transition. It should test
|
||
the unobserved interval directly; it does not authorize a production fix.
|
||
|
||
## Protocol history
|
||
|
||
- 2026-10-11: protocol written before the temporal fixture; targets and
|
||
verdict rules above are prospective. Subsequent changes and measured
|
||
results must be recorded here with their date and run paths.
|
||
- 2026-10-11: first private campaign in
|
||
`/tmp/swayfx-mosaic-nested-grab-36Cbn4JP/` completed ten cycles in each
|
||
configuration, plus 18 camera transitions per mode, outside clicks and a
|
||
layout-return pilot. The original runner/analyzer sources are retained in
|
||
that lab's `source-snapshot-v1/`. Its immediate `layout splith` capture
|
||
contained no right-output B pixels; the protocol now adds a stabilized
|
||
capture and B click before classification. The camera runner also adds a
|
||
separate command burst without captures between every accepted scroll.
|
||
These changes affect measurement timing, not the private clip algorithm.
|
||
- 2026-10-11: `SPIKE_DAMAGE` lacks monotonic timestamps and an output commit
|
||
marker. A separate private SceneFX logging patch is therefore planned for
|
||
the next lab. It may log `CLOCK_MONOTONIC` nanoseconds, the damage extent,
|
||
and a **local experimental** output-commit ordinal/result. It will not
|
||
expose a native transaction generation, alter public headers or prove
|
||
presentation by itself. Compare the instrumented result with the
|
||
uninstrumented campaign for probe-induced changes.
|
||
- 2026-10-11: the first instrumented lab
|
||
`/tmp/swayfx-mosaic-nested-grab-M5uSSO6U/` retained 10 cycles per mode,
|
||
18 camera round trips in each of three pacing modes, outside clicks and a
|
||
successful stable layout-return check. It logged damage but zero SceneFX
|
||
commit-hook calls. Source audit found the actual call in private SwayFX
|
||
`sway/desktop/output.c`; a separate logging-only Mosaic patch is now added
|
||
to the next private lab. The initial toggle runner failure in
|
||
`/tmp/swayfx-mosaic-nested-grab-pX0BTADM/` was a left-side fixture sample
|
||
after stable right-side pixels had already been captured; it was not a
|
||
compositor or XDG failure. Its logs and exit code are retained.
|
||
- 2026-10-11: the private SwayFX commit-hook patch logged the repaint path
|
||
actually used. Pixel-wise unions and `matrix.json` were added to the
|
||
analyzer after the first complete instrumented campaign; its original
|
||
analyzer hash was retained in `temporal-source-sha256-initial.txt` under
|
||
that lab. Its own source and artifact manifests remain available.
|
||
- 2026-10-11: a final protocol refinement adds an explicit A right-button
|
||
interaction after B's destruction in each cycle, and a separate hidden-owner
|
||
outside-click run. Earlier cycles demonstrated A mapping and B creation via
|
||
an A click, but did not directly recheck A input after B closed. The new
|
||
run must not erase or relabel earlier evidence; its own manifest and run IDs
|
||
will distinguish this stronger input check from the previous matrix.
|
||
- 2026-10-11: the refined campaign in
|
||
`/tmp/swayfx-mosaic-nested-grab-RbwDblky/` completed the 30-cycle matrix,
|
||
camera modes and both outside-click contexts. Ten post-B A interactions per
|
||
configuration and the separate hidden-click non-hit assertion passed. Its
|
||
final source and artifact manifests validate the finished analysis. The
|
||
verdict remains **PARTIALLY_FEASIBLE** because frames and native transaction
|
||
generations remain unobserved.
|