Tier 88 (context/plans/build-site.md): the registry had no unblocked task left; what remained to an agent were criteria no task covered any more. T-518. Criteria met by earlier tasks ticked with their evidence: gpu R11's review (T-513 and Codex's 2026-10-24 pass), content-blocking R7 (the bundle's sha check against NOTICE and the lists' README, the README paragraph with cardview.jpg, round 26's licence reading), modern-web R1 (T-484 and run 2c; the README's Caveats link) and T-500's two. T-501's stays [~] for MSE (below). The template placeholders never filled (T500_KIT, T501_KIT, T501_DEVICE_RESULT in docs/MODERN-WEB.md, DEVICE_STATE_EVENING and TRACE_PICKUP in PICKUP) are filled; .cavekit/config is the owner's one line again; the README's "Where it stands" regenerated. T-519. On the build with the review fixes (engine 0058), the 10 s scripted pan on six pages under JIHAD_GPU_VERIFY=1 (docs/rounds/t519-2026-10-24/): 0 rows structurally wrong on all; 0 rows differ at all on the long page, jihad-fixed-both.html (new: an opaque header AND footer, nothing else), sticky-mix, scroll-js and Hacker News; Wikipedia 3 of 70 frames with resampling-class rows. The one miss is the verify mode's own: on jihad-anim-css.html the animated block's 160 rows differ (the reference samples the animation at its own compose time), every other row equal — R2's first criterion [~] with the engine fix named. The dumps looked at frame by frame; Hacker News at 0.955 shows its right side and bottom. R4's four ticked on the compositor's lines: the fixed-both page reads two bands with both kept, the long page one kept, Wikipedia's see-through panels as 2 columns in 3-5 chunks; sticky-mix takes the whole path as in T-503's rounds (its sticky layer changes every step). R3's table: the GPU path against NOGPU=1 on every page, in docs/RENDERING-OPTIONS.md — the GPU path ahead on every page (long static 30-33 against 11-12.5 fps, Wikipedia 18.5-26 against 2.7-2.9, Hacker News 37-48 against 6-10). The frame rates were measured again without verify after a first sweep read 5-6 fps under it (a whole reference per job): tools/device/t502/README.md says so; pan-run.sh takes ROUND_DIR. T-520. The blocker's device criteria on the Enyo card through the inject channel, the listed hosts mapped to the host PC in the device's /etc/hosts for the run (only the blocker can then stop a load): a listed host opens top-level; EasyPrivacy's ||123count.com^$third-party loads first-party (the page on that host) and is refused third-party; an @@||host^ exception (a list copy with one added, exceptions 6+1083 against 5+1079) loads the host; the master switch and hiding flip live through setpref (the observer re-applies the sheet); the settings line shows the versions and a counter that rose 10 -> 16 on a page with 6 refusals; "Update the lists now" moved the lists three times and the line followed; shouldLoad on 200 refused images is within 10 % of blocking off (6.5 against 6.0 s, the floor the engine's own per-image work); MSE reports H.264 and AAC (T-501's criterion closed). R4's cost criterion was NOT met: hiding on cost the MDN page's copy 3.7-7.5 s against 2.6-3.0 off, the real cached page 15 against 11, and a daemon's first load 8-12 s. T-522. Four variants of the cached sheet on the device named the cost: the 268 @-moz-document regexp groups (one per site-excepted generic selector, each carrying the 160 generic-hide hosts' 2.4 KB regexp again), evaluated per document; the same 13,079 keyed selectors under url-prefix scopes or bare cost nothing. The compiler (version 11) keeps those selectors apart (excSel) and the component adds them to the per-document sheet for every host the selector is not excepted on, with the generic-hide sites (hosts and address prefixes) honoured there too; the global sheet keeps its one regexp group. Measured: the MDN copy with hiding on 2868, 3104, 2876 ms against 2712, 2578, 2846 off (+8.7 %, within R4's 15 %), a daemon's first load 3.7 s where it took 8-12; generic hiding still applies under a host name, a site-excepted selector is hidden where not excepted, and a $generichide host (jetzt.de mapped to the host PC) gets neither; the compile reports 268 excepted selectors per document and 154 generic-hide sites with 4 address prefixes. New test pages: jihad-fixed-both.html (an opaque header and footer), jihad-tp-first/third.html, jihad-exception.html, jihad-hiding.html, jihad-excsel.html, jihad-mse-probe.html, jihad-plain-ok.png. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
27 KiB
created, last_edited
| created | last_edited |
|---|---|
| 2026-10-18 | 2026-10-18 |
Cavekit: GPU Rendering (the pick: 2 + 4)
Scope
The page is composited on the TouchPad's GPU (the Adreno 220, through EGL) by the engine's own OpenGL compositor running inside the headless daemon, and the finished frame is read back into the YAP shared buffer the card already shows (option 4). WebGL then runs on the same GPU through EGL (option 2). The BrowserAdapter↔BrowserServer contract stays byte-identical: the card receives the same buffers and messages as from the software path, only faster. All three interfaces (Enyo, Mochi, Mojo) get it; the software path stays as the fallback.
User decisions: 2026-10-17, the rendering report cut down to the survivors and "the pick: 2 + 4" (GPU compositor with readback, then WebGL through EGL), a one-week spike first (T-502); video sometimes, 24 fps video acceptable, styled video matters (fades, rounded corners, video under a modal), so the video overlay (5) is held back. 2026-10-17: "dont treat the chart speed predictions as the theoretical maximum, but the bare minimum goal, and keep the performance acceleration going as far as you can". 2026-10-18, the owner's finger test on the GPU path: "areas turn grey and zoom rendering of page content lags behind actual page zoom state". 2026-10-18: "continue using cavekit 3.1 to finish the implementation".
The chart's rows for 2 + 4 (the floor, not the target): animation and in-band scroll 42 ms
(24 fps); new content 106 ms (9 fps); WebGL 42 ms (24 fps); video decode plus a 42 ms frame. The
whole account, the measurements and the traps: docs/RENDERING-OPTIONS.md ("T-502").
What exists at the kit's creation (T-502, rounds 1-141): engine patches 0040 (the compositor),
0041 (the Adreno 220's GL) and 0042 (compositor-side scroll, band reads, the band surface,
displayport, fixed/sticky rows, the composition fix); the daemon's job pipeline
(render/goanna/BrowserPageGoanna.cpp gpuJobStart/poll, GoannaRenderPage.cpp ComposeStart/Poll,
the wake pipe in render/browserserver/Main.cpp); behind JIHAD_GPU_COMPOSITOR=1, Enyo only,
started by hand (tools/device/t502/). Measured: the test pan 27-34 fps, the animation page 26-31,
Hacker News 36-37, desktop Wikipedia 13-14 (software 9-12.4).
Requirements
R1: The GPU path is the default, with the software path as its fallback
Description: The daemons of all three interfaces composite on the GPU unless it is unavailable. Acceptance Criteria:
packaging/event.d/{jihad,jihad-mochi,jihad-mojo}(or the daemon's own default) start the GPU path;JIHAD_GPU_COMPOSITOR=0(and a pref the bundle reads) forces the software path (2026-10-19, T-510: the generated jobs setJIHAD_GPU_COMPOSITOR=1 JIHAD_GPU_EXPRESS=1; the daemon settles the path before the engine starts (render/browserserver/Main.cpp):JIHAD_GPU_COMPOSITOR=0oruser_pref("jihad.gpu.enabled", false)in the profile (defaulttrue,packaging/prefs/jihad-platform-prefs.js) unset both, and the log says "rendering: the GPU path, frames off the main thread (the express lane)" or "the software path (why)". On the bench: all three jobs on the GPU path; the pref put Mochi on the software path and back;JIHAD_GPU_COMPOSITOR=0put a hand-started Enyo daemon on it.)- A daemon whose EGL setup fails (simulated by an env that makes the context creation fail) renders every page by the software path, and the startup report names the path taken (2026-10-19, round 230:
JIHAD_GPU_TEST_NO_EGL=1(engine 0047): the engine falls back to its software compositor, the daemon finds three frames failed and logs "the GPU path is off for this daemon (the compositor failed three frames): the software path renders from here"; the page renders; pages made later start in software) - No GPU wait is unbounded: a stuck job is abandoned after a bound and the page falls back to the software path for that daemon's life; LunaSysMgr never loses EGL because of the daemon (memory
gpu-wedge-needs-a-reboot) (rounds 229-230:JIHAD_GPU_TEST_STALL=30holds a job 6 s; at 3 s (JIHAD_GPU_JOB_BOUND_MS) the daemon forgets it (the compositor then writes nothing into its slot) and paints in software; LunaSysMgr kept its EGL in every run, no "EGL error" in the system log. A driver call that never returns cannot be tested safely: the page goes on in software, the stuck compositor thread stays stuck) - Enyo, Mochi and Mojo each load, pan, zoom and close a page on the GPU path on the bench (CE 3.1.0) (2026-10-19,
tools/device/t502/default-check.shon each variant's own upstart daemon, desktop en.wikipedia.org through the card's self-test hook: Enyo two pinches and a double tap (23 frames, 7 of them the express lane's, 6 zooms), Mochi a drag, a flick and two pinches (27, 11, 5), Mojo a drag and two pinches (27, 30, 4); each card closed, no fault, no fallback; the screenshots at rest sharp and covered) Dependencies: offscreen-rendering R1-R6, device-build R4
R2: Every frame is right
Description: What the card shows on the GPU path equals a whole composite of the page at the frame's scroll and zoom. Acceptance Criteria:
- [~]
JIHAD_GPU_VERIFY=1reports 0 differing rows over a scripted pan onjihad-long-static.html(fixed header),jihad-anim-css.html,jihad-scroll-js.html, a page with a fixed header AND a fixed footer, desktop en.wikipedia.org (stuck sticky sidebars) and news.ycombinator.com (2026-10-24, T-519, on the build with the review fixes (engine 0058), the 10 s scripted pan on each (docs/rounds/t519-2026-10-24/pan-*-gpu-daemon-gpu.log): 0 rows structurally wrong on all six; 0 rows differ at all onjihad-long-static.html(61 verified frames),jihad-fixed-both.html(65; an opaque header AND footer, added for this),jihad-sticky-mix.html(62),jihad-scroll-js.html(120) and news.ycombinator.com (142); desktop Wikipedia 3 of 70 frames with rows that differ beyond the threshold (371, 7 and 7 rows, none structurally: a fractional scroll's resampling, the class the mode reports apart). The one miss: onjihad-anim-css.html117 of 119 frames differ in exactly the animated block's 160 rows (261..421), and 2 of them count 80 and 144 of those rows structurally wrong; every other row of every frame is equal. The reference composite samples the CSS animation at its own compose time, a few ms after the job's, so an animating layer moves between the two: a limit of the verify mode, not of the frame (the dumps show the box and the overlay drawn). Left open: pin the reference's animation time to its job's (TransformShadowTree(time)in the engine's compose), an engine patch after 0058.) - The mid-pan frame dumps of each are looked at and match the page (memory
verify-device-frames-by-eye) (2026-10-24, T-519: frames 60, 120 and 180 of each pan,docs/rounds/t519-2026-10-24/pan-*-gpu-frame-*.jpg, looked at: the headers and footers in place, the text continuous and numbered in order, the sticky sidebar and its opaque box in place over the stripes, the animated box and the overlay drawn, the self-scrolling page's counter, Wikipedia's text and its right-hand panel, Hacker News' last rows (the footer and search box) in frame 60 and white past the page's end in the later frames (the pan overshoots a 1249 px page, as recorded).) - A page laid out wider than the card (fit zoom below 1) shows its right side and bottom (rounds 129-134, T-502: the root's composition is its scroll port on the GPU path and the displayport covers what the card shows. 2026-10-24, T-519: news.ycombinator.com at the fit zoom 0.9552 (
displayport: scroll port 764x942 CSS px, shown 804x986): frame 60 of the pan has the footer bar across the frame's whole width and the page's last rows; the only mark beyond the page is a 1 px light column at the frame's right edge, present in the T-505 dumps (r200) too.) - A fast flick (a shift of more than 256 rows a frame) and two cards panned in turn pass the verify mode (added 2026-10-19 by T-513's review: the band scratch shared between compositors, the band frame drawn with the wrong surface current) (2026-10-19: six 700 ms flicks of 6000 px on
jihad-long-static.html, 40 verified frames with shifts to 1200 rows, 0 rows wrong; two cards in one daemon panned in turn (the long page, thenjihad-sticky-mix.htmlin a second card, then the first again:tools/device/t502/two-cards.sh, the card brought back by the Enyo test hook'sAstep and the inject channel'starget focus), 26 frames, shifts to 1130, 0 rows wrong. The verify reference is now composed right behind its job, on the same layer tree: composed at the job's poll it met a tree the flick had moved on from (the displayport's tiles gone) and called right frames wrong, 744 rows in the first run. Again on 2026-10-24 on the build with Codex's fixes: two cards 22 frames, six flicks 40 frames with 15 shifts over 256 rows, 0 rows wrong. Notesdocs/rounds/t513-2026-10-19/.) Dependencies: R1
R3: Pans meet the chart, on real pages too
Description: A drag-scroll moves the content by compositing the painted displayport, not by repainting. Acceptance Criteria:
- The scripted pan (0 → 3000 card px in 10 s,
tools/device/t502/pan-run.sh) runs at 24 fps or better onjihad-long-static.htmland on desktop en.wikipedia.org after its load (2026-10-19, T-515: the test page 30-35 fps; desktop Wikipedia 19-21 fps in 2 s windows, median frame gap 45 ms, with the frames made off the main thread. The page's script no longer gaps them (its 2.2 s restyle ran under frames every ~45 ms); the floor is the compositor thread's ~45 ms a Wikipedia frame, whichever lane asks for it: T-517. A page whose script holds the main thread 600 ms in every 700 pans at 26-32 fps (2.4-3.8 without the express lane).) - On every page measured, the GPU path's pan is at least as fast as the software path's on the same pan (
NOGPU=1), and the table indocs/RENDERING-OPTIONS.mdsays so per page (2026-10-24, T-519, the same 10 s pan on each page both ways on engine 0058, the pan's 2 s windows: long static 30.4-33.3 against 10.8-12.5 fps, fixed header and footer 26.4-27.9 against 10.9-12.7, sticky-mix 16.5-19.0 against 8.6-10.0, the animation page panned 14.5-24.4 against 11.4-23.6, the self-scrolling page 22.8-27.7 against 10.5-11.4, Hacker News 37.5-48.0 against 6.3-10.2 (the pan overshoots its 1249 px, the last frames are past the page), desktop Wikipedia 18.5-25.9 against 2.7-2.9 (the 18.5 window is the first scroll's restyle). The table is indocs/RENDERING-OPTIONS.md; logsdocs/rounds/t519-2026-10-24/pan-*-gpu2-*andpan-*-sw-*.) - Frame gaps of 56 ms or more during a pan are accounted for (traced to their source) and the avoidable ones removed (2026-10-18, traced: desktop Wikipedia's pan has 3-13 a 2 s window. The stall sampler resolves them to the page's own restyle on the first scroll (955 ms, 36% selector matching: its sticky header), the layer paints of the displayport moves (58-121 ms: display list, glyphs, regions), and short misc events. None is the daemon's own work; the anchor distance does not change them (0.125 and 0.4 heights measured). What would remove them from the frames is the frames made off the main thread: T-515. 2026-10-19: done (T-515, the express lane): the main thread's stalls are covered by frames composed and published from a thread of their own; the gaps left are the compositor's own (T-517).)
- During a pan the card has content past the view's edges, as the software path's frames have: a gap between frames or a busy main thread shows the page, not grey (added 2026-10-18 from the owner's "areas turn grey": the GPU frame carries 0.15 of the card's height above and below the view (engine 0046,
JIHAD_GPU_OVERSCAN); verify 0 structurally wrong rows with it on the test page, sticky-mix, desktop Wikipedia and Hacker News; frame dumps looked at) Dependencies: R2
R4: Fixed and sticky content costs little
Description: Fixed headers and footers and stuck sticky elements stay put and are not re-read whole every pan step. Acceptance Criteria:
- An opaque fixed or stuck layer that held still keeps its pixels from the previous frame; only the rows the shift uncovers beside it are read (T-503, rounds 138-150. 2026-10-24, T-519 on engine 0058:
jihad-long-static.html16 of 16 band frames1 kept(the header) reading the two bands beside it, e.g.rows 79..160 and 1162..1224;jihad-fixed-both.html2 kept, e.g.rows 139..141 and 1033..1224; desktop Wikipedia's band frames1 kept(its opaque sticky header).) - A non-opaque one is read as its columns, not as full rows (T-503. 2026-10-24, T-519: desktop Wikipedia's two see-through pinned panels, 9 of 13 band frames
2 columns in 3-5 chunks (110-232 rows)on the band surface.jihad-sticky-mix.html's transparent sidebar is a different case: its layer changes every step (the stuck position follows the engine's anchor), so the diff-first path finds 415-566 changed-plus-fixed rows and takes the whole composite, as it did in T-503's and T-505's rounds (r198, r200: 0 band frames, 15-17 fps); no columns are read there because no band frame is made.) - A page with a fixed header and a fixed footer reads two bands, not the whole frame (2026-10-24, T-519:
jihad-fixed-both.html(an opaque fixed header and footer, nothing else fixed): every band frame reads two bands,rows 139..141 and 1033..1224,rows 130..171 and 1024..1224, with the header and footer kept.) - R2's verify passes on each case (2026-10-24, T-519: 0 rows structurally wrong on
jihad-long-static.html,jihad-fixed-both.html,jihad-sticky-mix.htmland desktop Wikipedia underJIHAD_GPU_VERIFY=1over the 10 s pan; the per-page lines are in R2.) Dependencies: R2
R5: Animation and new content meet the chart
Acceptance Criteria:
jihad-anim-css.htmlanimates at 24 fps or better (only the changed rows composed and read) (2026-10-18, round 202: 26-31 fps; each frame reads its 160 changed rows)- A content change (a DOM edit on a test page, typing into a field) reaches the card within 106 ms (round 203, the inject channel's input to the first published frame with changed rows: eight keys typed into
jihad-input-echo.html22-62 ms (one 4 ms, the previous key's echo), five DOM edits 26-70 ms) - A page that scrolls itself (
jihad-scroll-js.html) is followed at 9 fps or better (round 202: 10.7-13.9 fps) Dependencies: R2
R6: Zoom keeps up (the owner's finger test, 2026-10-18)
Description: A pinch or a double-tap zoom shows the page at the new zoom promptly and never leaves part of the card grey. Acceptance Criteria:
- A scripted pinch in to about 1.7 and back out to the fit zoom (and a double-tap zoom) on desktop en.wikipedia.org and on
jihad-long-static.htmlis reproduced on the bench with the frame timeline logged (2026-10-18: the card's own gesture calls through its test hook,gpinches andtdouble taps; Wikipedia 0.69 → 1.23 → 2.20 → 1.51 → 1.03, double tap 1.26 and back to 0.69; the test page 0.79 → 1.41 → 2.51 → 1.72 → 1.18 and its double taps; each zoom's "the first frame at the new zoom is out" line) - The first frame at the new zoom reaches the card within 250 ms of the zoom command, and the frames after it keep the pan rate of R3 (2026-10-18, PARTIAL: on a settled page 52-217 ms for pinches, 61-124 ms for a double tap in and 182-257 ms back out, one double tap in at 384 and 414 ms in two runs of ten; a pan at 1.23 runs 18.5-28 fps, the fit zoom's rate. While the page's own script holds the main thread (desktop Wikipedia's modules for ~10 s after its load) the daemon cannot even read the zoom command: 0.8-1.7 s. That part waits on frames made off the main thread, with T-505. 2026-10-19, T-515: with the frames made off the main thread the zoom command is read on a thread of its own and the frame composed while the script runs: ten zooms each on Wikipedia after its load 10/10 within 160-225 ms (median 58-77; held off: median 681, max 1116, three never framed), on a page holding the main thread 600 ms in 700 within 45-91 ms (held off: median 450, max 697). Card double taps 40-449 ms: the slow ones are GPU draws of the other resolution's tiles after a zoom in's repaint (20-35 ms a draw on the Adreno), on either lane: T-516. T-516 (rounds 270-280): the slow ones were the clocks after a pause, not draws (the readback 100-390 ms, the CPU swizzle 20-122 ms); with the clock hold raised by the reader thread and the frame threads ahead of the others, 0-2 double taps in 12 over 250 ms (261-323), median 158; the GPU's own ramp after a pause is what is left.)
- No area of the card is left grey or blank at rest: within 500 ms of the gesture's end every row of the card has content at the new zoom (dumps looked at) (2026-10-18:
JIHAD_GPU_ZOOM_DUMPkeeps the frame the card shows at rest; the last frame of each zoom came 344-612 ms after it and covers the card: Wikipedia at 1.23, 2.20, 1.51, a double tap at 1.26, the test page at 2.51 and 1.72. Zoomed in, the settle had published frames at the engine's x under a card at another x, a grey strip down the right; fixed) - Tile uploads do not each wait behind queued GPU work (the Adreno 220 serialises an upload with pending GPU work: 12-63 ms per 256x256 tile seen) (2026-10-18: the wait was the driver converting a texture on its first write after its first draw, ~18 ms per 256x256, once per texture (
gpu-bench.csections 11-16); engine patch 0044 converts each new tile texture at 1x1 (1.1-2 ms) and pools textures: re-uploads slower than 8 ms from 55-59 a Wikipedia zoom run to one) - Zoomed in, the page is painted at the zoom (text as sharp as the software path's), not a 1x paint magnified (added 2026-10-18 from the owner's "zoom rendering of page content lags behind actual page zoom state": above a zoom of 1.1 the pres shell's resolution follows the zoom; Wikipedia at 2.2 compared with the 1x paint, crisp and aligned to the pixel) Dependencies: R2
R7: Video and plugins on the GPU path
Acceptance Criteria:
<video>(VP8, Theora, H.264) plays to the end on the GPU path with its frames composited (the ImageBridge), at the video's own rate up to 24 fps, with no frame the software path would not show (2026-10-19, rounds 213-228 onjihad-media-test.html: VP8, Theora, VP9 and H.264 end with every frame decoded (150 and 148 of 150); the video is its own image layer (its planes uploaded as textures); 15 fps clips published at 16-20 fps, the 640x360 24 fps clip at 15.5-18 (the software path 10-15; the CPU's limit); a 60 s clip shot side by side with the software path frame for frame. H.264 had played on neither path: the update push never carried FFmpeg's libraries, now it does. Once in six runs the 640x360 clip never started (not reproduced in five more))- Styled video works: rounded corners, an opacity fade, video under a modal (
render/goanna/test/pages) (jihad-video-styled.html: rounded corners and the modal as on the software path; the fade's brightness moves 58-94 over four shots on the GPU path in four runs;jihad-anim-opacity.htmlfades a block and a video) - Flash (NPAPI windowless) draws, animates and takes input on the GPU path at its own bounds (the device's test movies:
animmoves at 21-25 published fps (software 25-27),keyturns from green to red after a tap and two keys (the plugin'shandled=1)) Dependencies: R2, gre-widgets (media), addons-extensions R7
R8: WebGL through EGL (option 2)
Description: WebGL 1 contexts are created on the device's GPU and composited without a CPU round trip per WebGL frame. Acceptance Criteria:
- On the GPU path
canvas.getContext("webgl")succeeds on the bench; on the software path WebGL stays off (2026-10-19, T-511, engine 0051: WebGL asks EGL on the GPU path and is not blocklisted there;NOGPU=1: getContext null, "Refused to create native OpenGL context" (rounds 281-313,docs/rounds/t502-2026-10-17/webgl-r281-313.txt)) - A WebGL test page (a spinning textured cube,
render/goanna/test/) renders correctly and runs at 24 fps or better (2026-10-19, T-511,render/goanna/test/jihad-webgl-cube.html: renders correctly (screenshots r288, r305, r310). On the card: a 240 px cube 26.5-26.9 fps, 360 px 21.5-22.8, 480 px 18-20.5 (the page's own rate 21.5-25 at 480). The canvas reaches the compositor with no copy (one share group); what is left is the compositor job's ~45 ms for 482 rows, the same floor as Wikipedia's pan frames: carried by T-517) - Context loss (the card closed, the GPU reset) is handled without a daemon crash; a WebGL page cannot wedge the GPU path (R1's bound) (2026-10-19, T-511: the second WebGL page closed faulted in libGLESv2 until a context was released from its thread before its destruction (engine 0051); 8 open/close cycles of the card on the cube, no fault;
WEBGL_lose_contextlose and restore (?lose=1): the page rebuilds and draws on; the cube's compose jobs run under R1's job bound like any other) - WebGL conformance spot checks (the basic ones a page needs: textures, framebuffers, shaders) pass, and what does not is listed (2026-10-19, T-511: the test page's checks: shaders, a texture upload, a framebuffer object, readPixels of what was drawn: ok; MAX_TEXTURE_SIZE 4096; 14 extensions; missing against desktop WebGL 1: ANGLE_instanced_arrays, WEBGL_compressed_texture_s3tc, EXT_blend_minmax, EXT_shader_texture_lod (not offered by the GLES 2.0 driver)) Dependencies: R1
R9: Everything else the card does still works on the GPU path
Acceptance Criteria:
- Rotation (portrait ↔ landscape) and a resize redraw the page right (2026-10-18, rounds 206 and 209: the card held landscape by
enyo.setAllowedOrientation(the test hook'sOstep): 1024x890 frames (686 rows and the overscan), the page laid out for 1024; back to portrait and the keyboard's resize redraw right (screenshots looked at)) - Select popups, the text caret, link highlights, find-in-page highlights and the card thumbnail show as on the software path (rounds 205-212 on
render/goanna/test/jihad-card-events.html: the select's list (the card's own, Enyo) opens with its four rows and a pick reaches the page; the caret shows in the tapped field; find-in-page highlights its match; the thumbnail is the view (the frame's view row with overscan; fixed); the popups' origin is the published frame's. Link taps: the daemon sends no highlight rectangles on either path, the page's own styles draw in the frames) - Loading a new page, going back and forward, and reloading show the new content with no stale frame (rounds 207-208: a link to another page, back (the first page, forward lit), forward and reload (the second page), screenshots after each) Dependencies: R2
R10: It fits the device
Acceptance Criteria:
- The daemon's resident memory and the GPU memory with a page on the GPU path are measured against the software path and recorded; the three daemons on the GPU path at once run without running the device out of memory or GPU memory (rounds 231-232: desktop Wikipedia in Enyo 210 MB resident on the GPU path against 143 MB (44 MB more anonymous, 44 MB of shared /dev/zero mappings; the GPU's own allocations are not in the resident count); three daemons at once (Wikipedia, Hacker News, the test page) 447 MB against 341 MB, the device's free plus cached memory 324 MB against 476 MB, swap untouched, every daemon composited, LunaSysMgr kept its EGL;
tools/device/t502/three-daemons.sh) - An idle page on the GPU path uses no more CPU than on the software path (no compositing while nothing changes) (settled Wikipedia 41 against 42 CPU ticks in 30 s, no frame published on either path; the test page 17 against 17; Hacker News 24 against 65)
- Twenty card open/close cycles on the GPU path leave the GPU's memory (kgsl) and the daemon's resident memory flat within a stated margin (added 2026-10-19 by T-513's review: the pbuffers and targets each closed card left in the share group) (2026-10-19, the margin 1 MB over twenty: the GPU's buffers show in the daemon as
/dev/zeromappings. Before the fix ten cycles of the Enyo card on a test page took them from 45 to 205 MB (+16 MB a card) and the daemon's resident memory from 103 to 258 MB, the device's free memory down 157 MB; after it twenty cycles added 76 KB of mappings and resident memory stayed at 57 MB, every cycle on the GPU path) Dependencies: R1
R11: The code is fit to keep
Acceptance Criteria:
- The
[jihad-gpu]diagnostics left are bounded and off by default; the verify mode and the frame dumps stay (they are the test); everyJIHAD_GPU_*knob is listed intools/device/t502/README.md(2026-10-19, T-512: one gate in the engine (engine 0057,mozilla/gfx/JihadGpuLog.h) and one in the daemon (render/goanna/JihadGpuLog.h):JIHAD_GPU_LOG=1, or a device round'sJIHAD_GPU_TIMELINE/VERIFY/DUMP_EVERY; failures and fallbacks print anyway. The shipped daemons of all three interfaces logged three engine startup lines in a load, pan, pinch and close (default-check.sh); the daemon's log is capped at 2 MB. The 76 switches in the code are in the README) - The engine work is folded into the patch queue (
check-engine-pins.shandpatch-queue.sh --checkagree) anddocs/ENGINE-SOURCE.mdnames each patch (2026-10-19: the 57 patches reproduced UXP_PINbaaefa58exactly, the pins agreed, every patch had its row; 2026-10-24: 0058 added, the 58 reproduce7a872e8f) - A review (Codex by direct invocation, the inspector as backup) of the engine and daemon changes, every finding dispositioned (2026-10-19, T-513: Codex out of credits, so two inspectors read the daemon and the adapter over Tier 87's span and patches 0040-0057 and found twelve problems, all fixed; 2026-10-24: Codex by direct invocation read the fixes, T-499 and T-487 and found nine more, all fixed. Every finding with its disposition:
context/impl/impl-review-findings-gpu-2.md.) docs/RENDERING-OPTIONS.md,docs/PICKUP.mdand the README say what the GPU path does and what it measured (2026-10-19: RENDERING-OPTIONS' "What it does" and table with tonight's numbers and what it does not reach; the README's known issues; PICKUP's evening delta) Dependencies: R1-R10
R12: The owner's finger round
Acceptance Criteria:
- The owner pans, flicks, pinches and double-taps real pages on the GPU path in all three interfaces (
docs/FINGER-TESTS.md) and finds it smooth Dependencies: R1-R10 (BLOCKED-EXTERNAL: a person at the device)
Non-goals (this version)
- The video overlay (option 5) and a LunaSysMgr change (option 6): held back by the owner's pick.
- WebGL 2.
- The TouchPad Go (opal): no unit on the bench; the GPU path is untested there.
- Stock webOS 3.0.5: the bench runs CE 3.1.0 only (ask the owner before stock-only work).
References
docs/RENDERING-OPTIONS.md— the options, the chart, the pick, T-502's rounds and trapsdocs/PICKUP.md— 2026-10-17 deltatools/device/t502/README.md— the device scripts and knobs- memories:
compositor-scroll-traps,gpu-wedge-needs-a-reboot,verify-pans-by-dumps,verify-device-frames-by-eye,owner-tests-clash-with-pan-runs
Changelog
- 2026-10-18: created from T-502 (rounds 1-141) and the owner's finger test; R1-R12.
- 2026-10-18: R6 gains the sharpness criterion (the zoom's resolution) after T-504's rounds 162-186.
- 2026-10-18: R3 gains the overscan criterion (content past the view's edges during a pan) after T-505's rounds 187-201.