Flutter Engine
The Flutter Engine
SurfaceTextureWrapper.java
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package io.flutter.embedding.engine.renderer;
6
7import android.graphics.SurfaceTexture;
8import androidx.annotation.Keep;
9import androidx.annotation.NonNull;
10import androidx.annotation.Nullable;
11
12/**
13 * A wrapper for a SurfaceTexture that tracks whether the texture has been released.
14 *
15 * <p>The engine calls {@code SurfaceTexture.release} on the platform thread, but {@code
16 * updateTexImage} is called on the raster thread. This wrapper will prevent {@code updateTexImage}
17 * calls on an abandoned texture.
18 */
19@Keep
21 private SurfaceTexture surfaceTexture;
22 private boolean released;
23 private boolean attached;
24 private Runnable onFrameConsumed;
25 private boolean newFrameAvailable = false;
26
27 public SurfaceTextureWrapper(@NonNull SurfaceTexture surfaceTexture) {
28 this(surfaceTexture, null);
29 }
30
31 /**
32 * A wrapper for a SurfaceTexture.
33 *
34 * <p>The provided {@code onFrameConsumed} callback must be invoked when the most recent image was
35 * consumed.
36 *
37 * @param onFrameConsumed The callback after the {@code updateTexImage} is called.
38 */
40 @NonNull SurfaceTexture surfaceTexture, @Nullable Runnable onFrameConsumed) {
41 this.surfaceTexture = surfaceTexture;
42 this.released = false;
43 this.onFrameConsumed = onFrameConsumed;
44 }
45
46 @NonNull
47 public SurfaceTexture surfaceTexture() {
48 return surfaceTexture;
49 }
50
51 public void markDirty() {
52 synchronized (this) {
53 newFrameAvailable = true;
54 }
55 }
56
57 public boolean shouldUpdate() {
58 synchronized (this) {
59 return newFrameAvailable;
60 }
61 }
62
63 // Called by native.
64 @SuppressWarnings("unused")
65 public void updateTexImage() {
66 synchronized (this) {
67 newFrameAvailable = false;
68 if (!released) {
69 surfaceTexture.updateTexImage();
70 if (onFrameConsumed != null) {
71 onFrameConsumed.run();
72 }
73 }
74 }
75 }
76
77 public void release() {
78 synchronized (this) {
79 if (!released) {
80 surfaceTexture.release();
81 released = true;
82 attached = false;
83 }
84 }
85 }
86
87 // Called by native.
88 @SuppressWarnings("unused")
89 public void attachToGLContext(int texName) {
90 synchronized (this) {
91 if (released) {
92 return;
93 }
94 // When the rasterizer tasks run on a different thread, the GrContext is re-created.
95 // This causes the texture to be in an uninitialized state.
96 // This should *not* be an issue once platform views are always rendered as TextureLayers
97 // since thread merging will be always disabled on Android.
98 // For more see: SurfaceTextureExternalTextureGL::OnGrContextCreated in
99 // surface_texture_external_texture_gl.cc, and
100 // https://github.com/flutter/flutter/issues/98155
101 if (attached) {
102 surfaceTexture.detachFromGLContext();
103 }
104 surfaceTexture.attachToGLContext(texName);
105 attached = true;
106 }
107 }
108
109 // Called by native.
110 @SuppressWarnings("unused")
111 public void detachFromGLContext() {
112 synchronized (this) {
113 if (attached && !released) {
114 surfaceTexture.detachFromGLContext();
115 attached = false;
116 }
117 }
118 }
119
120 // Called by native.
121 @SuppressWarnings("unused")
122 public void getTransformMatrix(@NonNull float[] mtx) {
123 surfaceTexture.getTransformMatrix(mtx);
124 }
125}
SurfaceTextureWrapper( @NonNull SurfaceTexture surfaceTexture, @Nullable Runnable onFrameConsumed)
SurfaceTextureWrapper(@NonNull SurfaceTexture surfaceTexture)