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

Commit bd17bd34 authored by Romain Guy's avatar Romain Guy
Browse files

Ensure we have a GL context before deleting View layers

Bug #7391098

The existing code was doing a make current to guarantee we have a
current context. This can however fail when the surface is destroyed
which could lead to GL calls without an EGL context, and therefore
potential leaks. This change fixes the issue by using a technique
found in HardwareRenderer.destroyHardwareResources(). If the surface
is not available then we use a special 1x1 pbuffer as a way to get
a valid context.

Change-Id: I716d3799bf90120d793d76e90a83956837ecd491
parent 3a2d6aaf
Loading
Loading
Loading
Loading
+29 −24
Original line number Diff line number Diff line
@@ -1525,30 +1525,6 @@ public abstract class HardwareRenderer {
            ((GLES20TextureLayer) layer).setSurfaceTexture(surfaceTexture);
        }

        @Override
        void destroyLayers(View view) {
            if (view != null && isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) {
                if (mCanvas != null) {
                    mCanvas.clearLayerUpdates();
                }
                destroyHardwareLayer(view);
                GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
            }
        }

        private static void destroyHardwareLayer(View view) {
            view.destroyLayer(true);

            if (view instanceof ViewGroup) {
                ViewGroup group = (ViewGroup) view;

                int count = group.getChildCount();
                for (int i = 0; i < count; i++) {
                    destroyHardwareLayer(group.getChildAt(i));
                }
            }
        }

        @Override
        boolean safelyRun(Runnable action) {
            boolean needsContext = true;
@@ -1573,6 +1549,35 @@ public abstract class HardwareRenderer {
            return true;
        }

        @Override
        void destroyLayers(final View view) {
            if (view != null) {
                safelyRun(new Runnable() {
                    @Override
                    public void run() {
                        if (mCanvas != null) {
                            mCanvas.clearLayerUpdates();
                        }
                        destroyHardwareLayer(view);
                        GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
                    }
                });
            }
        }

        private static void destroyHardwareLayer(View view) {
            view.destroyLayer(true);

            if (view instanceof ViewGroup) {
                ViewGroup group = (ViewGroup) view;

                int count = group.getChildCount();
                for (int i = 0; i < count; i++) {
                    destroyHardwareLayer(group.getChildAt(i));
                }
            }
        }

        @Override
        void destroyHardwareResources(final View view) {
            if (view != null) {