Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31f2c2e9 authored by Romain Guy's avatar Romain Guy
Browse files

Notify views when EGL resources are about to be destroyed

Bug #5639899

Change-Id: I7c5d8bebf02294426f5b3ab1358a31c38a4fd064
parent 7859c184
Loading
Loading
Loading
Loading
+51 −22
Original line number Diff line number Diff line
@@ -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;

@@ -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) {
            if (GLES20Canvas.isAvailable()) {
                return new Gl20Renderer(translucent);
@@ -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;
+11 −0
Original line number Diff line number Diff line
@@ -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) {
+20 −1
Original line number Diff line number Diff line
@@ -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
+7 −0
Original line number Diff line number Diff line
@@ -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 &&
+1 −1
Original line number Diff line number Diff line
@@ -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
Loading