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

Commit f2cc48fe authored by Romain Guy's avatar Romain Guy Committed by Android (Google) Code Review
Browse files

Merge "Let HardwareRenderer support multiple threads."

parents ee4a6478 566b3efb
Loading
Loading
Loading
Loading
+51 −45
Original line number Diff line number Diff line
@@ -325,12 +325,15 @@ public abstract class HardwareRenderer {
        private static final int SURFACE_STATE_SUCCESS = 1;
        private static final int SURFACE_STATE_UPDATED = 2;
        
        static EGLContext sEglContext;
        static EGL10 sEgl;
        static EGLDisplay sEglDisplay;
        static EGLConfig sEglConfig;
        static final Object[] sEglLock = new Object[0];

        private static Thread sEglThread;
        static final ThreadLocal<EGLContext> sEglContextStorage = new ThreadLocal<EGLContext>();

        EGLContext mEglContext;
        Thread mEglThread;

        EGLSurface mEglSurface;
        
@@ -487,9 +490,8 @@ public abstract class HardwareRenderer {
        abstract GLES20Canvas createCanvas();

        void initializeEgl() {
            if (sEglContext != null) return;

            sEglThread = Thread.currentThread();
            synchronized (sEglLock) {
                if (sEgl == null && sEglConfig == null) {
                    sEgl = (EGL10) EGLContext.getEGL();
                    
                    // Get to the default display.
@@ -520,12 +522,16 @@ public abstract class HardwareRenderer {
                            throw new RuntimeException("eglConfig not initialized");
                        }
                    }
                }
            }

            /*
            * Create an EGL context. We want to do this as rarely as we can, because an
            * EGL context is a somewhat heavy object.
            */
            sEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
            mEglContext = sEglContextStorage.get();
            mEglThread = Thread.currentThread();

            if (mEglContext == null) {
                mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
                sEglContextStorage.set(mEglContext);
            }
        }

        private EGLConfig chooseEglConfig() {
@@ -554,7 +560,7 @@ public abstract class HardwareRenderer {
            if (sEglConfig == null) {
                throw new RuntimeException("eglConfig not initialized");
            }
            if (Thread.currentThread() != sEglThread) {
            if (Thread.currentThread() != mEglThread) {
                throw new IllegalStateException("HardwareRenderer cannot be used " 
                        + "from multiple threads");
            }
@@ -590,7 +596,7 @@ public abstract class HardwareRenderer {
             * Before we can issue GL commands, we need to make sure
             * the context is current and bound to a surface.
             */
            if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
            if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                throw new Surface.OutOfResourcesException("eglMakeCurrent failed "
                        + getEGLErrorString(sEgl.eglGetError()));
            }
@@ -611,7 +617,7 @@ public abstract class HardwareRenderer {
                mDirtyRegionsEnabled = GLES20Canvas.isBackBufferPreserved();
            }

            return sEglContext.getGL();
            return mEglContext.getGL();
        }

        EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
@@ -752,22 +758,22 @@ public abstract class HardwareRenderer {
        }

        /**
         * Ensures the currnet EGL context is the one we expect.
         * Ensures the current EGL context is the one we expect.
         * 
         * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
         *         {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
         *         {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
         */
        private int checkCurrent() {
            if (sEglThread != Thread.currentThread()) {
            if (mEglThread != Thread.currentThread()) {
                throw new IllegalStateException("Hardware acceleration can only be used with a " +
                        "single UI thread.\nOriginal thread: " + sEglThread + "\n" +
                        "single UI thread.\nOriginal thread: " + mEglThread + "\n" +
                        "Current thread: " + Thread.currentThread());
            }

            if (!sEglContext.equals(sEgl.eglGetCurrentContext()) ||
            if (!mEglContext.equals(sEgl.eglGetCurrentContext()) ||
                    !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
                if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
                if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
                    fallback(true);
                    Log.e(LOG_TAG, "eglMakeCurrent failed " +
                            getEGLErrorString(sEgl.eglGetError()));