diff --git a/libraries/common/src/main/java/androidx/media3/common/util/GlUtil.java b/libraries/common/src/main/java/androidx/media3/common/util/GlUtil.java index 23f91f4052..91f2d57332 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/GlUtil.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/GlUtil.java @@ -16,7 +16,6 @@ package androidx.media3.common.util; import static android.opengl.EGL14.EGL_CONTEXT_CLIENT_VERSION; -import static android.opengl.EGL14.EGL_NO_SURFACE; import static android.opengl.GLU.gluErrorString; import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkState; @@ -804,9 +803,6 @@ public final class GlUtil { if (eglDisplay == null || eglSurface == null) { return; } - if (EGL14.eglGetCurrentSurface(EGL14.EGL_DRAW) == EGL_NO_SURFACE) { - return; - } EGL14.eglDestroySurface(eglDisplay, eglSurface); checkEglException("Error destroying surface"); diff --git a/libraries/effect/src/main/java/androidx/media3/effect/FinalShaderProgramWrapper.java b/libraries/effect/src/main/java/androidx/media3/effect/FinalShaderProgramWrapper.java index 7bfed03025..32bfe03016 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/FinalShaderProgramWrapper.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/FinalShaderProgramWrapper.java @@ -335,9 +335,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; return; } - if (outputSurfaceInfo != null - && this.outputSurfaceInfo != null - && !this.outputSurfaceInfo.surface.equals(outputSurfaceInfo.surface)) { + if (this.outputSurfaceInfo != null + && (outputSurfaceInfo == null + || !this.outputSurfaceInfo.surface.equals(outputSurfaceInfo.surface))) { + // Destroy outputEglSurface as soon as we lose reference to the corresponding Surface. + // outputEglSurface is a graphics buffer producer for a BufferQueue, and + // this.outputSurfaceInfo.surface is the associated consumer. The consumer owns the + // BufferQueue https://source.android.com/docs/core/graphics/arch-bq-gralloc#BufferQueue. + // If the consumer and the BufferQueue are released while the producer is still alive, EGL + // gets stuck trying to dequeue a new buffer from the released BufferQueue. This probably + // happens when the previously queued back buffer is ready for display. try { GlUtil.destroyEglSurface(eglDisplay, outputEglSurface); } catch (GlUtil.GlException e) { @@ -455,11 +462,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } checkNotNull(outputSizeBeforeSurfaceTransformation); - if (outputSurfaceInfo == null) { - GlUtil.destroyEglSurface(eglDisplay, outputEglSurface); - outputEglSurface = null; - } if (outputSurfaceInfo == null && textureOutputListener == null) { + checkState(outputEglSurface == null); if (defaultShaderProgram != null) { defaultShaderProgram.release(); defaultShaderProgram = null;