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

Commit 83536cee authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change I1179efbb into eclair-mr2

* changes:
  resolved conflicts for merge of ba56915a to eclair-mr2
parents 0cda5911 1179efbb
Loading
Loading
Loading
Loading
+158 −139
Original line number Original line Diff line number Diff line
@@ -955,6 +955,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
     * to a Renderer instance to do the actual drawing. Can be configured to
     * to a Renderer instance to do the actual drawing. Can be configured to
     * render continuously or on request.
     * render continuously or on request.
     *
     *
     * All potentially blocking synchronization is done through the
     * sGLThreadManager object. This avoids multiple-lock ordering issues.
     *
     */
     */
    class GLThread extends Thread {
    class GLThread extends Thread {
        GLThread(Renderer renderer) {
        GLThread(Renderer renderer) {
@@ -974,51 +977,31 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                Log.i("GLThread", "starting tid=" + getId());
                Log.i("GLThread", "starting tid=" + getId());
            }
            }


            /*
             * When the android framework launches a second instance of
             * an activity, the new instance's onCreate() method may be
             * called before the first instance returns from onDestroy().
             *
             * This semaphore ensures that only one instance at a time
             * accesses EGL.
             */
            try {
            try {
                guardedRun();
                guardedRun();
            } catch (InterruptedException e) {
            } catch (InterruptedException e) {
                // fall thru and exit normally
                // fall thru and exit normally
            } finally {
            } finally {
                synchronized(this) {
                sGLThreadManager.threadExiting(this);
                    if (LOG_THREADS) {
                        Log.i("GLThread", "exiting tid=" +  getId());
                    }
                    mDone = true;
                    notifyAll();
                }
            }
        }

        private void startEgl() throws InterruptedException {
            if (! mHaveEgl) {
                mHaveEgl = true;
                sGLThreadManager.start(this);
                mEglHelper.start();
            }
            }
        }
        }


        private void stopEgl() {
        /*
         * This private method should only be called inside a
         * synchronized(sGLThreadManager) block.
         */
        private void stopEglLocked() {
            if (mHaveEgl) {
            if (mHaveEgl) {
                mHaveEgl = false;
                mHaveEgl = false;
                mEglHelper.destroySurface();
                mEglHelper.destroySurface();
                mEglHelper.finish();
                mEglHelper.finish();
                sGLThreadManager.end(this);
                sGLThreadManager.releaseEglSurface(this);
            }
            }
        }
        }


        private void guardedRun() throws InterruptedException {
        private void guardedRun() throws InterruptedException {
            mEglHelper = new EglHelper();
            mEglHelper = new EglHelper();
            try {
            try {
                startEgl();

                GL10 gl = null;
                GL10 gl = null;
                boolean tellRendererSurfaceCreated = true;
                boolean tellRendererSurfaceCreated = true;
                boolean tellRendererSurfaceChanged = true;
                boolean tellRendererSurfaceChanged = true;
@@ -1027,50 +1010,59 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                 * This is our main activity thread's loop, we go until
                 * This is our main activity thread's loop, we go until
                 * asked to quit.
                 * asked to quit.
                 */
                 */
                while (!mDone) {
                while (!isDone()) {

                    /*
                    /*
                     *  Update the asynchronous state (window size)
                     *  Update the asynchronous state (window size)
                     */
                     */
                    int w, h;
                    int w = 0;
                    boolean changed;
                    int h = 0;
                    boolean changed = false;
                    boolean needStart = false;
                    boolean needStart = false;
                    synchronized (this) {
                    boolean eventsWaiting = false;
                        Runnable r;

                        while ((r = getEvent()) != null) {
                    synchronized (sGLThreadManager) {
                            r.run();
                        while (true) {
                        }
                            // Manage acquiring and releasing the SurfaceView
                            // surface and the EGL surface.
                            if (mPaused) {
                            if (mPaused) {
                            stopEgl();
                                stopEglLocked();
                            needStart = true;
                            }
                            }
                        while(true) {
                            if (!mHasSurface) {
                            if (!mHasSurface) {
                                if (!mWaitingForSurface) {
                                if (!mWaitingForSurface) {
                                    stopEgl();
                                    stopEglLocked();
                                    mWaitingForSurface = true;
                                    mWaitingForSurface = true;
                                    notifyAll();
                                    sGLThreadManager.notifyAll();
                                }
                                }
                            } else {
                            } else {
                                boolean shouldHaveEgl = sGLThreadManager.shouldHaveEgl(this);
                                if (!mHaveEgl) {
                                if (mHaveEgl && (!shouldHaveEgl)) {
                                    if (sGLThreadManager.tryAcquireEglSurface(this)) {
                                    stopEgl();
                                        mHaveEgl = true;
                                } else if ((!mHaveEgl) && shouldHaveEgl) {
                                        mEglHelper.start();
                                    startEgl();
                                        mRequestRender = true;
                                        needStart = true;
                                        needStart = true;
                                    }
                                    }
                                }
                                }
                            if (!needToWait()) {
                                break;
                            }
                            if (LOG_THREADS) {
                                Log.i("GLThread", "needToWait tid=" + getId());
                            }
                            wait();
                            }
                            }

                            // Check if we need to wait. If not, update any state
                            // that needs to be updated, copy any state that
                            // needs to be copied, and use "break" to exit the
                            // wait loop.

                            if (mDone) {
                            if (mDone) {
                                return;
                            }

                            if (mEventsWaiting) {
                                eventsWaiting = true;
                                mEventsWaiting = false;
                                break;
                                break;
                            }
                            }

                            if ( (! mPaused) && mHasSurface && mHaveEgl
                                    && (mWidth > 0) && (mHeight > 0)
                                    && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))
                                    ) {
                                changed = mSizeChanged;
                                changed = mSizeChanged;
                                w = mWidth;
                                w = mWidth;
                                h = mHeight;
                                h = mHeight;
@@ -1079,11 +1071,36 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                                if (mHasSurface && mWaitingForSurface) {
                                if (mHasSurface && mWaitingForSurface) {
                                    changed = true;
                                    changed = true;
                                    mWaitingForSurface = false;
                                    mWaitingForSurface = false;
                            notifyAll();
                                    sGLThreadManager.notifyAll();
                                }
                                break;
                            }

                            // By design, this is the only place where we wait().

                            if (LOG_THREADS) {
                                Log.i("GLThread", "waiting tid=" + getId());
                            }
                            }
                            sGLThreadManager.wait();
                        }
                        }
                    } // end of synchronized(sGLThreadManager)

                    /*
                     * Handle queued events
                     */
                    if (eventsWaiting) {
                        Runnable r;
                        while ((r = getEvent()) != null) {
                            r.run();
                            if (isDone()) {
                                return;
                            }
                        }
                        // Go back and see if we need to wait to render.
                        continue;
                    }

                    if (needStart) {
                    if (needStart) {
                        startEgl();
                        tellRendererSurfaceCreated = true;
                        tellRendererSurfaceCreated = true;
                        changed = true;
                        changed = true;
                    }
                    }
@@ -1115,71 +1132,63 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                /*
                /*
                 * clean-up everything...
                 * clean-up everything...
                 */
                 */
                stopEgl();
                synchronized (sGLThreadManager) {
                    stopEglLocked();
                }
                }
            }
            }

        private boolean needToWait() {
            if (mDone) {
                return false;
            }

            if (mPaused || (! mHasSurface) || (! mHaveEgl)) {
                return true;
        }
        }


            if ((mWidth > 0) && (mHeight > 0) && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) {
        private boolean isDone() {
                return false;
            synchronized (sGLThreadManager) {
                return mDone;
            }
            }

            return true;
        }
        }


        public void setRenderMode(int renderMode) {
        public void setRenderMode(int renderMode) {
            if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) {
            if ( !((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY)) ) {
                throw new IllegalArgumentException("renderMode");
                throw new IllegalArgumentException("renderMode");
            }
            }
            synchronized(this) {
            synchronized(sGLThreadManager) {
                mRenderMode = renderMode;
                mRenderMode = renderMode;
                if (renderMode == RENDERMODE_CONTINUOUSLY) {
                if (renderMode == RENDERMODE_CONTINUOUSLY) {
                    notifyAll();
                    sGLThreadManager.notifyAll();
                }
                }
            }
            }
        }
        }


        public int getRenderMode() {
        public int getRenderMode() {
            synchronized(this) {
            synchronized(sGLThreadManager) {
                return mRenderMode;
                return mRenderMode;
            }
            }
        }
        }


        public void requestRender() {
        public void requestRender() {
            synchronized(this) {
            synchronized(sGLThreadManager) {
                mRequestRender = true;
                mRequestRender = true;
                notifyAll();
                sGLThreadManager.notifyAll();
            }
            }
        }
        }


        public void surfaceCreated() {
        public void surfaceCreated() {
            synchronized(this) {
            synchronized(sGLThreadManager) {
                if (LOG_THREADS) {
                if (LOG_THREADS) {
                    Log.i("GLThread", "surfaceCreated tid=" + getId());
                    Log.i("GLThread", "surfaceCreated tid=" + getId());
                }
                }
                mHasSurface = true;
                mHasSurface = true;
                notifyAll();
                sGLThreadManager.notifyAll();
            }
            }
        }
        }


        public void surfaceDestroyed() {
        public void surfaceDestroyed() {
            synchronized(this) {
            synchronized(sGLThreadManager) {
                if (LOG_THREADS) {
                if (LOG_THREADS) {
                    Log.i("GLThread", "surfaceDestroyed tid=" + getId());
                    Log.i("GLThread", "surfaceDestroyed tid=" + getId());
                }
                }
                mHasSurface = false;
                mHasSurface = false;
                notifyAll();
                sGLThreadManager.notifyAll();
                while(!mWaitingForSurface && isAlive() && ! mDone) {
                while(!mWaitingForSurface && isAlive() && ! mDone) {
                    try {
                    try {
                        wait();
                        sGLThreadManager.wait();
                    } catch (InterruptedException e) {
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        Thread.currentThread().interrupt();
                    }
                    }
@@ -1188,35 +1197,35 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
        }
        }


        public void onPause() {
        public void onPause() {
            synchronized (this) {
            synchronized (sGLThreadManager) {
                mPaused = true;
                mPaused = true;
                notifyAll();
                sGLThreadManager.notifyAll();
            }
            }
        }
        }


        public void onResume() {
        public void onResume() {
            synchronized (this) {
            synchronized (sGLThreadManager) {
                mPaused = false;
                mPaused = false;
                mRequestRender = true;
                mRequestRender = true;
                notifyAll();
                sGLThreadManager.notifyAll();
            }
            }
        }
        }


        public void onWindowResize(int w, int h) {
        public void onWindowResize(int w, int h) {
            synchronized (this) {
            synchronized (sGLThreadManager) {
                mWidth = w;
                mWidth = w;
                mHeight = h;
                mHeight = h;
                mSizeChanged = true;
                mSizeChanged = true;
                notifyAll();
                sGLThreadManager.notifyAll();
            }
            }
        }
        }


        public void requestExitAndWait() {
        public void requestExitAndWait() {
            // don't call this from GLThread thread or it is a guaranteed
            // don't call this from GLThread thread or it is a guaranteed
            // deadlock!
            // deadlock!
            synchronized(this) {
            synchronized(sGLThreadManager) {
                mDone = true;
                mDone = true;
                notifyAll();
                sGLThreadManager.notifyAll();
            }
            }
            try {
            try {
                join();
                join();
@@ -1232,6 +1241,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
        public void queueEvent(Runnable r) {
        public void queueEvent(Runnable r) {
            synchronized(this) {
            synchronized(this) {
                mEventQueue.add(r);
                mEventQueue.add(r);
                synchronized(sGLThreadManager) {
                    mEventsWaiting = true;
                    sGLThreadManager.notifyAll();
                }
            }
            }
        }
        }


@@ -1245,6 +1258,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
            return null;
            return null;
        }
        }


        // Once the thread is started, all accesses to the following member
        // variables are protected by the sGLThreadManager monitor
        private boolean mDone;
        private boolean mDone;
        private boolean mPaused;
        private boolean mPaused;
        private boolean mHasSurface;
        private boolean mHasSurface;
@@ -1254,6 +1269,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
        private int mHeight;
        private int mHeight;
        private int mRenderMode;
        private int mRenderMode;
        private boolean mRequestRender;
        private boolean mRequestRender;
        private boolean mEventsWaiting;
        // End of member variables protected by the sGLThreadManager monitor.

        private Renderer mRenderer;
        private Renderer mRenderer;
        private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
        private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
        private EglHelper mEglHelper;
        private EglHelper mEglHelper;
@@ -1300,58 +1318,46 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
    }
    }


    private static class GLThreadManager {
    private static class GLThreadManager {
        public boolean shouldHaveEgl(GLThread thread) {
            if (mMultipleGLESContextsAllowed) {
                return true;
            } else {
                synchronized(this) {
                    return thread == mMostRecentGLThread || mMostRecentGLThread == null;
                }
            }
        }

        public void start(GLThread thread) throws InterruptedException {
           if (! mGLESVersionCheckComplete) {
                mGLESVersion = SystemProperties.getInt(
                        "ro.opengles.version",
                        ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
                if (mGLESVersion >= kGLES_20) {
                    mMultipleGLESContextsAllowed = true;
                }
                mGLESVersionCheckComplete = true;
            }


            GLThread oldThread = null;
        public synchronized void threadExiting(GLThread thread) {
            synchronized(this) {
            if (LOG_THREADS) {
                oldThread = mMostRecentGLThread;
                Log.i("GLThread", "exiting tid=" +  thread.getId());
                mMostRecentGLThread = thread;
            }
            }
            if (oldThread != null && ! mMultipleGLESContextsAllowed) {
            thread.mDone = true;
                synchronized(oldThread) {
            if (mEglOwner == thread) {
                    oldThread.notifyAll();
                mEglOwner = null;
            }
            }
            notifyAll();
        }
        }


            synchronized(this) {
        /*
                while ((! mMultipleGLESContextsAllowed)
         * Tries to acquire the right to use an EGL
                        && mGLContextCount > 0) {
         * surface. Does not block.
                    wait();
         * @return true if the right to use an EGL surface was acquired.
         */
        public synchronized boolean tryAcquireEglSurface(GLThread thread) {
            if (mEglOwner == thread || mEglOwner == null) {
                mEglOwner = thread;
                notifyAll();
                return true;
            }
            }

            checkGLESVersion();
                mGLContextCount++;
            if (mMultipleGLESContextsAllowed) {
                return true;
            }
            }
            return false;
        }
        }


        public synchronized void end(GLThread thread) {
        public synchronized void releaseEglSurface(GLThread thread) {
            mGLContextCount--;
            if (mEglOwner == thread) {
            notifyAll();
                mEglOwner = null;
            if (mMostRecentGLThread == thread) {
                mMostRecentGLThread = null;
            }
            }
            notifyAll();
        }
        }


        public synchronized void checkGLDriver(GL10 gl) {
        public synchronized void checkGLDriver(GL10 gl) {
            if (! mGLESDriverCheckComplete) {
            if (! mGLESDriverCheckComplete) {
                checkGLESVersion();
                if (mGLESVersion < kGLES_20) {
                if (mGLESVersion < kGLES_20) {
                    String renderer = gl.glGetString(GL10.GL_RENDERER);
                    String renderer = gl.glGetString(GL10.GL_RENDERER);
                    mMultipleGLESContextsAllowed =
                    mMultipleGLESContextsAllowed =
@@ -1362,16 +1368,29 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
            }
            }
        }
        }


        private void checkGLESVersion() {
            if (! mGLESVersionCheckComplete) {
                mGLESVersion = SystemProperties.getInt(
                        "ro.opengles.version",
                        ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
                if (mGLESVersion >= kGLES_20) {
                    mMultipleGLESContextsAllowed = true;
                }
                mGLESVersionCheckComplete = true;
            }

        }

        private boolean mGLESVersionCheckComplete;
        private boolean mGLESVersionCheckComplete;
        private int mGLESVersion;
        private int mGLESVersion;
        private GLThread mMostRecentGLThread;
        private boolean mGLESDriverCheckComplete;
        private boolean mGLESDriverCheckComplete;
        private boolean mMultipleGLESContextsAllowed;
        private boolean mMultipleGLESContextsAllowed;
        private int mGLContextCount;
        private int mGLContextCount;
        private static final int kGLES_20 = 0x20000;
        private static final int kGLES_20 = 0x20000;
        private static final String kMSM7K_RENDERER_PREFIX =
        private static final String kMSM7K_RENDERER_PREFIX =
            "Q3Dimension MSM7500 ";
            "Q3Dimension MSM7500 ";
    };
        private GLThread mEglOwner;
    }


    private static final GLThreadManager sGLThreadManager = new GLThreadManager();
    private static final GLThreadManager sGLThreadManager = new GLThreadManager();
    private boolean mSizeChanged = true;
    private boolean mSizeChanged = true;