Merge "Notify views when EGL resources are about to be destroyed Bug #5639899" into ics-mr1
This commit is contained in:
@ -162,12 +162,20 @@ public abstract class HardwareRenderer {
|
|||||||
abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
|
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
|
* @param view The root of the view hierarchy
|
||||||
*/
|
*/
|
||||||
abstract void destroyLayers(View view);
|
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
|
* This method should be invoked whenever the current hardware renderer
|
||||||
* context should be reset.
|
* context should be reset.
|
||||||
@ -347,15 +355,6 @@ public abstract class HardwareRenderer {
|
|||||||
Gl20Renderer.trimMemory(level);
|
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.
|
* Indicates whether hardware acceleration is currently enabled.
|
||||||
*
|
*
|
||||||
@ -412,8 +411,8 @@ public abstract class HardwareRenderer {
|
|||||||
static final Object[] sEglLock = new Object[0];
|
static final Object[] sEglLock = new Object[0];
|
||||||
int mWidth = -1, mHeight = -1;
|
int mWidth = -1, mHeight = -1;
|
||||||
|
|
||||||
static final ThreadLocal<Gl20Renderer.MyEGLContext> sEglContextStorage
|
static final ThreadLocal<Gl20Renderer.Gl20RendererEglContext> sEglContextStorage
|
||||||
= new ThreadLocal<Gl20Renderer.MyEGLContext>();
|
= new ThreadLocal<Gl20Renderer.Gl20RendererEglContext>();
|
||||||
|
|
||||||
EGLContext mEglContext;
|
EGLContext mEglContext;
|
||||||
Thread mEglThread;
|
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;
|
mEglContext = managedContext != null ? managedContext.getContext() : null;
|
||||||
mEglThread = Thread.currentThread();
|
mEglThread = Thread.currentThread();
|
||||||
|
|
||||||
if (mEglContext == null) {
|
if (mEglContext == null) {
|
||||||
mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
|
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 EGLSurface sPbuffer;
|
||||||
private static final Object[] sPbufferLock = new Object[0];
|
private static final Object[] sPbufferLock = new Object[0];
|
||||||
|
|
||||||
static class MyEGLContext extends ManagedEGLContext {
|
static class Gl20RendererEglContext extends ManagedEGLContext {
|
||||||
final Handler mHandler = new Handler();
|
final Handler mHandler = new Handler();
|
||||||
|
|
||||||
public MyEGLContext(EGLContext context) {
|
public Gl20RendererEglContext(EGLContext context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -939,7 +938,8 @@ public abstract class HardwareRenderer {
|
|||||||
sEglContextStorage.remove();
|
sEglContextStorage.remove();
|
||||||
|
|
||||||
sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
|
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.eglReleaseThread();
|
||||||
sEgl.eglTerminate(sEglDisplay);
|
sEgl.eglTerminate(sEglDisplay);
|
||||||
@ -1046,10 +1046,9 @@ public abstract class HardwareRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void destroyHardwareLayer(View view) {
|
private static void destroyHardwareLayer(View view) {
|
||||||
if (view.destroyLayer()) {
|
view.destroyLayer();
|
||||||
view.invalidate(true);
|
|
||||||
}
|
|
||||||
if (view instanceof ViewGroup) {
|
if (view instanceof ViewGroup) {
|
||||||
ViewGroup group = (ViewGroup) view;
|
ViewGroup group = (ViewGroup) view;
|
||||||
|
|
||||||
@ -1060,6 +1059,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) {
|
static HardwareRenderer create(boolean translucent) {
|
||||||
if (GLES20Canvas.isAvailable()) {
|
if (GLES20Canvas.isAvailable()) {
|
||||||
return new Gl20Renderer(translucent);
|
return new Gl20Renderer(translucent);
|
||||||
@ -1070,7 +1099,7 @@ public abstract class HardwareRenderer {
|
|||||||
static void trimMemory(int level) {
|
static void trimMemory(int level) {
|
||||||
if (sEgl == null || sEglConfig == null) return;
|
if (sEgl == null || sEglConfig == null) return;
|
||||||
|
|
||||||
Gl20Renderer.MyEGLContext managedContext = sEglContextStorage.get();
|
Gl20RendererEglContext managedContext = sEglContextStorage.get();
|
||||||
// We do not have OpenGL objects
|
// We do not have OpenGL objects
|
||||||
if (managedContext == null) {
|
if (managedContext == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -203,7 +203,10 @@ public class TextureView extends View {
|
|||||||
@Override
|
@Override
|
||||||
protected void onDetachedFromWindow() {
|
protected void onDetachedFromWindow() {
|
||||||
super.onDetachedFromWindow();
|
super.onDetachedFromWindow();
|
||||||
|
destroySurface();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void destroySurface() {
|
||||||
if (mLayer != null) {
|
if (mLayer != null) {
|
||||||
boolean shouldRelease = true;
|
boolean shouldRelease = true;
|
||||||
if (mListener != null) {
|
if (mListener != null) {
|
||||||
@ -300,6 +303,14 @@ public class TextureView extends View {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void destroyHardwareResources() {
|
||||||
|
super.destroyHardwareResources();
|
||||||
|
destroySurface();
|
||||||
|
invalidateParentCaches();
|
||||||
|
invalidate(true);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
HardwareLayer getHardwareLayer() {
|
HardwareLayer getHardwareLayer() {
|
||||||
if (mLayer == null) {
|
if (mLayer == null) {
|
||||||
|
@ -10073,7 +10073,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
|
|||||||
switch (mLayerType) {
|
switch (mLayerType) {
|
||||||
case LAYER_TYPE_HARDWARE:
|
case LAYER_TYPE_HARDWARE:
|
||||||
destroyLayer();
|
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:
|
case LAYER_TYPE_SOFTWARE:
|
||||||
destroyDrawingCache();
|
destroyDrawingCache();
|
||||||
break;
|
break;
|
||||||
@ -10235,11 +10235,30 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
|
|||||||
if (mHardwareLayer != null) {
|
if (mHardwareLayer != null) {
|
||||||
mHardwareLayer.destroy();
|
mHardwareLayer.destroy();
|
||||||
mHardwareLayer = null;
|
mHardwareLayer = null;
|
||||||
|
|
||||||
|
invalidate(true);
|
||||||
|
invalidateParentCaches();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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
|
* <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
|
* to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
|
||||||
|
@ -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() {
|
void destroyHardwareLayers() {
|
||||||
if (mThread != Thread.currentThread()) {
|
if (mThread != Thread.currentThread()) {
|
||||||
if (mAttachInfo.mHardwareRenderer != null &&
|
if (mAttachInfo.mHardwareRenderer != null &&
|
||||||
|
@ -425,7 +425,7 @@ public class WindowManagerImpl implements WindowManager {
|
|||||||
if (mViews == null) return;
|
if (mViews == null) return;
|
||||||
int count = mViews.length;
|
int count = mViews.length;
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
mRoots[i].destroyHardwareResources();
|
mRoots[i].terminateHardwareResources();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Terminate the hardware renderer to free all resources
|
// Terminate the hardware renderer to free all resources
|
||||||
|
@ -47,8 +47,7 @@ import com.google.android.gles_jni.EGLImpl;
|
|||||||
public abstract class ManagedEGLContext {
|
public abstract class ManagedEGLContext {
|
||||||
static final String TAG = "ManagedEGLContext";
|
static final String TAG = "ManagedEGLContext";
|
||||||
|
|
||||||
static final ArrayList<ManagedEGLContext> sActive
|
static final ArrayList<ManagedEGLContext> sActive = new ArrayList<ManagedEGLContext>();
|
||||||
= new ArrayList<ManagedEGLContext>();
|
|
||||||
|
|
||||||
final EGLContext mContext;
|
final EGLContext mContext;
|
||||||
|
|
||||||
@ -127,7 +126,7 @@ public abstract class ManagedEGLContext {
|
|||||||
sActive.clear();
|
sActive.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<active.size(); i++) {
|
for (int i = 0; i < active.size(); i++) {
|
||||||
active.get(i).execTerminate();
|
active.get(i).execTerminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user