Skip mpv renders that land after the app went to the background

Four build 270 crash logs abort inside the GL driver
(GLDContextRec::flushContextInternal) from presentRenderbuffer, reached
from the immediate render queued by appDidBecomeActive/resumeRendering.
Only displayLinkFired checked isInBackground; renders dispatched
directly to the render queue could run, or present, after the app was
backgrounded again, where GPU work is not permitted.

Check isInBackground at the top of performRender and again before
presenting. PiP rendering is unaffected.
This commit is contained in:
Arkadiusz Fal
2026-10-14 20:55:41 +02:00
parent eeee74f35f
commit 7d769f3541

View File

@@ -900,6 +900,16 @@ final class MPVRenderView: UIView {
private func performRender() {
defer { isRendering = false }
// GPU work is not permitted in the background, and presenting there
// aborts inside the GL driver. The display link already checks this,
// but renders queued by appDidBecomeActive/resumeRendering can run
// after the app went back to the background. PiP keeps rendering.
guard !isInBackground || isPiPActive else {
MPVLogging.log("performRender: skipped (app in background)")
return
}
let frameStart = Date()
let tFrameStart = CACurrentMediaTime()
let gapSincePrevFrame = lastRenderStartMediaTime > 0 ? tFrameStart - lastRenderStartMediaTime : 0
@@ -967,8 +977,11 @@ final class MPVRenderView: UIView {
let tRenderEnd = CACurrentMediaTime()
// Present the renderbuffer (skip when PiP is active - main view is hidden anyway)
if !isPiPActive {
// Present the renderbuffer (skip when PiP is active - main view is hidden anyway).
// Re-checked here: the app can enter the background while mpv renders.
if isInBackground && !isPiPActive {
MPVLogging.log("performRender: present skipped (app entered background)")
} else if !isPiPActive {
glBindRenderbuffer(GLenum(GL_RENDERBUFFER), colorRenderbuffer)
let presented = eaglContext.presentRenderbuffer(Int(GL_RENDERBUFFER))
if !presented {