From f93b95b3a4a36d8bba4826eb40243c76a1ab0881 Mon Sep 17 00:00:00 2001 From: "kim..ng" Date: Tue, 24 May 2011 14:57:50 +0000 Subject: [PATCH] Android: Fixed app lifecycle. If you leave your activity with the back key the app will be destroyed, if you use the home key the app gets frozen in the background. You can return to it and it will be in the same state as when you left it. git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7522 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../android/com/jme3/app/AndroidHarness.java | 59 +++++++++++++++---- .../jme3/renderer/android/OGLESRenderer.java | 18 ++++++ .../renderer/android/OGLESShaderRenderer.java | 53 ++++++++++++----- .../com/jme3/system/android/OGLESContext.java | 40 ++++++++++--- 4 files changed, 136 insertions(+), 34 deletions(-) diff --git a/engine/src/android/com/jme3/app/AndroidHarness.java b/engine/src/android/com/jme3/app/AndroidHarness.java index 3071cedf6..67af93b60 100644 --- a/engine/src/android/com/jme3/app/AndroidHarness.java +++ b/engine/src/android/com/jme3/app/AndroidHarness.java @@ -18,8 +18,9 @@ import com.jme3.system.android.OGLESContext; /** - * + * AndroidHarness wraps a jme application object and runs it on Android * @author Kirill + * @author larynx */ public class AndroidHarness extends Activity implements DialogInterface.OnClickListener { @@ -30,6 +31,8 @@ public class AndroidHarness extends Activity implements DialogInterface.OnClickL protected String appClass = "jme3test.android.Test"; protected Application app = null; + + protected boolean debug = false; @Override public void onCreate(Bundle savedInstanceState) @@ -57,31 +60,60 @@ public class AndroidHarness extends Activity implements DialogInterface.OnClickL } app.setSettings(settings); - app.start(); - + app.start(); ctx = (OGLESContext) app.getContext(); - view = ctx.createView(input); + if (debug) + { + view = ctx.createView(input, GLSurfaceView.DEBUG_CHECK_GL_ERROR | GLSurfaceView.DEBUG_LOG_GL_CALLS); + } + else + { + view = ctx.createView(input); + } setContentView(view); } + + @Override + protected void onRestart(){ + super.onRestart(); + app.restart(); + logger.info("onRestart"); + } + + + @Override + protected void onStart(){ + super.onStart(); + logger.info("onStart"); + } + @Override protected void onResume() { super.onResume(); view.onResume(); + logger.info("onResume"); } @Override protected void onPause() { super.onPause(); view.onPause(); + logger.info("onPause"); + } + + @Override + protected void onStop(){ + super.onStop(); + logger.info("onStop"); } -// @Override -// protected void onDestroy(){ -// super.onDestroy(); - -// Debug.stopMethodTracing(); -// } + @Override + protected void onDestroy(){ + super.onDestroy(); + app.stop(); + logger.info("onDestroy"); + } /** @@ -100,8 +132,13 @@ public class AndroidHarness extends Activity implements DialogInterface.OnClickL { s += ste.getClassName() + "." + ste.getMethodName() + "(" + + ste.getLineNumber() + ") "; } - } + } + final String sTrace = s; + + logger.severe(t != null ? t.toString() : "Failed"); + logger.severe((errorMsg != null ? errorMsg + ": " : "") + sTrace); + this.runOnUiThread(new Runnable() { @Override public void run() diff --git a/engine/src/android/com/jme3/renderer/android/OGLESRenderer.java b/engine/src/android/com/jme3/renderer/android/OGLESRenderer.java index 7d7244a8b..47d9cedd1 100644 --- a/engine/src/android/com/jme3/renderer/android/OGLESRenderer.java +++ b/engine/src/android/com/jme3/renderer/android/OGLESRenderer.java @@ -988,4 +988,22 @@ public final class OGLESRenderer implements Renderer { } } + @Override + public void invalidateState() { + // TODO Auto-generated method stub + + } + + @Override + public void deleteImage(Image image) { + // TODO Auto-generated method stub + + } + + @Override + public void setAlphaToCoverage(boolean value) { + // TODO Auto-generated method stub + + } + } diff --git a/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java b/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java index 4c30650e5..95cca4b3b 100644 --- a/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java +++ b/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java @@ -32,6 +32,7 @@ package com.jme3.renderer.android; +import com.jme3.asset.TextureKey; import com.jme3.light.LightList; import com.jme3.material.RenderState; import com.jme3.math.ColorRGBA; @@ -57,6 +58,7 @@ import com.jme3.shader.Shader; import com.jme3.shader.Shader.ShaderSource; import com.jme3.shader.Shader.ShaderType; import com.jme3.shader.Uniform; +import com.jme3.system.JmeSystem; import com.jme3.texture.FrameBuffer; import com.jme3.texture.FrameBuffer.RenderBuffer; import com.jme3.texture.Image; @@ -77,6 +79,8 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.microedition.khronos.opengles.GL10; + +import android.graphics.Bitmap; import android.opengl.GLES10; import android.opengl.GLES11; import android.opengl.GLES20; @@ -407,7 +411,11 @@ public class OGLESShaderRenderer implements Renderer { logger.log(Level.INFO, "Caps: " + caps); } - public void resetGLObjects(){ + /** + * resetGLObjects should be called when die GLView gets recreated to reset all GPU objects + */ + public void resetGLObjects() + { objManager.resetObjects(); statistics.clearMemory(); boundShader = null; @@ -1853,18 +1861,29 @@ public class OGLESShaderRenderer implements Renderer { img.clearUpdateNeeded(); } - public void setTexture(int unit, Texture tex){ + public void setTexture(int unit, Texture tex) + { Image image = tex.getImage(); - if (image.isUpdateNeeded()){ + if (image.isUpdateNeeded()) + { + Bitmap bmp = (Bitmap)image.getEfficentData(); + // Check if the bitmap got recycled, can happen after wakeup/restart + if ( bmp.isRecycled() ) + { + // We need to reload the bitmap + Texture textureReloaded = JmeSystem.newAssetManager().loadTexture((TextureKey)tex.getKey()); + image.setEfficentData( textureReloaded.getImage().getEfficentData()); + } updateTexImageData(image, tex.getType(), tex.getMinFilter().usesMipMapLevels()); } int texId = image.getId(); assert texId != -1; - if (texId == -1) { - logger.warning("error: texture image has -1 id"); - } + if (texId == -1) + { + logger.warning("error: texture image has -1 id"); + } Image[] textures = context.boundTextures; @@ -1877,22 +1896,26 @@ public class OGLESShaderRenderer implements Renderer { // glEnable(type); } - if (textures[unit] != image){ - if (context.boundTextureUnit != unit){ - if (verboseLogging) - logger.info("GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + " + unit + ")"); - GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + unit); - context.boundTextureUnit = unit; + if (textures[unit] != image) + { + if (context.boundTextureUnit != unit) + { + if (verboseLogging) + logger.info("GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + " + unit + ")"); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + unit); + context.boundTextureUnit = unit; } - if (verboseLogging) - logger.info("GLES20.glBindTexture(" + type + ", " + texId + ")"); + if (verboseLogging) + logger.info("GLES20.glBindTexture(" + type + ", " + texId + ")"); GLES20.glBindTexture(type, texId); textures[unit] = image; statistics.onTextureUse(tex.getImage(), true); - }else{ + } + else + { statistics.onTextureUse(tex.getImage(), false); } diff --git a/engine/src/android/com/jme3/system/android/OGLESContext.java b/engine/src/android/com/jme3/system/android/OGLESContext.java index 3b569067c..069300148 100644 --- a/engine/src/android/com/jme3/system/android/OGLESContext.java +++ b/engine/src/android/com/jme3/system/android/OGLESContext.java @@ -90,13 +90,32 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer return Type.Display; } + /** + * createView + * @param activity The Android activity which is parent for the GLSurfaceView + * @return GLSurfaceView The newly created view + */ public GLSurfaceView createView(Activity activity) { return createView(new AndroidInput(activity)); } - - + /** + * createView + * @param AndroidInput The Android input which must be bound to an activity + * @return GLSurfaceView The newly created view + */ public GLSurfaceView createView(AndroidInput view) + { + return createView(view, 0); + } + + /** + * createView + * @param AndroidInput The Android input which must be bound to an activity + * @param debugflags 0, GLSurfaceView.DEBUG_CHECK_GL_ERROR | GLSurfaceView.DEBUG_LOG_GL_CALLS + * @return GLSurfaceView The newly created view + */ + public GLSurfaceView createView(AndroidInput view, int debugflags) { this.view = view; @@ -112,11 +131,9 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer view.setFocusableInTouchMode(true); view.setFocusable(true); view.getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU); -// view.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR); -// | GLSurfaceView.DEBUG_LOG_GL_CALLS); + view.setDebugFlags(debugflags); view.setRenderer(this); return view; - } @@ -253,9 +270,16 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer @Override public void onSurfaceCreated(GL10 gl, EGLConfig cfg) { - logger.info("GL Surface created"); - initInThread(); - renderable.set(true); + if (created.get() && renderer != null) + { + renderer.resetGLObjects(); + } + else + { + logger.info("GL Surface created"); + initInThread(); + renderable.set(true); + } } // SystemListener:reshape