Tomasu
Tomasu

Reputation: 181

blank screen after onResume when using GLES

I'm having a problem where when I get an onResume, I re create the EGL and GLES state from scratch, but it won't draw anything any longer. The important code is identical between the initial create and the resume code. I'm currently stumped as to what could cause this. Things work perfectly with the initial creation and display of my EGL surface. Only when the app is resumed (press home button, then go back into the app) does it fail to display anything. I've verified that everything else is behaving as it should, input is received, and android callbacks happen as normal (no blocking or locking up in either the dalvik or rendering threads). The EGL and GLES state are completely destroyed and re-created between onPause and onResume.

Upvotes: 0

Views: 2221

Answers (1)

James Coote
James Coote

Reputation: 1973

What I do is load all my 3D model vertices, textures etc into memory (not the GL handle) when the app starts or when I need them.

I have a relatively simple game app written in openGL-es 1.1 (no lighting, shaders, particles etc, just textured models). The only things I need to load into the openGL handle ahead of time are the textures, because they takes so long to load. Everything else can be done at run-time in the onDraw method of the renderer

So my code looks a bit like this:

@override
public void onPause(){

    findViewById(R.id.loading_screen).setVisibility(View.VISIBLE); 

}

@Override
public void onResume(){
    super.onResume();

    findViewById(R.id.loading_screen).setVisibility(View.VISIBLE);

    myRenderer.reLoadTextures();   

    findViewById(R.id.loading_screen).setVisibility(View.GONE);     
}

@Override
public void onRestart(){
    super.onRestart();

    findViewById(R.id.loading_screen).setVisibility(View.VISIBLE);

    myRenderer.reLoadTextures();

    findViewById(R.id.loading_screen).setVisibility(View.GONE); 
}

class MyRenderer implements Renderer{

    private HashMap<String,Texture> textures;
    private boolean reloadTextures = false;

    // flag to the renderer that textures need to be reloaded
    public void reLoadTextures(){
        reloadTextures = true;
    }

    public void onDraw(GL10 gl){

        if(reloadTextures){

            // loop through hashmap and reload textures
            Iterator it = textures.entrySet().iterator();
            while(it.hasNext()){
                Entry set = it.next();
                set.getValue().loadTexture(gl, set.getKey(), context);
            }

            reloadTextures = false;
        }

        // draw models as normal

    }

}

... which I know is not what you're really looking for. Doing it this way means it doesn't matter that the GL state is destroyed. Android will automatically give you a fresh GL state as though it is starting the app for the first time. It also means you never have to extend SurfaceView, just implement Renderer

This is the simplified version, and it gets a lot more complex once you factor in threading. There is also a bit of work in Texture.loadTexture() to make sure that the references that models use and the Id's that you get from glGenTextures still match after the app / activity is resumed.

Also, if you have android:screenOrientation="landscape" in your manifest file, make sure to handle orientation changes, as often, as is the case with my phone, the home screen and lock screen are always in portrait, and on resumption of the app, the orientation will be wrong. Not overriding onConfigurationChange() can cause problems with the GLSurfaceView (like some textures not showing) even if you've re-loaded them in onResume

Upvotes: 2

Related Questions