Skip to content

Commit ef09a21

Browse files
author
Romain Guy
committed
Don't destroy the same texture twice
Bug #7221449 SurfaceTexture already deletes the GL texture when detachFromContext is invoked. The newly introduced refcount would casue the Layer object to be destroyed later and attempt to delete the GL texture again. By the time the second cleanup occurs, the texture name might have been reused by somebody else, resulting in erroneous behaviors. Change-Id: I257c589fea64b34c00f46fbfaa7732e6854a5e41
1 parent 509e2ce commit ef09a21

File tree

7 files changed

+38
-8
lines changed

7 files changed

+38
-8
lines changed

core/java/android/view/GLES20Canvas.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ void clearLayerUpdates() {
166166
static native void nSetLayerColorFilter(int layerId, int nativeColorFilter);
167167
static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque,
168168
SurfaceTexture surface);
169+
static native void nClearLayerTexture(int layerId);
169170
static native void nSetTextureLayerTransform(int layerId, int matrix);
170171
static native void nDestroyLayer(int layerId);
171172
static native void nDestroyLayerDeferred(int layerId);

core/java/android/view/GLES20Layer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ void destroy() {
6666
mLayer = 0;
6767
}
6868

69+
@Override
70+
void clearStorage() {
71+
if (mLayer != 0) GLES20Canvas.nClearLayerTexture(mLayer);
72+
}
73+
6974
static class Finalizer {
7075
private int mLayerId;
7176

core/java/android/view/GLES20TextureLayer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class GLES20TextureLayer extends GLES20Layer {
3939
mFinalizer = new Finalizer(mLayer);
4040
} else {
4141
mFinalizer = null;
42-
}
42+
}
4343
}
4444

4545
@Override

core/java/android/view/HardwareLayer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,9 @@ void update(int width, int height, boolean isOpaque) {
204204
* @param dirtyRect The dirty region of the layer that needs to be redrawn
205205
*/
206206
abstract void redrawLater(DisplayList displayList, Rect dirtyRect);
207+
208+
/**
209+
* Indicates that this layer has lost its underlying storage.
210+
*/
211+
abstract void clearStorage();
207212
}

core/java/android/view/TextureView.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ public void run() {
224224
private void destroySurface() {
225225
if (mLayer != null) {
226226
mSurface.detachFromGLContext();
227+
mLayer.clearStorage();
227228

228229
boolean shouldRelease = true;
229230
if (mListener != null) {

core/jni/android_view_GLES20Canvas.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,11 @@ static void android_view_GLES20Canvas_updateRenderLayer(JNIEnv* env, jobject cla
822822
layer->updateDeferred(renderer, displayList, left, top, right, bottom);
823823
}
824824

825+
static void android_view_GLES20Canvas_clearLayerTexture(JNIEnv* env, jobject clazz,
826+
Layer* layer) {
827+
layer->clearTexture();
828+
}
829+
825830
static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz,
826831
Layer* layer, SkMatrix* matrix) {
827832

@@ -1016,6 +1021,7 @@ static JNINativeMethod gMethods[] = {
10161021
{ "nUpdateTextureLayer", "(IIIZLandroid/graphics/SurfaceTexture;)V",
10171022
(void*) android_view_GLES20Canvas_updateTextureLayer },
10181023
{ "nUpdateRenderLayer", "(IIIIIII)V", (void*) android_view_GLES20Canvas_updateRenderLayer },
1024+
{ "nClearLayerTexture", "(I)V", (void*) android_view_GLES20Canvas_clearLayerTexture },
10191025
{ "nDestroyLayer", "(I)V", (void*) android_view_GLES20Canvas_destroyLayer },
10201026
{ "nDestroyLayerDeferred", "(I)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred },
10211027
{ "nDrawLayer", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawLayer },

libs/hwui/Layer.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,6 @@ struct Layer {
134134
return fbo;
135135
}
136136

137-
inline GLuint* getTexturePointer() {
138-
return &texture.id;
139-
}
140-
141137
inline GLuint getTexture() {
142138
return texture.id;
143139
}
@@ -181,15 +177,31 @@ struct Layer {
181177
ANDROID_API void setColorFilter(SkiaColorFilter* filter);
182178

183179
inline void bindTexture() {
184-
glBindTexture(renderTarget, texture.id);
180+
if (texture.id) {
181+
glBindTexture(renderTarget, texture.id);
182+
}
185183
}
186184

187185
inline void generateTexture() {
188-
glGenTextures(1, &texture.id);
186+
if (!texture.id) {
187+
glGenTextures(1, &texture.id);
188+
}
189189
}
190190

191191
inline void deleteTexture() {
192-
if (texture.id) glDeleteTextures(1, &texture.id);
192+
if (texture.id) {
193+
glDeleteTextures(1, &texture.id);
194+
texture.id = 0;
195+
}
196+
}
197+
198+
/**
199+
* When the caller frees the texture itself, the caller
200+
* must call this method to tell this layer that it lost
201+
* the texture.
202+
*/
203+
void clearTexture() {
204+
texture.id = 0;
193205
}
194206

195207
inline void deleteFbo() {

0 commit comments

Comments
 (0)