I am having a bizarre problem where if the View that contains my
GLSurfaceView is not the first to be shown by my ScreenController,
then the GL commands never actually get drawn. If the GLSurfaceView is
drawn first, then everything renders perfectly. Does anyone have any
ideas why this is happening? Below are the two files:

----------------------------------------------------
ScreenController.as
----------------------------------------------------
public class ScreenController extends ViewAnimator {

        public static final String SCREEN_ID = "mCurrentScreenId";

        public class ScreenAnimationListener implements AnimationListener {
                private int nextScreenId = -1;

                public void onAnimationEnd(Animation animation) {
                        ScreenController gc = ((DecadesActivity) getContext())
                                        .getController();

                        if (animation == mOutAnimation) {
                                gc.removeScreen();

                                if (nextScreenId != -1) {
                                        
gc.getHandler().showScreen(nextScreenId);
                                }
                        }

                        else if (animation == mInAnimation) {
                        }
                }

                public void onAnimationRepeat(Animation animation) {
                        // TODO Auto-generated method stub
                }

                public void onAnimationStart(Animation animation) {
                        // TODO Auto-generated method stub
                }

                public void setNextScreen(int id) {
                        nextScreenId = id;
                }
        }

        /**
         * A handler for sending messages to the controller on its own
thread. Used
         * for screen changes only.
         */
        public class UIThreadHandler extends Handler {
                public void handleMessage(Message msg) {
                        if (msg.what != -1) {
                                ScreenController.this.showScreen(msg.what);
                        }
                }

                public void restoreState() {
                        this.removeMessages(-1);
                        sendMessage(obtainMessage(-1));
                }

                public void showScreen(int id) {
                        this.removeMessages(id);
                        sendMessage(obtainMessage(id, 0));
                }
        }

        // These are all the possible game states. Every screen in the game
will set
        // one of these
        // after it is activated.
        ScreenAnimationListener animListener = null;
        UIThreadHandler handler = new UIThreadHandler();

        private Bundle mAltBundle = null;

        ViewGroup mCurrentScreen = null; // ! A reference to the currently
displayed
        private int mCurrentScreenId = -1;

        Animation mInAnimation = null; // ! The animation used for a view
coming in.
        Animation mOutAnimation = null; // ! The animation used for an
exiting view.

        int mLevelIndex = 0; // ! The array index of the current level.

        boolean mPaused = false;

        boolean mRestoring = false; // ! A flag used to determine if a view
is being

        public ScreenController(Context context, AttributeSet attrs) {
                super(context, attrs);
        }

        public Bundle getAltBundle() {
                return mAltBundle;
        }

        @Override
        public UIThreadHandler getHandler() {
                return handler;
        }

        public int getScreenId() {
                return mCurrentScreenId;
        }

        public void restoreScreenState(Bundle bundle) {
                mCurrentScreenId = bundle.getInt(SCREEN_ID);

                showScreen(mCurrentScreenId);

                if ( mCurrentScreen != null ) {
                        
((ScreenLayout)mCurrentScreen.getChildAt(0)).restoreState
(bundle);
                }
        }

        public Bundle saveScreenState() {
                Bundle map = new Bundle();

                map.putInt(SCREEN_ID, mCurrentScreenId);

                // Save level scores.
                if ( mCurrentScreen != null ) {
                        
((ScreenLayout)mCurrentScreen.getChildAt(0)).saveState(map);
                }
        return map;
        }

        /** Initializes our game controller **/
        public void init(boolean start) {
                GameTimer.getTimer().start(start);

                animListener = new ScreenAnimationListener();

                mInAnimation = getInAnimation();

                mOutAnimation = getOutAnimation();

                mOutAnimation.setAnimationListener(animListener);

                mInAnimation.setAnimationListener(animListener);

                if (start)
                        showScreen(R.layout.title_screen);
        }

        public ScreenLayout getActiveScreen() {
                return (ScreenLayout)mCurrentScreen.getChildAt(0);
        }

        /**
         * Clears out a screen. Usually called after the out animation has
completed
         **/
        public void removeScreen() {
                if (mCurrentScreen != null) {
                        mCurrentScreen.removeAllViews();
                        mCurrentScreen = null;
                }
        }

        /**
         * Screen swap function. Calling this will swap out the current
screen with
         * the specified one.
         **/
        public void showScreen(int screenId) {
                // First, find the view requested.
                if (mCurrentScreen != null) {
                        animListener.setNextScreen(screenId);
                        mCurrentScreen.startAnimation(mOutAnimation);
                } else {
                        postInvalidate();
                        mCurrentScreenId = screenId;
                        ViewGroup v1 = (ViewGroup) findViewById(R.id.rootPane);
                        mCurrentScreen = (ViewGroup) View.inflate(getContext(),
                                        mCurrentScreenId, v1);
                        mCurrentScreen.startAnimation(mInAnimation);
                }
        }
}

---------------------------------------
GLView.as
---------------------------------------
public class GLView extends SurfaceView implements
SurfaceHolder.Callback {
        /**
         * An EGL helper class.
         */

        private class EglHelper {
                EGL10 mEgl;

                EGLConfig mEglConfig;

                EGLContext mEglContext;

                EGLDisplay mEglDisplay;

                EGLSurface mEglSurface;

                public EglHelper() {

                }

                /*
                 * Create and return an OpenGL surface
                 */
                public GL createSurface(SurfaceHolder holder) {
                        /*
                         * The window size has changed, so we need to create a 
new surface.
                         */
                        if (mEglSurface != null) {

                                /*
                                 * Unbind and destroy the old EGL surface, if 
there is one.
                                 */
                                mEgl.eglMakeCurrent(mEglDisplay, 
EGL10.EGL_NO_SURFACE,
                                                EGL10.EGL_NO_SURFACE, 
EGL10.EGL_NO_CONTEXT);
                                mEgl.eglDestroySurface(mEglDisplay, 
mEglSurface);
                        }

                        /*
                         * Create an EGL surface we can render into.
                         */
                        mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, 
mEglConfig,
                                        holder, null);

                        /*
                         * Before we can issue GL commands, we need to make 
sure the
context
                         * is current and bound to a surface.
                         */
                        mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, 
mEglSurface,
                                        mEglContext);

                        GL gl = mEglContext.getGL();
                        if (mGLWrapper != null) {
                                gl = mGLWrapper.wrap(gl);
                        }
                        return gl;
                }

                public void finish() {
                        if (mEglSurface != null) {
                                mEgl.eglMakeCurrent(mEglDisplay, 
EGL10.EGL_NO_SURFACE,
                                                EGL10.EGL_NO_SURFACE, 
EGL10.EGL_NO_CONTEXT);
                                mEgl.eglDestroySurface(mEglDisplay, 
mEglSurface);
                                mEglSurface = null;
                        }
                        if (mEglContext != null) {
                                mEgl.eglDestroyContext(mEglDisplay, 
mEglContext);
                                mEglContext = null;
                        }
                        if (mEglDisplay != null) {
                                mEgl.eglTerminate(mEglDisplay);
                                mEglDisplay = null;
                        }
                }

                /**
                 * Initialize EGL for a given configuration spec.
                 *
                 * @param configSpec
                 */
                public void start(int[] configSpec) {
                        /*
                         * Get an EGL instance
                         */
                        mEgl = (EGL10) EGLContext.getEGL();

                        /*
                         * Get to the default display.
                         */
                        mEglDisplay = 
mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

                        /*
                         * We can now initialize EGL for that display
                         */
                        int[] version = new int[2];
                        mEgl.eglInitialize(mEglDisplay, version);

                        EGLConfig[] configs = new EGLConfig[1];
                        int[] num_config = new int[1];
                        mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 
1,
                                        num_config);
                        mEglConfig = configs[0];

                        /*
                         * Create an OpenGL ES context. This must be done only 
once, an
                         * OpenGL context is a somewhat heavy object.
                         */
                        mEglContext = mEgl.eglCreateContext(mEglDisplay, 
mEglConfig,
                                        EGL10.EGL_NO_CONTEXT, null);

                        mEglSurface = null;
                }

                /**
                 * Display the current render surface.
                 *
                 * @return false if the context has been lost.
                 */
                public boolean swap() {
                        mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);

                        /*
                         * Always check for EGL_CONTEXT_LOST, which means the 
context and
                         * all associated data were lost (For instance because 
the device
                         * went to sleep). We need to sleep until we get a new 
surface.
                         */
                        return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
                }
        }

        /**
         * A generic GL Thread. Takes care of initializing EGL and GL.
Delegates to
         * a Renderer instance to do the actual drawing.
         *
         */

        class GLThread extends Thread {
                private boolean mContextLost;

                private boolean mDone;

                private EglHelper mEglHelper;

                private ArrayList<Runnable> mEventQueue = new 
ArrayList<Runnable>();

                private int mFrameRate;

                private boolean mHasFocus;

                private boolean mHasSurface;

                private int mHeight;

                private boolean mPaused;

                private Renderer3D mRenderer;

                private int mWidth;

                GLThread(Renderer3D renderer, String threadName) {
                        super();
                        mDone = false;
                        mWidth = 0;
                        mHeight = 0;
                        mRenderer = renderer;
                        mFrameRate = renderer.getFrameRate();
                        setName(threadName);
                }

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

                        }
                        return null;
                }

                private void guardedRun() throws InterruptedException {
                        mEglHelper = new EglHelper();
                        /*
                         * Specify a configuration for our opengl session and 
grab the
first
                         * configuration that matches is
                         */
                        int[] configSpec = mRenderer.getConfigSpec();
                        mEglHelper.start(configSpec);

                        GL10 gl = null;
                        boolean tellRendererSurfaceCreated = true;
                        boolean tellRendererSurfaceChanged = true;

                        int delta = -1;
                        if (mFrameRate > 0) {
                                delta = 1000 / mFrameRate;
                        }
                        long time = System.currentTimeMillis();

                        /*
                         * This is our main activity thread's loop, we go until 
asked to
                         * quit.
                         */
                        while (!mDone) {

                                /*
                                 * Update the asynchronous state (window size)
                                 */
                                int w, h;
                                boolean changed;
                                boolean needStart = false;
                                synchronized (this) {
                                        Runnable r;
                                        while ((r = getEvent()) != null) {
                                                r.run();
                                        }
                                        if (mPaused) {
                                                mEglHelper.finish();
                                                needStart = true;
                                        }
                                        if (needToWait()) {
                                                while (needToWait()) {
                                                        wait();
                                                }
                                        }
                                        if (mDone) {
                                                break;
                                        }
                                        changed = mSizeChanged;
                                        w = mWidth;
                                        h = mHeight;
                                        mSizeChanged = false;
                                }
                                if (needStart) {
                                        mEglHelper.start(configSpec);
                                        tellRendererSurfaceCreated = true;
                                        changed = true;
                                }
                                if (changed) {
                                        gl = (GL10) 
mEglHelper.createSurface(mHolder);
                                        tellRendererSurfaceChanged = true;
                                }
                                if (tellRendererSurfaceCreated) {
                                        mRenderer.surfaceCreated(gl);
                                        tellRendererSurfaceCreated = false;
                                }
                                if (tellRendererSurfaceChanged) {
                                        mRenderer.sizeChanged(gl, w, h);
                                        tellRendererSurfaceChanged = false;
                                }
                                if ((w > 0) && (h > 0)) {
                                        /* sync frame rate */
                                        if (System.currentTimeMillis() - time < 
delta) {
                                                try {
                                                        
Thread.sleep(System.currentTimeMillis() - time);
                                                } catch (InterruptedException 
ex) {
                                                }
                                        }

                                        /* draw a frame here */
                                        mRenderer.drawFrame(gl);

                                        time = System.currentTimeMillis();

                                        /*
                                         * Once we're done with GL, we need to 
call swapBuffers() to
                                         * instruct the system to display the 
rendered frame
                                         */
                                        mEglHelper.swap();
                                }
                        }

                        /*
                         * clean-up everything...
                         */
                        mEglHelper.finish();
                }

                private boolean needToWait() {
                        return (mPaused || (!mHasFocus) || (!mHasSurface) || 
mContextLost)
                                        && (!mDone);
                }

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

                public void onResume() {
                        synchronized (this) {
                                mPaused = false;
                                notify();
                        }
                }

                public void onWindowFocusChanged(boolean hasFocus) {
                        synchronized (this) {
                                mHasFocus = hasFocus;
                                if (mHasFocus == true) {
                                        notify();
                                }
                        }
                }

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

                /**
                 * 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);
                        }
                }

                public void requestExitAndWait() {
                        // don't call this from GLThread thread or it is a 
guaranteed
                        // deadlock!
                        synchronized (this) {
                                mDone = true;
                                notify();
                        }
                        try {
                                join();
                        } catch (InterruptedException ex) {
                                Thread.currentThread().interrupt();
                        }
                }

                @Override
                public void run() {
                        /*
                         * 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 {
                                        sEglSemaphore.acquire();
                                } catch (InterruptedException e) {
                                        return;
                                }
                                guardedRun();
                        } catch (InterruptedException e) {
                                // fall thru and exit normally
                        } finally {
                                sEglSemaphore.release();
                        }
                }

                public void surfaceCreated() {
                        synchronized (this) {
                                mHasSurface = true;
                                mContextLost = false;
                                notify();
                        }
                }

                public void surfaceDestroyed() {
                        synchronized (this) {
                                mHasSurface = false;
                                notify();
                        }
                }
        }

        public interface GLWrapper {
                GL wrap(GL gl);
        }

        /**
         * A generic renderer interface.
         */
        public interface Renderer3D {

                String name();

                /**
                 * Draw the current frame.
                 *
                 * @param gl
                 */
                void drawFrame(GL10 gl);

                /**
                 * @return the EGL configuration specification desired by the
renderer.
                 */
                int[] getConfigSpec();

                int getFrameRate();

                void setFrameRate(int fr);

                /**
                 * Surface changed size. Called after the surface is created and
                 * whenever the OpenGL ES surface size changes. Set your 
viewport
here.
                 *
                 * @param gl
                 * @param width
                 * @param height
                 */
                void sizeChanged(GL10 gl, int width, int height);

                /**
                 * Surface created. Called when the surface is created. Called 
when
the
                 * application starts, and whenever the GPU is reinitialized. 
This
will
                 * typically happen when the device awakes after going to 
sleep. Set
                 * your textures here.
                 */
                void surfaceCreated(GL10 gl);
        }

        private static final Semaphore sEglSemaphore = new Semaphore(1);

        private GLThread mGLThread;

        private GLWrapper mGLWrapper;

        private SurfaceHolder mHolder;

        private boolean mSizeChanged = true;

        public GLView(Context context) {
                super(context);
                init();
        }

        public GLView(Context context, AttributeSet attrs) {
                super(context, attrs);
                init();
        }

        private void init() {
                // Install a SurfaceHolder.Callback so we get notified when the
                // underlying surface is created and destroyed
                mHolder = getHolder();
                mHolder.addCallback(this);
                mHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
        }

        @Override
        protected void onDetachedFromWindow() {
                super.onDetachedFromWindow();
                mGLThread.requestExitAndWait();
        }

        /**
         * Inform the view that the activity is paused.
         */
        public void onPause() {
                mGLThread.onPause();
        }

        /**
         * Inform the view that the activity is resumed.
         */
        public void onResume() {
                mGLThread.onResume();
        }

        /**
         * Inform the view that the window focus has changed.
         */
        @Override
        public void onWindowFocusChanged(boolean hasFocus) {
                super.onWindowFocusChanged(hasFocus);
                mGLThread.onWindowFocusChanged(hasFocus);
        }

        /**
         * 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) {
                mGLThread.queueEvent(r);
        }

        public void setGLWrapper(GLWrapper glWrapper) {
                mGLWrapper = glWrapper;
        }

        public void setRenderer(Renderer3D renderer) {
                mGLThread = new GLThread(renderer, renderer.name());
                mGLThread.start();
        }

        public void surfaceChanged(SurfaceHolder holder, int format, int w,
int h) {
                // Surface size or format has changed. This should not happen in
this
                // example.
                mGLThread.onWindowResize(w, h);
        }

        public void surfaceCreated(SurfaceHolder holder) {
                mGLThread.surfaceCreated();
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
                // Surface will be destroyed when we return
                mGLThread.surfaceDestroyed();
        }
}

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers-unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to