Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 81a87c8

Browse files
author
Emmanuel Garcia
authored
Detach from GL context before attaching (#31390)
1 parent 4615f15 commit 81a87c8

File tree

2 files changed

+104
-3
lines changed

2 files changed

+104
-3
lines changed

shell/platform/android/io/flutter/embedding/engine/renderer/SurfaceTextureWrapper.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
public class SurfaceTextureWrapper {
2020
private SurfaceTexture surfaceTexture;
2121
private boolean released;
22+
private boolean attached;
2223

2324
public SurfaceTextureWrapper(@NonNull SurfaceTexture surfaceTexture) {
2425
this.surfaceTexture = surfaceTexture;
@@ -45,6 +46,7 @@ public void release() {
4546
if (!released) {
4647
surfaceTexture.release();
4748
released = true;
49+
attached = false;
4850
}
4951
}
5052
}
@@ -53,16 +55,33 @@ public void release() {
5355
@SuppressWarnings("unused")
5456
public void attachToGLContext(int texName) {
5557
synchronized (this) {
56-
if (!released) {
57-
surfaceTexture.attachToGLContext(texName);
58+
if (released) {
59+
return;
60+
}
61+
// When the rasterizer tasks run on a different thread, the GrContext is re-created.
62+
// This causes the texture to be in an uninitialized state.
63+
// This should *not* be an issue once platform views are always rendered as TextureLayers
64+
// since thread merging will be always disabled on Android.
65+
// For more see: AndroidExternalTextureGL::OnGrContextCreated in
66+
// android_external_texture_gl.cc, and
67+
// https://github.com/flutter/flutter/issues/98155
68+
if (attached) {
69+
surfaceTexture.detachFromGLContext();
5870
}
71+
surfaceTexture.attachToGLContext(texName);
72+
attached = true;
5973
}
6074
}
6175

6276
// Called by native.
6377
@SuppressWarnings("unused")
6478
public void detachFromGLContext() {
65-
surfaceTexture.detachFromGLContext();
79+
synchronized (this) {
80+
if (attached && !released) {
81+
surfaceTexture.detachFromGLContext();
82+
attached = false;
83+
}
84+
}
6685
}
6786

6887
// Called by native.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package io.flutter.embedding.engine.renderer;
2+
3+
import static junit.framework.TestCase.*;
4+
import static org.mockito.Mockito.*;
5+
6+
import android.graphics.SurfaceTexture;
7+
import androidx.test.ext.junit.runners.AndroidJUnit4;
8+
import org.junit.Test;
9+
import org.junit.runner.RunWith;
10+
11+
@RunWith(AndroidJUnit4.class)
12+
public class SurfaceTextureWrapperTest {
13+
14+
@Test
15+
public void attachToGLContext() {
16+
final SurfaceTexture tx = mock(SurfaceTexture.class);
17+
final SurfaceTextureWrapper wrapper = new SurfaceTextureWrapper(tx);
18+
19+
wrapper.attachToGLContext(0);
20+
verify(tx, times(1)).attachToGLContext(0);
21+
verifyNoMoreInteractions(tx);
22+
}
23+
24+
@Test
25+
public void attachToGLContext_detachesFromCurrentContext() {
26+
final SurfaceTexture tx = mock(SurfaceTexture.class);
27+
final SurfaceTextureWrapper wrapper = new SurfaceTextureWrapper(tx);
28+
29+
wrapper.attachToGLContext(0);
30+
31+
reset(tx);
32+
33+
wrapper.attachToGLContext(0);
34+
verify(tx, times(1)).detachFromGLContext();
35+
verify(tx, times(1)).attachToGLContext(0);
36+
verifyNoMoreInteractions(tx);
37+
}
38+
39+
@Test
40+
public void attachToGLContext_doesNotDetacheFromCurrentContext() {
41+
final SurfaceTexture tx = mock(SurfaceTexture.class);
42+
final SurfaceTextureWrapper wrapper = new SurfaceTextureWrapper(tx);
43+
44+
wrapper.attachToGLContext(0);
45+
46+
wrapper.detachFromGLContext();
47+
48+
reset(tx);
49+
50+
wrapper.attachToGLContext(0);
51+
verify(tx, times(1)).attachToGLContext(0);
52+
verifyNoMoreInteractions(tx);
53+
}
54+
55+
@Test
56+
public void detachFromGLContext() {
57+
final SurfaceTexture tx = mock(SurfaceTexture.class);
58+
final SurfaceTextureWrapper wrapper = new SurfaceTextureWrapper(tx);
59+
60+
wrapper.attachToGLContext(0);
61+
reset(tx);
62+
63+
wrapper.detachFromGLContext();
64+
verify(tx, times(1)).detachFromGLContext();
65+
verifyNoMoreInteractions(tx);
66+
}
67+
68+
@Test
69+
public void release() {
70+
final SurfaceTexture tx = mock(SurfaceTexture.class);
71+
final SurfaceTextureWrapper wrapper = new SurfaceTextureWrapper(tx);
72+
73+
wrapper.release();
74+
75+
verify(tx, times(1)).release();
76+
reset(tx);
77+
78+
wrapper.detachFromGLContext();
79+
wrapper.attachToGLContext(0);
80+
verifyNoMoreInteractions(tx);
81+
}
82+
}

0 commit comments

Comments
 (0)