Skip to content

fix(viewer): stop webpage transitions flashing a foreign page - #3160

Merged
vpetersson merged 3 commits into
masterfrom
worktree-twinkly-frolicking-treasure
Jul 8, 2026
Merged

fix(viewer): stop webpage transitions flashing a foreign page#3160
vpetersson merged 3 commits into
masterfrom
worktree-twinkly-frolicking-treasure

Conversation

@vpetersson

@vpetersson vpetersson commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Issues Fixed

Fixes #2954 — webpage asset transitions briefly flash another page in rotation.

Description

On the Qt6 boards (Pi 5 / x86 on Wayland/cage, pi4-64 on eglfs) the viewer
rendered URL assets through a two-QWebEngineView ping-pong: the next page
was loaded into an off-screen buffer and swapped in on loadFinished. But a
hidden or sibling-occluded QWebEngineView is frame-callback-throttled by
Chromium on the single fullscreen surface these boards use — it never
composited the preloaded page. So the swap revealed a buffer whose GPU
surface still held the page it had last shown two rotations earlier,
which flashed for ~1 frame before the new page painted — an unrelated asset
on every webpage→webpage transition.

The fix collapses webpage rendering to a single QWebEngineView on every
board (the path the 1 GB low-RAM boards already ran). An in-place load()
on the visible view keeps the current page composited until the next one
paints, so transitions are seamless — at worst a brief black frame, never a
foreign page. The now-obsolete ANTHIAS_LOW_RAM viewer flag and its
compose/upgrade plumbing are removed; the independent 1080p upload cap
(is_low_ram_device via host:total_mem_kb) is untouched. Reclaims the
~100 MB the second renderer cost on 2 GB+ boards as a bonus.

Validation (live on a Pi 5, grim burst-capture of a 4-page 10 s
rotation): baseline flashed the exact (n-2) page at every transition; after
the fix, 0 foreign flashes across 7 transitions, all seamless.

Memory & slow-load regression check

Removing ANTHIAS_LOW_RAM makes single-view universal, so the natural
question is whether the 2 GB+ boards lose the dual-buffer's seamless
crossfade and instead get the "brief blank during load" that #2915's commit
message noted for the 1 GB path. Measured on a Pi 5 with a page whose
HTTP response is delayed 5 s, rotated against instant pages, dual-buffer vs
single-view side by side (grim burst-capture, 1205 frames each):

Dual-buffer (before) Single-view (this PR)
Previous page held during the 5 s load yes (~13 s total) yes (~13 s total)
Near-black frames (of 1205) 0 0
Foreign flash (#2954) every transition none
QtWebEngine renderers 2 (~100 MB extra) 1

QtWebEngine holds the last composited frame across an in-place load()
until the new page first-paints, even for a multi-second load — so there is
no blank-during-load regression; single-view is seamless and
flash-free. The 1080p upload cap and the diagnostics "Low-RAM mode" banner
are unaffected (separate is_low_ram_device() / host:total_mem_kb path).

On the RockPi 4 (1 GB) the change is a no-op — it already ran single-view
(ANTHIAS_LOW_RAM=1); verified 1 QtWebEngine renderer, stable memory while
cycling webpage assets.

Checklist

  • I have performed a self-review of my own code.
  • New and existing unit tests pass locally and on CI with my changes (no test-surface change; C++/shell/docs only).
  • I have done an end-to-end test for Raspberry Pi devices (full stack on a Pi 5, real display).
  • I have tested my changes for x86 devices (not tested; same Qt6/cage single-surface path, fix applies).
  • I added a documentation for the changes I have made (when necessary).

- Collapse the webpage renderer to a single QWebEngineView on every
  board, not just low-RAM ones
- The preloaded second buffer never composited its new page on the
  Qt6 boards' single fullscreen surface (hidden/occluded QWebEngineView
  is frame-throttled), so revealing it flashed the page it last showed
  two rotations earlier for ~1 frame on each transition
- An in-place load() on the visible view holds the current page until
  the next paints: seamless, at worst a brief black frame, never a
  foreign page
- Drop the now-obsolete ANTHIAS_LOW_RAM viewer flag and its plumbing;
  the independent 1080p upload cap (host:total_mem_kb) is untouched
- Reclaims ~100 MB on 2 GB+ boards as a bonus

Live-reproduced and fix live-verified on a Pi 5: every transition
flashed the (n-2) page before, none after.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@vpetersson
vpetersson requested a review from a team as a code owner July 8, 2026 14:43
@vpetersson vpetersson self-assigned this Jul 8, 2026
@vpetersson
vpetersson requested a review from Copilot July 8, 2026 14:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes webpage→webpage transitions that briefly flashed an unrelated (“n-2”) page on Qt6 single-surface platforms by removing the off-screen preloaded QWebEngineView path and standardizing on a single in-place QWebEngineView navigation model across all boards.

Changes:

  • Collapse webpage rendering to a single QWebEngineView unconditionally; remove the legacy ANTHIAS_LOW_RAM-gated dual-buffer mode.
  • Remove ANTHIAS_LOW_RAM plumbing from container upgrade/export and compose template.
  • Update board enablement documentation to reflect the new single-view renderer behavior and rationale.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/anthias_webview/src/view.cpp Removes low-RAM gating and aliases webView2 to webView1 to eliminate off-screen preloading that caused stale-frame flashes.
docs/board-enablement.md Updates “Low-RAM mode” section to document removal of the preloaded second QWebEngineView path and why.
docker-compose.yml.tmpl Removes ANTHIAS_LOW_RAM from viewer container environment.
bin/upgrade_containers.sh Removes ANTHIAS_LOW_RAM export logic; documents new behavior and notes upload cap remains server-side.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/anthias_webview/src/view.cpp Outdated
Comment thread src/anthias_webview/src/view.cpp
Addresses review feedback on the #2954 fix. With webView2 aliased onto
webView1 the swap only hid then re-showed the same widget and swapped
two pointers that always alias; the "no-op" comment was also
inaccurate.

- Add a `currentWebView == nextWebView` fast path: show the one view
  (it may have been hidden by a preceding image/video asset) and arm
  the refresh timer, skipping the pointless hide/show toggle and swap
- Correct the constructor comment accordingly

No behaviour change for webpage rotation; re-verified on a Pi 5 that
webpage→webpage stays flash-free and image→webpage still shows the page.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

Comment thread src/anthias_webview/src/view.cpp
Copilot review follow-up: with the single-view collapse there is no
off-screen buffer, so the load log lines saying "background web view" /
"Background web page" were misleading during troubleshooting. Reword to
plain "Loading web page" / "Web page loaded|failed". Log-string only, no
behaviour change.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@vpetersson
vpetersson requested a review from Copilot July 8, 2026 15:27
@sonarqubecloud

sonarqubecloud Bot commented Jul 8, 2026

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated no new comments.

@vpetersson
vpetersson merged commit 290929a into master Jul 8, 2026
8 checks passed
@vpetersson
vpetersson deleted the worktree-twinkly-frolicking-treasure branch July 8, 2026 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Webpage asset transitions briefly flash another page in rotation

2 participants