fix(service): update viewport on GL thread per rotation, reuse EGL surface - #14
Merged
Merged
Conversation
…rface Symptom: after rotating the device the wallpaper only covered a corner region of the screen (bottom-left or bottom-right). Root cause: Engine.onSurfaceChanged called renderer.onSurfaceChanged on the UI thread. The orthographic matrix update (plain memory) took effect, but glViewport is a GL call and the EGL context is current on the GL thread, so the call was silently dropped - the viewport kept the old orientation and the newly-projected scene was squeezed into the old viewport rectangle. Additionally the EGL window surface was never recreated when the system destroyed and recreated the Surface, leaving swaps silently failing into a dead native window. Fix: route surface lifecycle through the GL thread. - Engine.onSurfaceCreated/Changed/Destroyed notify the GL thread via volatile flags instead of touching GL state directly. - A plain resize (typical rotation): the EGL window surface follows the native window, so only renderer.onSurfaceChanged (viewport + projection) runs on the GL thread - no EGL rebuild, no white flash, matching the pre-fix reuse behavior. - Surface destroy/recreate: release the EGL window surface (context kept, textures/programs survive) and rebuild it from the current holder Surface, retrying next frame if not valid yet. - The initial size is taken from the holder at thread start since engine notifications may predate thread startup.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix wallpaper covering only a screen corner after rotation
Problem
After rotating the device (landscape ⇄ portrait), the wallpaper only covered a corner region of the screen (bottom-left or bottom-right). The rest of the screen showed the compositor background.
Root cause
Engine.onSurfaceChangedcalledrenderer.onSurfaceChangedon the UI thread. The orthographic matrix update (plain memory) took effect, butglViewportis a GL call and the EGL context is current on the GL thread — a context can only be current on one thread at a time — so the call was silently dropped. The viewport kept the old orientation while the projection used the new one, squeezing the scene into the old viewport rectangle.Additionally, the EGL window surface was never recreated when the system destroyed and recreated the Surface, leaving swaps silently failing into a dead native window (the swap return value was never checked). This was a latent bug on ROMs that recreate the Surface on rotation.
Fix
Route the surface lifecycle through the GL thread via volatile flags instead of touching GL state from the engine thread:
renderer.onSurfaceChanged(viewport + projection) runs on the GL thread — no EGL rebuild, no white flash. The GL surface and textures stay fully reused, matching the pre-fix behavior.On the tested device, rotation resizes the surface in place, so the resize path is the exercised one; the destroy/recreate path is a robustness fix for ROMs that recreate the Surface.
Testing
compileDebugKotlin,testDebugUnitTest,ktlintCheckpass.