Crash on Galaxy S3

Started by AugTech, January 07, 2013, 09:34:28 PM

Previous topic - Next topic

AugTech

Hi,

I have just released a new version of our app, and unfortunately there is a repeatable crash on a galaxy S3. The only 'big' difference I can think of between that and the galaxy S2 I have always tested on is Android 4.x vs 2.3.3 ... The only information I have (not owning an S3) is the reported stack trace as below;


java.lang.RuntimeException: [ 1357589905458 ] - ERROR: before: glError 1281
at com.threed.jpct.Logger.log(Logger.java:189)
at com.threed.jpct.GL20.checkError(GL20.java:142)
at com.threed.jpct.GL20.glGenBuffers(GL20.java:1324)
at com.threed.jpct.CompiledInstance.compileToVBO(CompiledInstance.java:1299)
at com.threed.jpct.CompiledInstance.render(CompiledInstance.java:533)
at com.threed.jpct.GLRenderer.drawVertexArray(GLRenderer.java:2246)
at com.threed.jpct.World.draw(World.java:1321)
at com.threed.jpct.World.draw(World.java:1083)
at com.augtech.awila.graphics.JpctRenderer.onDrawFrame(JpctRenderer.java:165)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)


This happens after starting a new activity (such as a dialog) and then returning to the main activity that runs the rendering.

Could this be related to not re-creating the frame buffer if not required?


@Override
public void onSurfaceChanged(GL10 ignore, int width, int height) {
Globals.SCREEN_WIDTH = width;
Globals.SCREEN_HEIGHT = height;
if (frameBuffer==null) {
        frameBuffer = new FrameBuffer(Globals.SCREEN_WIDTH, Globals.SCREEN_HEIGHT);
        Log.i(LOG_TAG,"Frame buffer set - w: "+ Globals.SCREEN_WIDTH + ", h: "+Globals.SCREEN_HEIGHT );
}
}



Any ideas?!?
Many thanks in advance

EgonOlsen

Quote from: AugTech on January 07, 2013, 09:34:28 PM
Could this be related to not re-creating the frame buffer if not required?
Yes, most likely. If the context changes, the FrameBuffer should be recreated or otherwise, the gl context isn't initialized properly to be used by jPCT-AE.

AugTech

This seems to work happily on the other devices I have tested on, so a little strange... I had thought that onSurfacedChanged() was only called when the surface dimensions changed, and therefore as the layout is fixed to landscape within the application this wouldn't get called again via onResume() or similar.

If this is the case, is there a way to check if the context has changed prior to creating a new buffer? - Previously I wasn't checking if the frame buffer was null and therefore always re-creating it, but as you know re-initialising the context/ buffer causes a major slow-down, hence the change.

Cheers Egon.

EgonOlsen

I *think* that previous versions of Android never saved the context and always created a new one. They then made this behaviour a little smarter, but i'm neither sure if there is a way to detect this nor if it's save to rely on it. One, albeit unsave, option would be to check for the Android version and only rely on a saved context in 4 and above.

However, how comes that a S3 runs with 2.3.3 (or did i get this wrong?)? There never was a S3 with such an old version...

Thomas.

#4
Method onSurfaceChanged() will not be called by change of the orientation if you add the following line into your manifest.

android:restoreNeedsApplication="true"

edit: Oh, it was deprecated in API level 8...

AugTech

Ah.. The orientation is not changing anyway, due to android:screenOrientation="landscape" in the manifest.

Sorry for the confusion - The S3 is on Android 4.x.  My regular test/ dev device is an S2 which is on 2.3.3 - This has not shown the error, whereas the S3 has. Not sure how this fits with 4.x 'trying' to save the context...

EgonOlsen

Quote from: AugTech on January 07, 2013, 10:30:09 PM
Not sure how this fits with 4.x 'trying' to save the context...
Maybe it doesn't do this then...i'm left in that dark with all this context management of Android too. That's why i suggest to not rely on anything in this case and create a new buffer every time.

AugTech

:( I'll loose those valuable 1.8 seconds I thought I'd gained onResume() - Better than not crashing though!

Thanks Egon.

AugTech

As a footnote to this...

As I have to dispose and re-create the FrameBuffer each time, I thought I'd see if there were other ways to speed up the process.
I found that onSurfaceChanged() is actually being called twice, which I believe is an Android issue, and not mine.

Anyway, I've implemented a counter that is reset in the GLSurfaceView.onResume() method, so now when onSurfaceChanged() has been called once it isn't called again.  This is probably shaved 1/3 off the restart time.


@Override
public void onSurfaceChanged(GL10 ignore, int width, int height) {
if (SURFACE_RESTART_COUNT > 0) return;
SURFACE_RESTART_COUNT++;
Globals.SCREEN_WIDTH = width;
Globals.SCREEN_HEIGHT = height;
if (frameBuffer!=null) frameBuffer.dispose();
        frameBuffer = new FrameBuffer(Globals.SCREEN_WIDTH, Globals.SCREEN_HEIGHT);

        Log.i(LOG_TAG,"Frame buffer set - w: "+ Globals.SCREEN_WIDTH + ", h: "+Globals.SCREEN_HEIGHT );
}


Cheers.

EgonOlsen

Every Android version seems to change that behaviour. When pressing the lock-button, my Galaxy Note calls: onPause, onStop, onDestroy (with isFinishing() returning false), onCreate, onResume, onPause and onResume. After all that, my game runs behind the lock screen.... :o