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

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

Merge change Ica8c305a into eclair

* changes:
  More GLSurfaceView cleanup.
parents e0cadd7c a08d46d8
Loading
Loading
Loading
Loading
+125 −134
Original line number Diff line number Diff line
@@ -145,6 +145,10 @@ import android.view.SurfaceView;
 */
public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
    private final static boolean LOG_THREADS = false;
    private final static boolean LOG_SURFACE = false;
    private final static boolean LOG_RENDERER = false;
    // Work-around for bug 2263168
    private final static boolean DRAW_TWICE_AFTER_SIZE_CHANGED = true;
    /**
     * The renderer only renders
     * when the surface is created, or when {@link #requestRender} is called.
@@ -949,7 +953,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
    class GLThread extends Thread {
        GLThread(Renderer renderer) {
            super();
            mDone = false;
            mWidth = 0;
            mHeight = 0;
            mRequestRender = true;
@@ -982,7 +985,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                mHaveEgl = false;
                mEglHelper.destroySurface();
                mEglHelper.finish();
                sGLThreadManager.releaseEglSurface(this);
                sGLThreadManager.releaseEglSurfaceLocked(this);
            }
        }

@@ -990,81 +993,89 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
            mEglHelper = new EglHelper();
            try {
                GL10 gl = null;
                boolean tellRendererSurfaceCreated = true;
                boolean tellRendererSurfaceChanged = true;

                /*
                 * This is our main activity thread's loop, we go until
                 * asked to quit.
                 */
                while (!isDone()) {
                    /*
                     *  Update the asynchronous state (window size)
                     */
                boolean createEglSurface = false;
                boolean sizeChanged = false;
                int w = 0;
                int h = 0;
                    boolean changed = false;
                    boolean needStart = false;
                    boolean eventsWaiting = false;
                Runnable event = null;

                while (true) {
                    synchronized (sGLThreadManager) {
                        while (true) {
                            // Manage acquiring and releasing the SurfaceView
                            // surface and the EGL surface.
                            if (mPaused) {
                            if (mShouldExit) {
                                return;
                            }

                            if (! mEventQueue.isEmpty()) {
                                event = mEventQueue.remove(0);
                                break;
                            }

                            // Do we need to release the EGL surface?
                            if (mHaveEgl && mPaused) {
                                if (LOG_SURFACE) {
                                    Log.i("GLThread", "releasing EGL surface because paused tid=" + getId());
                                }
                                stopEglLocked();
                            }
                            if (!mHasSurface) {
                                if (!mWaitingForSurface) {

                            // Have we lost the surface view surface?
                            if ((! mHasSurface) && (! mWaitingForSurface)) {
                                if (LOG_SURFACE) {
                                    Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId());
                                }
                                if (mHaveEgl) {
                                    stopEglLocked();
                                }
                                mWaitingForSurface = true;
                                sGLThreadManager.notifyAll();
                            }
                            } else {
                                if (!mHaveEgl) {
                                    if (sGLThreadManager.tryAcquireEglSurface(this)) {
                                        mHaveEgl = true;
                                        mEglHelper.start();
                                        mRequestRender = true;
                                        needStart = true;
                                    }

                            // Have we acquired the surface view surface?
                            if (mHasSurface && mWaitingForSurface) {
                                if (LOG_SURFACE) {
                                    Log.i("GLThread", "noticed surfaceView surface acquired tid=" + getId());
                                }
                                mWaitingForSurface = false;
                                sGLThreadManager.notifyAll();
                            }

                            // 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) {
                                return;
                            }
                            // Ready to draw?
                            if ((!mPaused) && mHasSurface
                                && (mWidth > 0) && (mHeight > 0)
                                && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) {

                            if (mEventsWaiting) {
                                eventsWaiting = true;
                                mEventsWaiting = false;
                                break;
                                // If we don't have an egl surface, try to acquire one.
                                if ((! mHaveEgl) && sGLThreadManager.tryAcquireEglSurfaceLocked(this)) {
                                    mHaveEgl = true;
                                    mEglHelper.start();
                                    createEglSurface = true;
                                    sizeChanged = true;
                                    sGLThreadManager.notifyAll();
                                }

                            if ( (! mPaused) && mHasSurface && mHaveEgl
                                    && (mWidth > 0) && (mHeight > 0)
                                    && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))
                                    ) {
                                changed = mSizeChanged;
                                if (mHaveEgl) {
                                    if (mSizeChanged) {
                                        sizeChanged = true;
                                        w = mWidth;
                                        h = mHeight;
                                        if (DRAW_TWICE_AFTER_SIZE_CHANGED) {
                                            // We keep mRequestRender true so that we draw twice after the size changes.
                                            // (Once because of mSizeChanged, the second time because of mRequestRender.)
                                            // This forces the updated graphics onto the screen.
                                        } else {
                                            mRequestRender = false;
                                        }
                                        mSizeChanged = false;
                                    } else {
                                        mRequestRender = false;
                                if (mHasSurface && mWaitingForSurface) {
                                    changed = true;
                                    mWaitingForSurface = false;
                                    sGLThreadManager.notifyAll();
                                    }
                                    sGLThreadManager.notifyAll();
                                    break;
                                }
                            }

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

                            // By design, this is the only place in a GLThread thread where we wait().
                            if (LOG_THREADS) {
                                Log.i("GLThread", "waiting tid=" + getId());
                            }
@@ -1072,46 +1083,37 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                        }
                    } // 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.
                    if (event != null) {
                        event.run();
                        event = null;
                        continue;
                    }

                    if (needStart) {
                        tellRendererSurfaceCreated = true;
                        changed = true;
                    }
                    if (changed) {
                    if (createEglSurface) {
                        gl = (GL10) mEglHelper.createSurface(getHolder());
                        tellRendererSurfaceChanged = true;
                        if (LOG_RENDERER) {
                            Log.w("GLThread", "onSurfaceCreated");
                        }
                    if (tellRendererSurfaceCreated) {
                        mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
                        tellRendererSurfaceCreated = false;
                        createEglSurface = false;
                    }

                    if (sizeChanged) {
                        if (LOG_RENDERER) {
                            Log.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")");
                        }
                    if (tellRendererSurfaceChanged) {
                        mRenderer.onSurfaceChanged(gl, w, h);
                        tellRendererSurfaceChanged = false;
                        sizeChanged = false;
                    }
                    if ((w > 0) && (h > 0)) {
                        /* draw a frame here */
                        mRenderer.onDrawFrame(gl);

                        /*
                         * Once we're done with GL, we need to call swapBuffers()
                         * to instruct the system to display the rendered frame
                         */
                        mEglHelper.swap();
                    if (LOG_RENDERER) {
                        Log.w("GLThread", "onDrawFrame");
                    }
                    mRenderer.onDrawFrame(gl);
                    if(!mEglHelper.swap()) {
                        if (LOG_SURFACE) {
                            Log.i("GLThread", "egl surface lost tid=" + getId());
                        }
                    }
                }
            } finally {
@@ -1124,23 +1126,15 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
            }
        }

        private boolean isDone() {
            synchronized (sGLThreadManager) {
                return mDone;
            }
        }

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

        public int getRenderMode() {
            synchronized(sGLThreadManager) {
@@ -1172,7 +1166,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                }
                mHasSurface = false;
                sGLThreadManager.notifyAll();
                while(!mWaitingForSurface && isAlive() && ! mDone) {
                while((!mWaitingForSurface) && (!mExited)) {
                    try {
                        sGLThreadManager.wait();
                    } catch (InterruptedException e) {
@@ -1202,6 +1196,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
                mWidth = w;
                mHeight = h;
                mSizeChanged = true;
                mRequestRender = true;
                sGLThreadManager.notifyAll();
            }
        }
@@ -1210,43 +1205,36 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
            // don't call this from GLThread thread or it is a guaranteed
            // deadlock!
            synchronized(sGLThreadManager) {
                mDone = true;
                mShouldExit = true;
                sGLThreadManager.notifyAll();
            }
                while (! mExited) {
                    try {
                join();
                        sGLThreadManager.wait();
                    } catch (InterruptedException ex) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        }

        /**
         * Queue an "event" to be run on the GL rendering thread.
         * @param r the runnable to be run on the GL rendering thread.
         */
        public void queueEvent(Runnable r) {
            synchronized(this) {
                mEventQueue.add(r);
            if (r == null) {
                throw new IllegalArgumentException("r must not be null");
            }
            synchronized(sGLThreadManager) {
                    mEventsWaiting = true;
                mEventQueue.add(r);
                sGLThreadManager.notifyAll();
            }
        }
        }

        private Runnable getEvent() {
            synchronized(this) {
                if (mEventQueue.size() > 0) {
                    return mEventQueue.remove(0);
                }

            }
            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 mShouldExit;
        private boolean mExited;
        private boolean mPaused;
        private boolean mHasSurface;
        private boolean mWaitingForSurface;
@@ -1255,11 +1243,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
        private int mHeight;
        private int mRenderMode;
        private boolean mRequestRender;
        private boolean mEventsWaiting;
        private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
        // End of member variables protected by the sGLThreadManager monitor.

        private Renderer mRenderer;
        private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
        private EglHelper mEglHelper;
    }

@@ -1309,7 +1296,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
            if (LOG_THREADS) {
                Log.i("GLThread", "exiting tid=" +  thread.getId());
            }
            thread.mDone = true;
            thread.mExited = true;
            if (mEglOwner == thread) {
                mEglOwner = null;
            }
@@ -1318,10 +1305,11 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback

        /*
         * Tries once to acquire the right to use an EGL
         * surface. Does not block.
         * surface. Does not block. Requires that we are already
         * in the sGLThreadManager monitor when this is called.
         * @return true if the right to use an EGL surface was acquired.
         */
        public synchronized boolean tryAcquireEglSurface(GLThread thread) {
        public boolean tryAcquireEglSurfaceLocked(GLThread thread) {
            if (mEglOwner == thread || mEglOwner == null) {
                mEglOwner = thread;
                notifyAll();
@@ -1329,8 +1317,11 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
            }
            return false;
        }

        public synchronized void releaseEglSurface(GLThread thread) {
        /*
         * Releases the EGL surface. Requires that we are already in the
         * sGLThreadManager monitor when this is called.
         */
        public void releaseEglSurfaceLocked(GLThread thread) {
            if (mEglOwner == thread) {
                mEglOwner = null;
            }