Skip to content

Commit 8cd39e3

Browse files
Romain GuyAndroid (Google) Code Review
authored andcommitted
Merge "Notify views when EGL resources are about to be destroyed Bug #5639899" into ics-mr1
2 parents fb0784d + 31f2c2e commit 8cd39e3

File tree

6 files changed

+92
-27
lines changed

6 files changed

+92
-27
lines changed

core/java/android/view/HardwareRenderer.java

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,20 @@ public static boolean isAvailable() {
162162
abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
163163

164164
/**
165-
* Destoys the layers used by the specified view hierarchy.
165+
* Destroys the layers used by the specified view hierarchy.
166166
*
167167
* @param view The root of the view hierarchy
168168
*/
169169
abstract void destroyLayers(View view);
170170

171+
/**
172+
* Destroys all hardware rendering resources associated with the specified
173+
* view hierarchy.
174+
*
175+
* @param view The root of the view hierarchy
176+
*/
177+
abstract void destroyHardwareResources(View view);
178+
171179
/**
172180
* This method should be invoked whenever the current hardware renderer
173181
* context should be reset.
@@ -347,15 +355,6 @@ static void trimMemory(int level) {
347355
Gl20Renderer.trimMemory(level);
348356
}
349357

350-
/**
351-
* Invoke this method when the system needs to clean up all resources
352-
* associated with hardware rendering.
353-
*/
354-
static void terminate() {
355-
Log.d(LOG_TAG, "Terminating hardware rendering");
356-
Gl20Renderer.terminate();
357-
}
358-
359358
/**
360359
* Indicates whether hardware acceleration is currently enabled.
361360
*
@@ -412,8 +411,8 @@ static abstract class GlRenderer extends HardwareRenderer {
412411
static final Object[] sEglLock = new Object[0];
413412
int mWidth = -1, mHeight = -1;
414413

415-
static final ThreadLocal<Gl20Renderer.MyEGLContext> sEglContextStorage
416-
= new ThreadLocal<Gl20Renderer.MyEGLContext>();
414+
static final ThreadLocal<Gl20Renderer.Gl20RendererEglContext> sEglContextStorage
415+
= new ThreadLocal<Gl20Renderer.Gl20RendererEglContext>();
417416

418417
EGLContext mEglContext;
419418
Thread mEglThread;
@@ -565,13 +564,13 @@ void initializeEgl() {
565564
}
566565
}
567566

568-
Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get();
567+
Gl20Renderer.Gl20RendererEglContext managedContext = sEglContextStorage.get();
569568
mEglContext = managedContext != null ? managedContext.getContext() : null;
570569
mEglThread = Thread.currentThread();
571570

572571
if (mEglContext == null) {
573572
mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
574-
sEglContextStorage.set(new Gl20Renderer.MyEGLContext(mEglContext));
573+
sEglContextStorage.set(new Gl20Renderer.Gl20RendererEglContext(mEglContext));
575574
}
576575
}
577576

@@ -909,10 +908,10 @@ static class Gl20Renderer extends GlRenderer {
909908
private static EGLSurface sPbuffer;
910909
private static final Object[] sPbufferLock = new Object[0];
911910

912-
static class MyEGLContext extends ManagedEGLContext {
911+
static class Gl20RendererEglContext extends ManagedEGLContext {
913912
final Handler mHandler = new Handler();
914913

915-
public MyEGLContext(EGLContext context) {
914+
public Gl20RendererEglContext(EGLContext context) {
916915
super(context);
917916
}
918917

@@ -939,7 +938,8 @@ public void onTerminate(final EGLContext eglContext) {
939938
sEglContextStorage.remove();
940939

941940
sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
942-
sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
941+
sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
942+
EGL_NO_SURFACE, EGL_NO_CONTEXT);
943943

944944
sEgl.eglReleaseThread();
945945
sEgl.eglTerminate(sEglDisplay);
@@ -1046,10 +1046,9 @@ void destroyLayers(View view) {
10461046
}
10471047
}
10481048

1049-
private void destroyHardwareLayer(View view) {
1050-
if (view.destroyLayer()) {
1051-
view.invalidate(true);
1052-
}
1049+
private static void destroyHardwareLayer(View view) {
1050+
view.destroyLayer();
1051+
10531052
if (view instanceof ViewGroup) {
10541053
ViewGroup group = (ViewGroup) view;
10551054

@@ -1059,6 +1058,36 @@ private void destroyHardwareLayer(View view) {
10591058
}
10601059
}
10611060
}
1061+
1062+
@Override
1063+
void destroyHardwareResources(View view) {
1064+
if (view != null) {
1065+
boolean needsContext = true;
1066+
if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
1067+
1068+
if (needsContext) {
1069+
Gl20RendererEglContext managedContext = sEglContextStorage.get();
1070+
if (managedContext == null) return;
1071+
usePbufferSurface(managedContext.getContext());
1072+
}
1073+
1074+
destroyResources(view);
1075+
GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
1076+
}
1077+
}
1078+
1079+
private static void destroyResources(View view) {
1080+
view.destroyHardwareResources();
1081+
1082+
if (view instanceof ViewGroup) {
1083+
ViewGroup group = (ViewGroup) view;
1084+
1085+
int count = group.getChildCount();
1086+
for (int i = 0; i < count; i++) {
1087+
destroyResources(group.getChildAt(i));
1088+
}
1089+
}
1090+
}
10621091

10631092
static HardwareRenderer create(boolean translucent) {
10641093
if (GLES20Canvas.isAvailable()) {
@@ -1070,7 +1099,7 @@ static HardwareRenderer create(boolean translucent) {
10701099
static void trimMemory(int level) {
10711100
if (sEgl == null || sEglConfig == null) return;
10721101

1073-
Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get();
1102+
Gl20RendererEglContext managedContext = sEglContextStorage.get();
10741103
// We do not have OpenGL objects
10751104
if (managedContext == null) {
10761105
return;

core/java/android/view/TextureView.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,10 @@ protected void onAttachedToWindow() {
203203
@Override
204204
protected void onDetachedFromWindow() {
205205
super.onDetachedFromWindow();
206+
destroySurface();
207+
}
206208

209+
private void destroySurface() {
207210
if (mLayer != null) {
208211
boolean shouldRelease = true;
209212
if (mListener != null) {
@@ -300,6 +303,14 @@ boolean destroyLayer() {
300303
return false;
301304
}
302305

306+
@Override
307+
protected void destroyHardwareResources() {
308+
super.destroyHardwareResources();
309+
destroySurface();
310+
invalidateParentCaches();
311+
invalidate(true);
312+
}
313+
303314
@Override
304315
HardwareLayer getHardwareLayer() {
305316
if (mLayer == null) {

core/java/android/view/View.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10073,7 +10073,7 @@ public void setLayerType(int layerType, Paint paint) {
1007310073
switch (mLayerType) {
1007410074
case LAYER_TYPE_HARDWARE:
1007510075
destroyLayer();
10076-
// fall through - unaccelerated views may use software layer mechanism instead
10076+
// fall through - non-accelerated views may use software layer mechanism instead
1007710077
case LAYER_TYPE_SOFTWARE:
1007810078
destroyDrawingCache();
1007910079
break;
@@ -10235,11 +10235,30 @@ boolean destroyLayer() {
1023510235
if (mHardwareLayer != null) {
1023610236
mHardwareLayer.destroy();
1023710237
mHardwareLayer = null;
10238+
10239+
invalidate(true);
10240+
invalidateParentCaches();
10241+
1023810242
return true;
1023910243
}
1024010244
return false;
1024110245
}
1024210246

10247+
/**
10248+
* Destroys all hardware rendering resources. This method is invoked
10249+
* when the system needs to reclaim resources. Upon execution of this
10250+
* method, you should free any OpenGL resources created by the view.
10251+
*
10252+
* Note: you <strong>must</strong> call
10253+
* <code>super.destroyHardwareResources()</code> when overriding
10254+
* this method.
10255+
*
10256+
* @hide
10257+
*/
10258+
protected void destroyHardwareResources() {
10259+
destroyLayer();
10260+
}
10261+
1024310262
/**
1024410263
* <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
1024510264
* to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a

core/java/android/view/ViewRootImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,13 @@ void destroyHardwareResources() {
576576
}
577577
}
578578

579+
void terminateHardwareResources() {
580+
if (mAttachInfo.mHardwareRenderer != null) {
581+
mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
582+
mAttachInfo.mHardwareRenderer.destroy(false);
583+
}
584+
}
585+
579586
void destroyHardwareLayers() {
580587
if (mThread != Thread.currentThread()) {
581588
if (mAttachInfo.mHardwareRenderer != null &&

core/java/android/view/WindowManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ public void trimMemory(int level) {
425425
if (mViews == null) return;
426426
int count = mViews.length;
427427
for (int i = 0; i < count; i++) {
428-
mRoots[i].destroyHardwareResources();
428+
mRoots[i].terminateHardwareResources();
429429
}
430430
}
431431
// Terminate the hardware renderer to free all resources

opengl/java/android/opengl/ManagedEGLContext.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@
4747
public abstract class ManagedEGLContext {
4848
static final String TAG = "ManagedEGLContext";
4949

50-
static final ArrayList<ManagedEGLContext> sActive
51-
= new ArrayList<ManagedEGLContext>();
50+
static final ArrayList<ManagedEGLContext> sActive = new ArrayList<ManagedEGLContext>();
5251

5352
final EGLContext mContext;
5453

@@ -127,7 +126,7 @@ public static boolean doTerminate() {
127126
sActive.clear();
128127
}
129128

130-
for (int i=0; i<active.size(); i++) {
129+
for (int i = 0; i < active.size(); i++) {
131130
active.get(i).execTerminate();
132131
}
133132

0 commit comments

Comments
 (0)