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

Commit 8ff6b9eb authored by Romain Guy's avatar Romain Guy
Browse files

Terminate EGL when an app goes in the background

This does not happen on high end gfx devices. This happens
only if only one EGL context is initialized in the current
process.

Change-Id: Ibd1737efdf84eef8a84108b05795440d1ae9964e
parent 36a7f2a9
Loading
Loading
Loading
Loading
+21 −0
Original line number Original line Diff line number Diff line
@@ -315,6 +315,27 @@ class GLES20Canvas extends HardwareCanvas {


    private static native void nFlushCaches(int level);
    private static native void nFlushCaches(int level);


    /**
     * Release all resources associated with the underlying caches. This should
     * only be called after a full flushCaches().
     * 
     * @hide
     */
    public static void terminateCaches() {
        nTerminateCaches();
    }

    private static native void nTerminateCaches();

    /**
     * @hide
     */
    public static void initCaches() {
        nInitCaches();
    }

    private static native void nInitCaches();
    
    ///////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////
    // Display list
    // Display list
    ///////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////
+61 −10
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@ import android.opengl.GLUtils;
import android.os.SystemClock;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.util.Log;
import android.util.Log;
import com.google.android.gles_jni.EGLImpl;


import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGL11;
import javax.microedition.khronos.egl.EGL11;
@@ -324,6 +325,15 @@ 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.
     * 
     * 
@@ -633,6 +643,8 @@ public abstract class HardwareRenderer {
                        + GLUtils.getEGLErrorString(sEgl.eglGetError()));
                        + GLUtils.getEGLErrorString(sEgl.eglGetError()));
            }
            }
            
            
            initCaches();

            // If mDirtyRegions is set, this means we have an EGL configuration
            // If mDirtyRegions is set, this means we have an EGL configuration
            // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set
            // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set
            if (sDirtyRegions) {
            if (sDirtyRegions) {
@@ -652,6 +664,8 @@ public abstract class HardwareRenderer {
            return mEglContext.getGL();
            return mEglContext.getGL();
        }
        }


        abstract void initCaches();

        EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
        EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
            int[] attribs = { EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL_NONE };
            int[] attribs = { EGL_CONTEXT_CLIENT_VERSION, mGlVersion, EGL_NONE };


@@ -896,6 +910,11 @@ public abstract class HardwareRenderer {
            };
            };
        }
        }
        
        
        @Override
        void initCaches() {
            GLES20Canvas.initCaches();
        }

        @Override
        @Override
        boolean canDraw() {
        boolean canDraw() {
            return super.canDraw() && mGlCanvas != null;
            return super.canDraw() && mGlCanvas != null;
@@ -987,6 +1006,22 @@ public abstract class HardwareRenderer {
            if (eglContext == null) {
            if (eglContext == null) {
                return;
                return;
            } else {
            } else {
                usePbufferSurface(eglContext);
            }

            switch (level) {
                case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
                case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
                case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
                    GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE);
                    break;
                case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                    GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL);
                    break;
            }
        }

        private static void usePbufferSurface(EGLContext eglContext) {
            synchronized (sPbufferLock) {
            synchronized (sPbufferLock) {
                // Create a temporary 1x1 pbuffer so we have a context
                // Create a temporary 1x1 pbuffer so we have a context
                // to clear our OpenGL objects
                // to clear our OpenGL objects
@@ -999,15 +1034,31 @@ public abstract class HardwareRenderer {
            sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext);
            sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext);
        }
        }


            switch (level) {
        static void terminate() {
                case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
            synchronized (sEglLock) {
                case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
                if (sEgl == null) return;
                case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
    
                    GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE);
                if (EGLImpl.getInitCount(sEglDisplay) == 1) {
                    break;
                    EGLContext eglContext = sEglContextStorage.get();
                case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                    if (eglContext == null) return;
                    GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL);

                    break;
                    usePbufferSurface(eglContext);
                    GLES20Canvas.terminateCaches();

                    sEgl.eglDestroyContext(sEglDisplay, eglContext);
                    sEglContextStorage.remove();
        
                    sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
                    sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);

                    sEgl.eglReleaseThread();
                    sEgl.eglTerminate(sEglDisplay);
                    
                    sEgl = null;
                    sEglDisplay = null;
                    sEglConfig = null;
                    sPbuffer = null;
                }
            }
            }
        }
        }
    }
    }
+1 −3
Original line number Original line Diff line number Diff line
@@ -567,7 +567,7 @@ public final class ViewRootImpl extends Handler implements ViewParent,
        }
        }
    }
    }


    private void destroyHardwareResources() {
    void destroyHardwareResources() {
        if (mAttachInfo.mHardwareRenderer != null) {
        if (mAttachInfo.mHardwareRenderer != null) {
            if (mAttachInfo.mHardwareRenderer.isEnabled()) {
            if (mAttachInfo.mHardwareRenderer.isEnabled()) {
                mAttachInfo.mHardwareRenderer.destroyLayers(mView);
                mAttachInfo.mHardwareRenderer.destroyLayers(mView);
@@ -880,12 +880,10 @@ public final class ViewRootImpl extends Handler implements ViewParent,
                || mNewSurfaceNeeded;
                || mNewSurfaceNeeded;


        WindowManager.LayoutParams params = null;
        WindowManager.LayoutParams params = null;
        int windowAttributesChanges = 0;
        if (mWindowAttributesChanged) {
        if (mWindowAttributesChanged) {
            mWindowAttributesChanged = false;
            mWindowAttributesChanged = false;
            surfaceChanged = true;
            surfaceChanged = true;
            params = lp;
            params = lp;
            windowAttributesChanges = mWindowAttributesChangesFlag;
        }
        }
        CompatibilityInfo compatibilityInfo = mCompatibilityInfo.get();
        CompatibilityInfo compatibilityInfo = mCompatibilityInfo.get();
        if (compatibilityInfo.supportsScreen() == mLastInCompatMode) {
        if (compatibilityInfo.supportsScreen() == mLastInCompatMode) {
+26 −1
Original line number Original line Diff line number Diff line
@@ -16,6 +16,8 @@


package android.view;
package android.view;


import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
import android.content.res.CompatibilityInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.PixelFormat;
@@ -409,9 +411,32 @@ public class WindowManagerImpl implements WindowManager {
     */
     */
    public void trimMemory(int level) {
    public void trimMemory(int level) {
        if (HardwareRenderer.isAvailable()) {
        if (HardwareRenderer.isAvailable()) {
            switch (level) {
                case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
                    // On low and medium end gfx devices
                    if (!ActivityManager.isHighEndGfx(getDefaultDisplay())) {
                        // Force a full memory flush
                        HardwareRenderer.trimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
                        // Destroy all hardware surfaces and resources associated to
                        // known windows
                        synchronized (this) {
                            if (mViews == null) return;
                            int count = mViews.length;
                            for (int i = 0; i < count; i++) {
                                mRoots[i].destroyHardwareResources();
                            }
                        }
                        // Terminate the hardware renderer to free all resources
                        HardwareRenderer.terminate();                        
                        break;
                    }
                    // high end gfx devices fall through to next case
                default:
                    HardwareRenderer.trimMemory(level);
                    HardwareRenderer.trimMemory(level);
            }
            }
        }
        }
    }


    /**
    /**
     * @hide
     * @hide
+1 −0
Original line number Original line Diff line number Diff line
@@ -160,6 +160,7 @@ LOCAL_C_INCLUDES += \
	$(JNI_H_INCLUDE) \
	$(JNI_H_INCLUDE) \
	$(LOCAL_PATH)/android/graphics \
	$(LOCAL_PATH)/android/graphics \
	$(LOCAL_PATH)/../../libs/hwui \
	$(LOCAL_PATH)/../../libs/hwui \
	$(LOCAL_PATH)/../../opengl/libs \
	$(call include-path-for, bluedroid) \
	$(call include-path-for, bluedroid) \
	$(call include-path-for, libhardware)/hardware \
	$(call include-path-for, libhardware)/hardware \
	$(call include-path-for, libhardware_legacy)/hardware_legacy \
	$(call include-path-for, libhardware_legacy)/hardware_legacy \
Loading