Hello,

I played a little with GLSurfaceView introduced in SDK 1.5 release and
it appears that only one instance of it can be used at a time. If
another instance is created on top then the associated renderer is not
invoked. It is demonstrated by the below code, which is slightly
reworked GLSurfaceView usage example posted here
http://android-developers.blogspot.com/2009/04/introducing-glsurfaceview.html

The modification is that once the finger is lifted off from the screen
another instance of the ClearActivity is created, which in turn
creates one more instance of ClearGLSurfaceView. However the
associated renderer is never invoked

--- Source code starts here
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import dalvik.system.VMRuntime;

public class ClearActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        instance = counter++;
        Log.e("ClearActivity", ":::::: onCreate: instance" + instance + "
is created");
        super.onCreate(savedInstanceState);
        mGLView = new ClearGLSurfaceView(this);
        setContentView(mGLView);
    }

    @Override
    protected void onPause() {
        Log.e("ClearActivity", ":::::: instance" + instance + " onPause:
is called");
        super.onPause();
        mGLView.onPause();
    }

    @Override
    protected void onResume() {
        Log.e("ClearActivity", ":::::: instance" + instance + " onResume:
is called");
        super.onResume();
        mGLView.onResume();
    }

    @Override
    protected void onStop() {
        Log.e("ClearActivity", ":::::: instance" + instance + " onStop:
is called");
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        Log.e("ClearActivity", ":::::: instance" + instance + "
onDestroy: is called");
        super.onDestroy();
    }

    private GLSurfaceView mGLView;

    private static int counter = 0;
    private int        instance;
}

class ClearGLSurfaceView extends GLSurfaceView {
    public ClearGLSurfaceView(Context context) {
        super(context);
        instance = counter++;
        Log.e("ClearGLSurfaceView", ":::::: instance" + instance + " is
created");
        mRenderer = new ClearRenderer();
        setRenderer(mRenderer);
    }

    public boolean onTouchEvent(final MotionEvent event) {
        switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE: {// falling through on purpose
here
                Log.e("ClearGLSurfaceView", ":::::: instance" + instance + "
onTouchEvent: handling down or move action");
                        queueEvent(new Runnable(){
                                public void run() {
                                        mRenderer.setColor(event.getX() / 
getWidth(),
                                                event.getY() / getHeight(), 
1.0f);
                                }}
                        );
                        return true;
                }
                case MotionEvent.ACTION_UP: {
                        // launch a second instance of the same activity
                Log.e("ClearGLSurfaceView", ":::::: instance" + instance + "
onTouchEvent: handling up action");
                        Intent intent = new Intent();
                        intent.setClass(getContext(), ClearActivity.class);
                        getContext().startActivity(intent);
                }

        }
        return true;
    }

    @Override
    protected void onDetachedFromWindow() {
        Log.e("ClearGLSurfaceView", ":::::: instance" + instance + "
onDetachedFromWindow: is called");
        super.onDetachedFromWindow();
    }

    ClearRenderer mRenderer;

    private static int counter = 0;
    private int instance;
}

class ClearRenderer implements GLSurfaceView.Renderer {
        public ClearRenderer() {
                instance = counter++;
        Log.e("ClearRenderer", ":::::: instance" + instance + " is
created");
        }

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // Do nothing special.
        Log.e("ClearRenderer", ":::::: instance" + instance + "
onSurfaceCreated: is called");
    }

    public void onSurfaceChanged(GL10 gl, int w, int h) {
        Log.e("ClearRenderer", ":::::: instance" + instance + "
onSurfaceChanged: is called");
        gl.glViewport(0, 0, w, h);
    }

    public void onDrawFrame(GL10 gl) {
        gl.glClearColor(mRed, mGreen, mBlue, 1.0f);
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT |
GL10.GL_DEPTH_BUFFER_BIT);
    }

    public int[] getConfigSpec() {
        Log.e("ClearRenderer", ":::::: instance" + instance + "
getConfigSpec: is called");
                int[] configSpec = { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE };
                return configSpec;
    }

    public void setColor(float r, float g, float b) {
        Log.e("ClearRenderer", ":::::: instance" + instance + " setColor:
is called");
        mRed = r;
        mGreen = g;
        mBlue = b;
    }

    private float mRed;
    private float mGreen;
    private float mBlue;

    private static int counter = 0;
    private int instance;
--- Source code ends here

--- Log starts here
E/ClearActivity( 1092): :::::: onCreate: instance0 is created
E/ClearGLSurfaceView( 1092): :::::: instance0 is created
E/ClearRenderer( 1092): :::::: instance0 is created
E/ClearRenderer( 1092): :::::: instance0 getConfigSpec: is called
E/ClearActivity( 1092): :::::: instance0 onResume: is called
E/ClearRenderer( 1092): :::::: instance0 onSurfaceCreated: is called
E/ClearRenderer( 1092): :::::: instance0 onSurfaceChanged: is called
E/ClearGLSurfaceView( 1092): :::::: instance0 onTouchEvent: handling
down or move action
E/ClearRenderer( 1092): :::::: instance0 setColor: is called
E/ClearGLSurfaceView( 1092): :::::: instance0 onTouchEvent: handling
down or move action
E/ClearRenderer( 1092): :::::: instance0 setColor: is called
E/ClearGLSurfaceView( 1092): :::::: instance0 onTouchEvent: handling
down or move action
E/ClearRenderer( 1092): :::::: instance0 setColor: is called
E/ClearGLSurfaceView( 1092): :::::: instance0 onTouchEvent: handling
down or move action
E/ClearRenderer( 1092): :::::: instance0 setColor: is called
E/ClearGLSurfaceView( 1092): :::::: instance0 onTouchEvent: handling
down or move action
E/ClearRenderer( 1092): :::::: instance0 setColor: is called
E/ClearGLSurfaceView( 1092): :::::: instance0 onTouchEvent: handling
down or move action
E/ClearRenderer( 1092): :::::: instance0 setColor: is called
E/ClearGLSurfaceView( 1092): :::::: instance0 onTouchEvent: handling
up action
E/ClearActivity( 1092): :::::: instance0 onPause: is called
E/ClearActivity( 1092): :::::: onCreate: instance1 is created
E/ClearGLSurfaceView( 1092): :::::: instance1 is created
E/ClearRenderer( 1092): :::::: instance1 is created
E/ClearActivity( 1092): :::::: instance1 onResume: is called
E/ClearActivity( 1092): :::::: instance0 onStop: is called
E/ClearGLSurfaceView( 1092): :::::: instance1 onTouchEvent: handling
down or move action
E/ClearGLSurfaceView( 1092): :::::: instance1 onTouchEvent: handling
down or move action
E/ClearGLSurfaceView( 1092): :::::: instance1 onTouchEvent: handling
down or move action
E/ClearGLSurfaceView( 1092): :::::: instance1 onTouchEvent: handling
down or move action
--- Log ends here

I studied the source code for GLSurfaceView and it looks like the
reason for this behavior is that the renderer provided to
GLSurfaceView is run in a separate thread implemented by the class
GLThread. Whenever the renderer is set to GLSurfaceView through
setRenderer() an instance of GLThread is created, which runs the code
for that renderer. Now, the thread acquires sEglSemaphore to run and
only releases it once mDone is set to true, which happens in
GLThread.requestExitAndWait() which is called from
GLSurfaceView.onDetachedFromWindow(). And this one is not called when
the first instance of ClearGLSurfaceView is covered by the second one
(i.e. its onPause(0 is called), it is only called when the first
instance of ClearAcitivity is destroyed at the end of its life cycle

What it looks like to me is either a bug in Android framework or
intentional limitation, which is unfortunately not documented in the
GLSurfaceView reference page 
http://developer.android.com/reference/android/opengl/GLSurfaceView.html.
Even more, the reference page says that GLSurfaceView would release
and recreate OpenGL display whenever the activity goes through pause-
resume cycle:

"GLSurfaceView clients are required to call onPause() when the
activity pauses and onResume() when the activity resumes. These calls
allow GLSurfaceView to pause and resume the rendering thread, and also
allow GLSurfaceView to release and recreate the OpenGL display. "

So, any advice (especially from Android framework team) would be
greatly appreciated

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

Reply via email to