Repository navigation
The loader hands the panel's EDID to the compositor, which chooses the display's scale - #895
Conversation
The design round's empty commit. The design and its roast are the pull request's body; the build drops this commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
|
The orchestrator, on the design's two decisions:
|
|
Design review, round 1: head Read against:
The orchestrator's rulings are taken as given: S1 first, the lending limit raised in S1, and Weighed
Where this review rests on Linux. In one place: I read GNOME Mutter's
The design rests on Linux in three places: B10 (Mutter), N8 (M1 through Ubuntu's sysfs) and N9 (KMS). BLOCKER
NOTE
DESIGN NEEDS CHANGES: fence every completion the design relies on (§5.7.6.5); keep one virtio-gpu guest smoke; make the cursor queue read-only, with QEMU's |
|
Design round 2: head Since round 1, BLOCKERs
NOTEs
What I need from the orchestrator: the decision on B6 (cut the control, or keep it with the feature mechanism above), and a design review of this revision. 🤖 Generated with Claude Code |
|
Orchestrator on B6: the decline control and its kernel actuator |
|
Design review, round 2: head Read against: Architecture. The shape is right, and it is simpler than round 1's:
Round 1, resolved
Linux. The body cites no Linux source or interface. BLOCKER
SUGGESTION
SEND BACK |
|
Design round 3: head BLOCKERs
SUGGESTIONs, all taken
🤖 Generated with Claude Code |
|
Design review, round 3: head What I read:
Evidence still valid.
None of them touches residue, lending or the virtio-gpu device answers. So the reading at Architecture. The shape is the one round 2 accepted, and it is unchanged:
This round removes the last structure-preserving workaround: the raised Recording note for the orchestrator (not a finding against the design). The body's ruling paragraph says the rulings were made "on round 2's review". There is no orchestrator comment on this PR after round 2: the next comment is the implementer's answer. The rulings the body lists do match the ones I was briefed with. Please post them on the PR so that the paragraph has a record to point to. Round 2's blockers
Round 2's suggestions
BLOCKER None. SUGGESTION
Readiness. I find nothing that blocks building S1 and S2 from this design. M1 precedes S2's GOP half, and the slot PR precedes S1's landing, as the body orders them. The four suggestions are optional wording and test-list additions that an implementer can absorb in the stage PRs. LAND |
|
Orchestrator: the design is accepted for the build (round 3, 6154671069: LAND, no blocker). For the record, the round-2 rulings the body cites were sent to the implementer by message, not posted; they were: (1) the Round 3's four suggestions are taken into the stage PRs: a first mode refused for its resources falls back to the least mode once, stub-tested; the "whatever the window's size" wording gets its exception; ties round down, stated; the cursor-queue Build order as the body says: M1 (the T14 EDID reading, run by the orchestrator), then S2's GOP half from its fixture, S1 after the slot PR lands. |
…and AMD bench reading PR #895's S2 sets the GOP machines' scale from the EDID the loader reads through UEFI's EFI_EDID_ACTIVE_PROTOCOL before ExitBootServices, and no boot of either laptop has asked whether its firmware publishes it. The loader now asks on every handle that carries a GOP: whether EDID Active and EDID Discovered are there, their SizeOfEdid, and each base block in hex. The metal row m1_edid_reading prints those lines from loader.log and is red only where the loader wrote none. Both are a reading, not S2's design: S2 replaces them with the copy into the handoff and its gop_edid_scale row. Under QEMU 11.1.1's OVMF, metal-sim's two GOP handles publish neither protocol, as edk2's QemuVideoDxe leaves it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
… scale The loader takes the panel's EDID base block from the one GOP handle that shows the scanout it hands over, by frame buffer base, size, format and stride, and that carries EFI_EDID_ACTIVE_PROTOCOL. M1 read the protocol on the first of two GOP handles on the T14 and on the second on the AMD bench, so the handle that shows the display is matched, not assumed; two matching handles that both carry one cannot be told apart, and neither is taken. KernelArgs and FramebufferInfo gain the block, unparsed, and its length, 0 or 128; the kernel refuses any other length the loader wrote. The compositor decodes it with the new toyos-edid crate (E-EDID 1.4: the first detailed timing's millimetres, falling back to bytes 0x15/0x16 in cm, an aspect ratio or unknown size giving none) and chooses a scale with toyos-desktop's Scale::auto, ToyOS's own rule as PR #895 states it: CSS Values 3's reference pixel at an assumed 24 inches, 112 dpi, the nearest quarter step from 1 to 4 with ties going down, stepped down until the logical screen holds 642x446. It logs the mode, the size and the scale, and `inspect display` reads the scale. Nothing draws at it yet. lib/edid's fixtures are both benches' panels as M1 read them, QEMU 11.1.1's generator, and its virtio-gpu's GET_EDID answer. M1's report and its row go; gop_edid_scale rides metalcase's boot and holds each bench to the handle M1 found the protocol on and to its fixture's size and scale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
A second GET_PROTOCOL open by the same image shares the first's entry, so closing both answered NOT_FOUND and the loader panicked on metal-sim. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Only an EDID block refused as malformed is an error; a size, or the lack of one, is a reading, as the compositor's other non-failure lines are. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
|
The accepted HiDPI design, as the PR body carried it through round 3 and the start of the build (round 3 accepted: #895 (comment)). Kept here because the body now records only what this PR lands; Design accepted (round 3); building in order on this branch, still a draft. M1 is read and S2's GOP half is built; see Build state at the end. The owner's go: a display scale factor (pixel density) and live resize / resolution change, on QEMU and on metal alike. Each stage below is its own pull request, built only once this design is accepted in a comment here. The branch carries the round-1 design commit and merges of The orchestrator's rulings (round 1, B6, and on round 2's review): S1 first; the 32 MiB lending limit is raised in S1 on its merits; What this was read from:
What was measured (evidence
What the tree has
What QEMU doesRead from QEMU 11.1.1 and, where marked, measured:
Order
Who owns what
M1. Each laptop's panel size, read the way ToyOS reads it
S1. virtio-gpu leaves the kernel; the compositor drives it and follows the host's windowIssue: stage 1 of Design.
Roast.
Checks.
S2. The scaleIssue: stage 5 of Design.
Roast.
Checks.
Metal, now and later
What I am unsure of
Build stateM1, read (staged with
S2's GOP half, built and read on both benches (head
Checks:
Next: the rest of S2 (drawing at the scale, the override on the 🤖 Generated with Claude Code |
issues/the-desktop-draws-at-the-panels-scale.md carries what PR #895 does not land: the display port and its override, drawing at the scale, the window protocol and the winit fork, and virtio-gpu leaving the kernel after the slot issue. It links the accepted design and its reviews on #895, and the desktop track's stage 5 points at it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
Build review: PR #895 at
|
… every turn Scale::n() goes with its false comment: no wire carries a scale until the track's first stage, which adds it with its first caller. LEAST and holds_least are private. The loader names a GOP list or open it could not make, where it dropped them silently, and spells its prefix in place. The compositor takes the EDID length the kernel guarantees with an expect naming that contract, where it clamped. The track's first item lists deliverables and leaves the design to the comment it links. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
No conflict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
No conflict. Both sides changed `Cargo.lock`, `Cargo.toml` and `tests/toyos.rs`, and each merged cleanly: main adds `lib/edid` and the `gop_edid_scale` row, which tells the benches apart by the `microcode:` line's signature, a line this branch leaves as it was on both benches. Main touches none of `kernel/pure/cpu.rs`, `kernel/pure/xsave.rs`, the HWP path, the counters path, `toyos-microcode`'s source or the rows judged at 49f786c. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
…gain #918 moved since 9b39b7c: review round 1 and two merges of main (#895, #917 and more). No conflict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy
On a GOP machine the compositor now knows the panel's physical size and the scale it calls for. The loader hands the panel's EDID to the kernel; the compositor decodes it, chooses a scale, logs it and answers it in
inspect display. Nothing draws at the scale yet: that, thedisplayport and its override, the window protocol, the winit fork and virtio-gpu leaving the kernel areissues/the-desktop-draws-at-the-panels-scale.md.The accepted design and its review rounds are on this PR: the design, reviews 1, 2 and 3, and the acceptance. The orchestrator ruled that this part lands on its own.
What changes
EFI_EDID_ACTIVE_PROTOCOLbeforeExitBootServices. It reads it only from a GOP handle that shows the scanout it hands over, matched by the frame buffer's base and the mode's size, pixel format and stride, and only where exactly one such handle carries the protocol. It logs which handle it took, or why it took none. The rule comes from a metal reading (M1, below): the protocol is on the first of two GOP handles on the T14 and on the second on the AMD bench, while the loader's display is the first on both. Two matching handles that both carry one are refused, because an EDID from the wrong output would set the wrong scale silently.KernelArgsgainsgop_edidandgop_edid_len, andFramebufferInfogainsedidandedid_len: the 128-byte base block, unparsed, and a length of 0 or 128. The kernel refuses any other length the loader writes and reads none of the bytes.lib/edid(toyos-edid), a crate of its own because it decodes bytes from outside the reader's trust. It refuses a short block, a missing header and a bad checksum by name. The size is the first detailed timing's mm; a timing of 0 mm is "undefined" and falls to bytes 0x15/0x16 in cm; one zero byte there is an aspect ratio and both zero are unknown, neither a size (VESA E-EDID 1.4, §3.3, §3.10, §3.11, Tables 3.12 and 3.21).toyos_desktop::Scale::auto, ToyOS's own rule. The desktop's pixel is CSS Values 3 §5.2's reference pixel, 1/96 inch at 28 inches; every panel is assumed viewed from 24 inches, ToyOS's choice and not a published figure, so the target is 112 dpi. The scale is the quarter step from 1 to 4 nearest the panel's density over that, a tie going down, stepped down until the logical screen holds 642x446: an 80x24 terminal of 8x16 cells inChrome::DEFAULT's frame above the taskbar, computed from those values. Integer arithmetic throughout.compositor: display WxH, panel WxH mm, scale Son standard output, or that the panel gave no size; only a block refused as malformed goes to standard error.inspect displaygainsscale.gop_edid_scaleridesmetalcase's existing boot. It tells the bench by its CPU signature and asserts the loader's line for the handle M1 found and the compositor's size and scale from that bench's fixture.Size.
git diff --shortstat origin/main...HEAD: 32 files changed, 745 insertions(+), 10 deletions(-). Of those, 230 are tests and their fixtures' provenance (lib/edid/src/tests.rs,scale.rs's tests, the row intests/toyos.rs,fixtures/SOURCE), 44 the fixtures' declarations inbuild/licence.rs, and 50 the issue files; the rest is production, the largest pieces the loader's handle matching (90) andScale(92).Checks and evidence
Evidence is on
ToyOSOrg/evidencebranchpr-895.9d8a3811a, run by the orchestrator, replaced by this change): T14 (LENOVO 20W0003AMZ), panel CMNN140HCA-EAE, 309x173 mm, on GOP handle 0 of 2; AMD bench (LENOVO 82A2), panel AUOB140HAN06.8, 309x174 mm, on handle 1 of 2. Neither block carries a serial in bytes 0x0C-0x0F or a0xFFdescriptor, so the committed fixtures are the panels' bytes unchanged.gop_edid_scaleat6fd69e2b4(T14, AMD, with each boot's kernel and loader logs beside them): T14 "GOP handle 0 of 2 shows the scanout and publishes 128 byte(s), the base block handed over" and "compositor: display 1920x1080, panel 309x173 mm, scale 1.5"; AMD bench handle 1 of 2, "panel 309x174 mm, scale 1.5". Why it still holds at the head: since6fd69e2b4the only change on that path is the compositor's line moving from standard error to standard output (system/compositor/src/session.rs, 3 lines); the row matches the line's text, not its channel. The merges ofmaintouch none of the loader, the handoff, the GOP path, the compositor,metalcaseor the row's judge.metalcase's boot.gop_edid_scalejudged with--metal-readbackon copies of M1's own readbacks, whose loader carries no S2 line, reds on both benches by name, exit 1 (T14, AMD).a_tie_goes_to_the_smaller_step; no step-down redsa_small_mode_steps_down_to_the_least_screenandeach_row_of_the_rule_gives_its_step; a 0 mm timing taken as a size redsa_timing_of_zero_millimetres_falls_to_the_base_block.scale.rs's tests assert.cargo test --test toyos-build -- desktop_without_x2apic --nocapture, exit 0, on metal-sim at6fd69e2b4(log): the loader finds no GOP handle showing the scanout with EDID Active, and the compositor runs at scale 1. Its first run caught the loader closing one GOP open twice (CloseProtocol ... NOT_FOUND), which6fd69e2b4fixes. No new guest test: no QEMU firmware publishes the protocol.cb9d2a4ea,cargo run -- --build-onlyexit 0 andcargo run -- --ci hostexit 0, 77 steps green (logs). The build review's fixes after the metal run change the loader only on paths the benches did not take (a GOP list or open that fails now says so), and leave the lines the row reads as they were.Risks
🤖 Generated with Claude Code
https://claude.ai/code/session_015xhaydXCVRNscoccHYFUWy