Merge "Notify views when EGL resources are about to be destroyed Bug #5639899" into ics-mr1

This commit is contained in:
Romain Guy
2011-11-21 17:57:05 -08:00
committed by Android (Google) Code Review
6 changed files with 92 additions and 27 deletions

View File

@ -162,12 +162,20 @@ public abstract class HardwareRenderer {
abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
/**
* Destoys the layers used by the specified view hierarchy.
* Destroys the layers used by the specified view hierarchy.
*
* @param view The root of the view hierarchy
*/
abstract void destroyLayers(View view);
/**
* Destroys all hardware rendering resources associated with the specified
* view hierarchy.
*
* @param view The root of the view hierarchy
*/
abstract void destroyHardwareResources(View view);
/**
* This method should be invoked whenever the current hardware renderer
* context should be reset.
@ -347,15 +355,6 @@ public abstract class HardwareRenderer {
Gl20Renderer.trimMemory(level);
}
/**
* Invoke this method when the system needs to clean up all resources
* associated with hardware rendering.
*/
static void terminate() {
Log.d(LOG_TAG, "Terminating hardware rendering");
Gl20Renderer.terminate();
}
/**
* Indicates whether hardware acceleration is currently enabled.
*
@ -412,8 +411,8 @@ public abstract class HardwareRenderer {
static final Object[] sEglLock = new Object[0];
int mWidth = -1, mHeight = -1;
static final ThreadLocal<Gl20Renderer.MyEGLContext> sEglContextStorage
= new ThreadLocal<Gl20Renderer.MyEGLContext>();
static final ThreadLocal<Gl20Renderer.Gl20RendererEglContext> sEglContextStorage
= new ThreadLocal<Gl20Renderer.Gl20RendererEglContext>();
EGLContext mEglContext;
Thread mEglThread;
@ -565,13 +564,13 @@ public abstract class HardwareRenderer {
}
}
Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get();
Gl20Renderer.Gl20RendererEglContext managedContext = sEglContextStorage.get();
mEglContext = managedContext != null ? managedContext.getContext() : null;
mEglThread = Thread.currentThread();
if (mEglContext == null) {
mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
sEglContextStorage.set(new Gl20Renderer.MyEGLContext(mEglContext));
sEglContextStorage.set(new Gl20Renderer.Gl20RendererEglContext(mEglContext));
}
}
@ -909,10 +908,10 @@ public abstract class HardwareRenderer {
private static EGLSurface sPbuffer;
private static final Object[] sPbufferLock = new Object[0];
static class MyEGLContext extends ManagedEGLContext {
static class Gl20RendererEglContext extends ManagedEGLContext {
final Handler mHandler = new Handler();
public MyEGLContext(EGLContext context) {
public Gl20RendererEglContext(EGLContext context) {
super(context);
}
@ -939,7 +938,8 @@ public abstract class HardwareRenderer {
sEglContextStorage.remove();
sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
sEgl.eglReleaseThread();
sEgl.eglTerminate(sEglDisplay);
@ -1046,10 +1046,9 @@ public abstract class HardwareRenderer {
}
}
private void destroyHardwareLayer(View view) {
if (view.destroyLayer()) {
view.invalidate(true);
}
private static void destroyHardwareLayer(View view) {
view.destroyLayer();
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
@ -1059,6 +1058,36 @@ public abstract class HardwareRenderer {
}
}
}
@Override
void destroyHardwareResources(View view) {
if (view != null) {
boolean needsContext = true;
if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
if (needsContext) {
Gl20RendererEglContext managedContext = sEglContextStorage.get();
if (managedContext == null) return;
usePbufferSurface(managedContext.getContext());
}
destroyResources(view);
GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
}
}
private static void destroyResources(View view) {
view.destroyHardwareResources();
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
int count = group.getChildCount();
for (int i = 0; i < count; i++) {
destroyResources(group.getChildAt(i));
}
}
}
static HardwareRenderer create(boolean translucent) {
if (GLES20Canvas.isAvailable()) {
@ -1070,7 +1099,7 @@ public abstract class HardwareRenderer {
static void trimMemory(int level) {
if (sEgl == null || sEglConfig == null) return;
Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get();
Gl20RendererEglContext managedContext = sEglContextStorage.get();
// We do not have OpenGL objects
if (managedContext == null) {
return;

View File

@ -203,7 +203,10 @@ public class TextureView extends View {
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
destroySurface();
}
private void destroySurface() {
if (mLayer != null) {
boolean shouldRelease = true;
if (mListener != null) {
@ -300,6 +303,14 @@ public class TextureView extends View {
return false;
}
@Override
protected void destroyHardwareResources() {
super.destroyHardwareResources();
destroySurface();
invalidateParentCaches();
invalidate(true);
}
@Override
HardwareLayer getHardwareLayer() {
if (mLayer == null) {

View File

@ -10073,7 +10073,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
switch (mLayerType) {
case LAYER_TYPE_HARDWARE:
destroyLayer();
// fall through - unaccelerated views may use software layer mechanism instead
// fall through - non-accelerated views may use software layer mechanism instead
case LAYER_TYPE_SOFTWARE:
destroyDrawingCache();
break;
@ -10235,11 +10235,30 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (mHardwareLayer != null) {
mHardwareLayer.destroy();
mHardwareLayer = null;
invalidate(true);
invalidateParentCaches();
return true;
}
return false;
}
/**
* Destroys all hardware rendering resources. This method is invoked
* when the system needs to reclaim resources. Upon execution of this
* method, you should free any OpenGL resources created by the view.
*
* Note: you <strong>must</strong> call
* <code>super.destroyHardwareResources()</code> when overriding
* this method.
*
* @hide
*/
protected void destroyHardwareResources() {
destroyLayer();
}
/**
* <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
* to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a

View File

@ -576,6 +576,13 @@ public final class ViewRootImpl extends Handler implements ViewParent,
}
}
void terminateHardwareResources() {
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
mAttachInfo.mHardwareRenderer.destroy(false);
}
}
void destroyHardwareLayers() {
if (mThread != Thread.currentThread()) {
if (mAttachInfo.mHardwareRenderer != null &&

View File

@ -425,7 +425,7 @@ public class WindowManagerImpl implements WindowManager {
if (mViews == null) return;
int count = mViews.length;
for (int i = 0; i < count; i++) {
mRoots[i].destroyHardwareResources();
mRoots[i].terminateHardwareResources();
}
}
// Terminate the hardware renderer to free all resources

View File

@ -47,8 +47,7 @@ import com.google.android.gles_jni.EGLImpl;
public abstract class ManagedEGLContext {
static final String TAG = "ManagedEGLContext";
static final ArrayList<ManagedEGLContext> sActive
= new ArrayList<ManagedEGLContext>();
static final ArrayList<ManagedEGLContext> sActive = new ArrayList<ManagedEGLContext>();
final EGLContext mContext;
@ -127,7 +126,7 @@ public abstract class ManagedEGLContext {
sActive.clear();
}
for (int i=0; i<active.size(); i++) {
for (int i = 0; i < active.size(); i++) {
active.get(i).execTerminate();
}