Rebind the compositor when the Surface changes size

A foldable opening or closing resizes the Surface rather than recreating it.
The compositor's swapchain, built for the old size, kept presenting, and the
system scaled those buffers onto the new window — on a Fold a 16:9 picture
came back stretched to the square panel, the same width and 2.09x the height.
Rebinding the window on a size change rebuilds the swapchain at the new size,
and the fit mode letterboxes as it should.
This commit is contained in:
The412Banner committed 2026-09-19 16:35:53 -04:00
1 parent 033db93058
commit de1bfb6b94
2 files changed
+28 -1

No files matched your search

@@ -226,9 +226,22 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
applyFrameGen()
}
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {}
private var surfaceW = 0
private var surfaceH = 0
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
val resized = surfaceW != 0 && (width != surfaceW || height != surfaceH)
surfaceW = width
surfaceH = height
if (resized) {
Log.i(TAG, "surface resized to ${width}x$height — rebinding the compositor")
CompositorHost.resize(holder.surface)
}
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
surfaceW = 0
surfaceH = 0
CompositorHost.detach()
}
@@ -48,6 +48,20 @@ object CompositorHost {
return true
}
/**
* The Surface changed size under the compositor (a foldable opening or closing). Android does
* not always recreate the Surface for that, and a swapchain built for the old size keeps
* presenting: the system then scales those buffers onto the new window, which on a Fold showed
* a 16:9 picture stretched to the square panel. Rebinding the window rebuilds the swapchain at
* the new size, and the scale mode letterboxes as it should.
*/
@Synchronized
fun resize(surface: Surface) {
if (!started) return
WaylandCompositor.nativeSetSurface(null)
WaylandCompositor.nativeSetSurface(surface)
}
/**
* The activity is going away. The compositor keeps running with nothing to present into —
* the guest carries on, and its next frames land on the Surface the next activity brings.