5

As per the title, the GLSurfaceView is blank after resuming from a paused state. The Renderer's onSurfaceCreated, onSurfaceChanged, and onDrawFrame get called after it resumes, but the screen is still blank!

Here's the relevant code:

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    gl.glShadeModel(GL10.GL_SMOOTH);
    gl.glClearDepthf(1.0f);
    gl.glEnable(GL10.GL_DEPTH_TEST);
    gl.glDepthFunc(GL10.GL_LEQUAL);

    boxWidth = 0.5f;
    boxHeight = 0.5f;
    boxCenter = new float[] { 0.5f, 0.5f };

    Log.v("resume", "onSurfaceCreated");
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {      
    gl.glViewport(0, 0, width, height);
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    gl.glOrthof(0, 1, 0, 1, -5, 5);
    gl.glMatrixMode(GL10.GL_MODELVIEW);

    viewHeight = height;
    viewWidth = width;

    Log.v("resume", "onSurfaceChanged");
}

@Override
public void onDrawFrame(GL10 gl) {
    gl.glLoadIdentity();

    float halfW = boxWidth/2.0f;
    float halfH = boxHeight/2.0f;

    float left = Math.max(boxCenter[0]-halfW, 0.001f);
    float right = Math.min(boxCenter[0]+halfW, 0.999f);
    float top = Math.min(boxCenter[1]+halfH, 0.999f);
    float bottom = Math.max(boxCenter[1]-halfH, 0.001f);

    boxHeight = Math.max(top - bottom, 0.05f);
    boxWidth = Math.max(right - left, 0.05f);
    boxCenter[0] = left + boxWidth/2.0f;
    boxCenter[1] = bottom + boxHeight/2.0f;

    float vertices[] = {
            left, top, 0.0f,
            left, bottom, 0.0f,
            right, bottom, 0.0f,
            right, top, 0.0f
    };

    ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    vertexBuffer = byteBuf.asFloatBuffer();
    vertexBuffer.put(vertices);

    gl.glTranslatef(0.001f, -0.001f, -3.0f);

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | 
            GL10.GL_DEPTH_BUFFER_BIT);

    vertexBuffer.position(0);

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, 
            vertexBuffer);

    gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

    gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, 4);
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

    Log.v("resume", "drawing");
}

I've read that you need to recreate the GL context inside onSurfaceChanged, but I'm not sure how, or if I already did when onSurfaceCreated was called.

Please help!

Edit: Here's the onResume code from the Activity that contains the GLSurfaceView: (called GLSurface here)

public void onResume() {
   super.onResume();
   if (mGLSurface != null) {
   if (mRenderer != null) {
      float[] center = new float[2];
      center[0] = settings.getFloat("renderer_boxCenter0", 0.5f);
      center[1] = settings.getFloat("renderer_boxCenter1", 0.5f);
      mRenderer.setBoxCenter(center);
      mRenderer.setBoxWidth(settings.getFloat("renderer_boxWidth", 0.5f));
      mRenderer.setBoxHeight(settings.getFloat("renderer_boxHeight", 0.5f));
   }
   mGLSurface.onResume();
}

I didn't do much in the onResume for the GLSurfaceView, and I didn't find any documentation that suggested that I need to do anything in particular to get my EGL context back either.

Edit 2: I would also like to note that calling setPreserveEGLContextOnPause(true) in the constructor of my GLSurfaceView did not, unfortunately, solve my problem.

confusedKid
  • 3,231
  • 6
  • 30
  • 49
  • Maybe post your onResume() code and also where you initialise and set up the GLSurfaceView view – James Coote Nov 22 '11 at 16:51
  • Try setting `gl.glOrthof(0, 1, 0, 1, -5, 5);` at the end of onSurfaceCreated and see whether anything appears when you first run the app. If that makes no difference, try setting `gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);` (i.e. setting the background colour red) in onDraw, and then changing it to `gl.glClearColor(0.0f, 0.0f, 1.0f, 0.0f);` (i.e. blue) after onResume() is called. That way you can tell if openGL is actually responding to what you're doing – James Coote Dec 02 '11 at 14:57
  • Ok, I tried that. The first suggestion didn't make any differences. In the second case, I saw the blue box flicker briefly before the screen turned black. What do you make of this? – confusedKid Dec 08 '11 at 21:49
  • I tried out all of your code in your question. It works fine on my ZTE Blade running android 2.1, and also on a HTC Wildfire and Kindle Fire. I did not however extend GLSurfaceView, so the problem is in your GLSurfaceView code, rather than in your Renderer or Activity – James Coote Dec 13 '11 at 20:55
  • I also tried in the emulator running 3.0 (API 11) and extended GLSurfaceView with nothing but super calls in each of the methods (2 constructors, onPause and onResume) plus setPreserveEGLContextOnPause(true) in both constructors. Again worked ok – James Coote Dec 13 '11 at 21:32
  • Alright. Thanks. I'm using the Samsung Galaxy Tab (3.1), not sure if this matters though. I guess I'll try to recode it from scratch and see if it works >. – confusedKid Dec 16 '11 at 00:47
  • Just recode your GLSurfaceView. The Renderer and the rest are fine. I know the android documentation says to extend GLSurfaceView, but I implemented my entire app without doing so. Trying to find out if there is a reason that I'm missing for doing so: http://www.anddev.org/post107733.html#p107733 – James Coote Dec 16 '11 at 11:34

2 Answers2

6

setPreserveEGLContextOnPause(true) is only supported on devices with Android 3.X and up. (even then it is device specific whether it is supported)

The solution your looking for is in the parent activity of the GlSurfaceView you call GlSurfaceView.onPause() in the onPause method of the activity and GlSurfaceView.onResume() in the onResume method of the activity.

Note this causes all of your textures and buffers to be lost. You need to reload them at this point.

user1659134
  • 93
  • 2
  • 7
0

This is a bit of a long shot, but do you try to control orientation or config changes (i.e. do you have public void onConfigurationChanged(Configuration config) in overridden your activity)?

I found that if I have onConfigurationChanges() overriden in my activity and android:screenOrientation="landscape" in my manifest file but not android:configChanges="orientation" I get something like what you describe

James Coote
  • 1,975
  • 19
  • 29
  • Hi, I have forced my application to only load in the landscape orientation, though I haven't actually overridden onConfigurationChanges(). I just put `android:screenOrientation="landscape"` in my manifest file. – confusedKid Dec 08 '11 at 21:36
  • Try overriding `onConfigurationChanges()` and adding the corresponding `configChanges="orientation"` in the manifest file and see if that fixes it, even if you just call super from onConfigurationChanges and don't actually do anything in it. It solved the problem for my own app at least. The downside is it does produce the rather annoying side effect that on slower devices, the app will show a messed-up portrait view of your app for a fraction of a second after it resumes before switching correctly to landscape. – James Coote Dec 09 '11 at 14:25
  • Did you mean `onConfigurationChanged()`? I tried to override that and added the `configChanges` as you suggested, but the problem persists. – confusedKid Dec 13 '11 at 00:26