From 1c0bd6dbb183780771b458138aae03c12193d93c Mon Sep 17 00:00:00 2001 From: Emmanuel Garcia Date: Thu, 10 Feb 2022 19:50:05 -0800 Subject: [PATCH 1/6] Detach from GL context before attaching --- .../renderer/SurfaceTextureWrapper.java | 21 +++++- .../renderer/SurfaceTextureWrapperTest.java | 69 +++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java diff --git a/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java b/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java index b9a9c57d95de4..f951cf3ddaaed 100644 --- a/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java +++ b/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java @@ -19,6 +19,7 @@ public class SurfaceTextureWrapper { private SurfaceTexture surfaceTexture; private boolean released; + private boolean attached; public SurfaceTextureWrapper(@NonNull SurfaceTexture surfaceTexture) { this.surfaceTexture = surfaceTexture; @@ -45,6 +46,7 @@ public void release() { if (!released) { surfaceTexture.release(); released = true; + attached = false; } } } @@ -53,8 +55,20 @@ public void release() { @SuppressWarnings("unused") public void attachToGLContext(int texName) { synchronized (this) { + // When the rasterizer tasks run on a different thread, the GrContext is re-created. + // This causes the texture to be in an uninitialized state. + // This should *not* be an issue once platform views are always rendered as TextureLayers + // since thread merging will be always disabled on Android. + // For more see: AndroidExternalTextureGL::OnGrContextCreated in + // android_external_texture_gl.cc, and + // https://github.com/flutter/flutter/issues/98155 + if (attached) { + surfaceTexture.detachFromGLContext(); + attached = false; + } if (!released) { surfaceTexture.attachToGLContext(texName); + attached = true; } } } @@ -62,7 +76,12 @@ public void attachToGLContext(int texName) { // Called by native. @SuppressWarnings("unused") public void detachFromGLContext() { - surfaceTexture.detachFromGLContext(); + synchronized (this) { + if (!released) { + surfaceTexture.detachFromGLContext(); + attached = false; + } + } } // Called by native. diff --git a/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java b/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java new file mode 100644 index 0000000000000..e3c40b3c1d1f6 --- /dev/null +++ b/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java @@ -0,0 +1,69 @@ +package io.flutter.embedding.engine.renderer; + +import static junit.framework.TestCase.*; +import static org.mockito.Mockito.*; + +import android.graphics.SurfaceTexture; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class SurfaceTextureWrapperTest { + + private SurfaceTextureWrapper textureWrapper; + + @Test + public void attachToGLContext() { + final SurfaceTexture tx = mock(SurfaceTexture.class); + final SurfaceTextureWrapper wrapper = new SurfaceTextureWrapper(tx); + + wrapper.attachToGLContext(0); + verify(tx, times(1)).attachToGLContext(0); + verifyNoMoreInteractions(tx); + } + + @Test + public void attachToGLContext_detachesFromCurrentContext() { + final SurfaceTexture tx = mock(SurfaceTexture.class); + final SurfaceTextureWrapper wrapper = new SurfaceTextureWrapper(tx); + + wrapper.attachToGLContext(0); + + reset(tx); + + wrapper.attachToGLContext(0); + verify(tx, times(1)).detachFromGLContext(); + verify(tx, times(1)).attachToGLContext(0); + verifyNoMoreInteractions(tx); + } + + @Test + public void attachToGLContext_doesNotDetacheFromCurrentContext() { + final SurfaceTexture tx = mock(SurfaceTexture.class); + final SurfaceTextureWrapper wrapper = new SurfaceTextureWrapper(tx); + + wrapper.attachToGLContext(0); + + wrapper.detachFromGLContext(); + + reset(tx); + + wrapper.attachToGLContext(0); + verify(tx, times(1)).attachToGLContext(0); + verifyNoMoreInteractions(tx); + } + + @Test + public void detachFromGLContext() { + final SurfaceTexture tx = mock(SurfaceTexture.class); + final SurfaceTextureWrapper wrapper = new SurfaceTextureWrapper(tx); + + wrapper.attachToGLContext(0); + reset(tx); + + wrapper.detachFromGLContext(); + verify(tx, times(1)).detachFromGLContext(); + verifyNoMoreInteractions(tx); + } +} From 436a96709c8362b16d60971fb6c60d428842b30a Mon Sep 17 00:00:00 2001 From: Emmanuel Garcia Date: Thu, 10 Feb 2022 19:56:38 -0800 Subject: [PATCH 2/6] Remove --- .../embedding/engine/renderer/SurfaceTextureWrapperTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java b/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java index e3c40b3c1d1f6..68d2b18683c55 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java @@ -11,8 +11,6 @@ @RunWith(AndroidJUnit4.class) public class SurfaceTextureWrapperTest { - private SurfaceTextureWrapper textureWrapper; - @Test public void attachToGLContext() { final SurfaceTexture tx = mock(SurfaceTexture.class); From b9295eb534db6b96660db5e0aa0200d5b1a6bb14 Mon Sep 17 00:00:00 2001 From: Emmanuel Garcia Date: Thu, 10 Feb 2022 19:57:36 -0800 Subject: [PATCH 3/6] Add line --- .../embedding/engine/renderer/SurfaceTextureWrapperTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java b/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java index 68d2b18683c55..6ac2d264230a3 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java @@ -64,4 +64,5 @@ public void detachFromGLContext() { verify(tx, times(1)).detachFromGLContext(); verifyNoMoreInteractions(tx); } + } From afd880dbf7de45f55c15112dfaf46e7a8d162b26 Mon Sep 17 00:00:00 2001 From: Emmanuel Garcia Date: Fri, 11 Feb 2022 11:00:48 -0800 Subject: [PATCH 4/6] checks --- .../engine/renderer/SurfaceTextureWrapper.java | 4 ++-- .../renderer/SurfaceTextureWrapperTest.java | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java b/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java index f951cf3ddaaed..33b01459fa450 100644 --- a/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java +++ b/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java @@ -66,7 +66,7 @@ public void attachToGLContext(int texName) { surfaceTexture.detachFromGLContext(); attached = false; } - if (!released) { + if (!attached && !released) { surfaceTexture.attachToGLContext(texName); attached = true; } @@ -77,7 +77,7 @@ public void attachToGLContext(int texName) { @SuppressWarnings("unused") public void detachFromGLContext() { synchronized (this) { - if (!released) { + if (attached && !released) { surfaceTexture.detachFromGLContext(); attached = false; } diff --git a/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java b/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java index 6ac2d264230a3..16219fdeba8cd 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java @@ -65,4 +65,19 @@ public void detachFromGLContext() { verifyNoMoreInteractions(tx); } + @Test + public void release() { + final SurfaceTexture tx = mock(SurfaceTexture.class); + final SurfaceTextureWrapper wrapper = new SurfaceTextureWrapper(tx); + + wrapper.attachToGLContext(0); + wrapper.release(); + + verify(tx, times(1)).release(); + reset(tx); + + wrapper.detachFromGLContext(); + wrapper.attachToGLContext(0); + verifyNoMoreInteractions(tx); + } } From 918de354a386faa79f915162ab426a611543d06e Mon Sep 17 00:00:00 2001 From: Emmanuel Garcia Date: Fri, 11 Feb 2022 11:03:10 -0800 Subject: [PATCH 5/6] No need to call attachToGLContext --- .../embedding/engine/renderer/SurfaceTextureWrapperTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java b/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java index 16219fdeba8cd..a9395f675235a 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/renderer/SurfaceTextureWrapperTest.java @@ -70,7 +70,6 @@ public void release() { final SurfaceTexture tx = mock(SurfaceTexture.class); final SurfaceTextureWrapper wrapper = new SurfaceTextureWrapper(tx); - wrapper.attachToGLContext(0); wrapper.release(); verify(tx, times(1)).release(); From b7970793fb3bdd79ccb84d0a78659d18253aefb4 Mon Sep 17 00:00:00 2001 From: Emmanuel Garcia Date: Fri, 11 Feb 2022 11:26:38 -0800 Subject: [PATCH 6/6] Simplify --- .../engine/renderer/SurfaceTextureWrapper.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java b/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java index 33b01459fa450..55f183c6c6cd6 100644 --- a/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java +++ b/shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java @@ -55,6 +55,9 @@ public void release() { @SuppressWarnings("unused") public void attachToGLContext(int texName) { synchronized (this) { + if (released) { + return; + } // When the rasterizer tasks run on a different thread, the GrContext is re-created. // This causes the texture to be in an uninitialized state. // This should *not* be an issue once platform views are always rendered as TextureLayers @@ -64,12 +67,9 @@ public void attachToGLContext(int texName) { // https://github.com/flutter/flutter/issues/98155 if (attached) { surfaceTexture.detachFromGLContext(); - attached = false; - } - if (!attached && !released) { - surfaceTexture.attachToGLContext(texName); - attached = true; } + surfaceTexture.attachToGLContext(texName); + attached = true; } }