fix(gdeq031t10): only commit the shadow after the panel confirms - #607
Conversation
shadow_framebuffer records what the panel is currently showing, but both refresh paths updated it before the refresh was confirmed, so a failed trigger or a BUSY timeout left it describing content that was never displayed. That misdescription compounds: the shadow is sent to the controller as CMD_DATA_START_OLD, so the per-pixel transitions get computed from an image the panel never held, and draw_bitmap() diffs against it, so a region matching a wrong shadow is treated as clean and never repainted. Both paths now commit only after wait_while_busy() confirms. refresh_full() also sends new data straight from the render buffer, which drops a full-framebuffer copy from the path. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughFull refreshes now send data directly from the render bitmap and update the shadow framebuffer only after the panel confirms completion. Windowed refreshes similarly gather region data without modifying the shadow during transmission, then copy regions into the shadow only on successful refreshes. Failed writes, triggers, or completion waits leave the previous shadow content unchanged. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Thank you for fixing this!! |
Fixes #606.
shadow_framebufferis the driver's record of what the panel is currently showing. Both refresh paths update it before the panel confirms the refresh completed, so any failure leaves it describing content that was never displayed.refresh_full()copied the render buffer into the shadow, then used the shadow as the source for the new-data write. That copy happened before theCMD_DISPLAY_REFRESHtrigger and beforewait_while_busy(), so a failed trigger or a BUSY timeout still left the shadow updated.refresh_window()had the same shape: it wrote the shadow inside the gather loop that fillsregion_buffer, before the new-data write and before the confirm.The consequences compound, because the shadow is not just a change-detection cache:
CMD_DATA_START_OLD, so a wrong shadow makes the controller compute per-pixel transitions from an image the panel was never showing.draw_bitmap()diffs against it to find the changed bounding box, so a region that "matches" a wrong shadow is treated as clean and never redrawn. The panel then holds stale content indefinitely while the UI believes it was painted.Change
Commit the shadow only after the panel confirms:
refresh_full()sends new data straight fromrender_bitmapand copies into the shadow only oncewait_while_busy()returns true. This also removes a full-framebuffer copy from the path.refresh_window()gathersregion_bufferfromrender_bitmaponly, and copies the window into the shadow after the confirm.On failure the shadow keeps describing the previous content, so the next change scan still sees the region as dirty and repaints it.
refresh_window()is currently unreachable (draw_bitmap()setsforce_full_refreshunconditionally as a work-around), but it is fixed here so the behaviour is correct when partial updates are re-enabled.No functional change on the success path.
Testing
Built and run on a T-Deck Max (with #603 applied so the board boots): normal operation is unaffected, menus render and navigate as before.
Worth being straight about the limits of that: the success path is unchanged by design, so this confirms nothing is broken rather than demonstrating the fix. The bug only bites when a refresh fails, which is difficult to provoke deliberately. The reasoning is in #606.
Summary by CodeRabbit