* Enable checking of errors per frame (if checkErrors is disabled)
 * Formatting and javadoc fixes in AndroidHarness
 * AndroidHarness.reportError() rewritten to for clarity
 * OGLESContext will report OpenGL2 failure directly to app through handleError instead of continuing execution 
 * OGLESContext will register uncaught exception handler only for current thread 
 * Formatting and javadoc fixes in OGLESContext

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9142 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Sha..rd 13 years ago
parent 65c27304be
commit 8652b1f759
  1. 172
      engine/src/android/com/jme3/app/AndroidHarness.java
  2. 8
      engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
  3. 387
      engine/src/android/com/jme3/system/android/OGLESContext.java

@ -26,97 +26,108 @@ import com.jme3.system.android.AndroidConfigChooser.ConfigType;
import com.jme3.system.android.JmeAndroidSystem;
import com.jme3.system.android.OGLESContext;
import com.jme3.util.JmeFormatter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* <code>AndroidHarness</code> wraps a jme application object and runs it on Android
* <code>AndroidHarness</code> wraps a jme application object and runs it on
* Android
*
* @author Kirill
* @author larynx
*/
public class AndroidHarness extends Activity implements TouchListener, DialogInterface.OnClickListener {
protected final static Logger logger = Logger.getLogger(AndroidHarness.class.getName());
/**
* The application class to start
*/
protected String appClass = "jme3test.android.Test";
/**
* The jme3 application object
*/
protected Application app = null;
/**
* ConfigType.FASTEST is RGB565, GLSurfaceView default
* ConfigType.BEST is RGBA8888 or better if supported by the hardware
* ConfigType.FASTEST is RGB565, GLSurfaceView default ConfigType.BEST is
* RGBA8888 or better if supported by the hardware
*/
protected ConfigType eglConfigType = ConfigType.FASTEST;
/**
* If true all valid and not valid egl configs are logged
*/
protected boolean eglConfigVerboseLogging = false;
/**
* If true MouseEvents are generated from TouchEvents
*/
protected boolean mouseEventsEnabled = true;
/**
* Flip X axis
*/
protected boolean mouseEventsInvertX = true;
/**
* Flip Y axis
*/
protected boolean mouseEventsInvertY = true;
/**
* Title of the exit dialog, default is "Do you want to exit?"
*/
protected String exitDialogTitle = "Do you want to exit?";
/**
* Message of the exit dialog, default is "Use your home key to bring this app into the background or exit to terminate it."
* Message of the exit dialog, default is "Use your home key to bring this
* app into the background or exit to terminate it."
*/
protected String exitDialogMessage = "Use your home key to bring this app into the background or exit to terminate it.";
/**
 * Set the screen window size
 * if screenFullSize is true, then the notification bar and title bar are
 *   removed and the screen covers the entire display
 * if screenFullSize is false, then the notification bar remains visible
 *   if screenShowTitle is true while screenFullScreen is false, then the
 *     title bar is also displayed under the notification bar
 */
* Set the screen window mode.
* If screenFullSize is true, then the notification bar and title bar are
* removed and the screen covers the entire display.  
* If screenFullSize is false, then the notification bar remains visible if
* screenShowTitle is true while screenFullScreen is false,
* then the title bar is also displayed under the notification bar.
*/
protected boolean screenFullScreen = true;
/**
* if screenShowTitle is true while screenFullScreen is false, then the
 *     title bar is also displayed under the notification bar
* title bar is also displayed under the notification bar
*/
protected boolean screenShowTitle = true;
/**
* Splash Screen picture Resource ID. If a Splash Screen is desired, set
* splashPicID to the value of the Resource ID (i.e. R.drawable.picname).
* If splashPicID = 0, then no splash screen will be displayed.
* Splash Screen picture Resource ID. If a Splash Screen is desired, set
* splashPicID to the value of the Resource ID (i.e. R.drawable.picname). If
* splashPicID = 0, then no splash screen will be displayed.
*/
protected int splashPicID = 0;
/**
* Set the screen orientation, default is SENSOR
* ActivityInfo.SCREEN_ORIENTATION_* constants
* package android.content.pm.ActivityInfo
*
* SCREEN_ORIENTATION_UNSPECIFIED
* SCREEN_ORIENTATION_LANDSCAPE
* SCREEN_ORIENTATION_PORTRAIT
* SCREEN_ORIENTATION_USER
* SCREEN_ORIENTATION_BEHIND
* SCREEN_ORIENTATION_SENSOR (default)
* SCREEN_ORIENTATION_NOSENSOR
* ActivityInfo.SCREEN_ORIENTATION_* constants package
* android.content.pm.ActivityInfo
*
* SCREEN_ORIENTATION_UNSPECIFIED SCREEN_ORIENTATION_LANDSCAPE
* SCREEN_ORIENTATION_PORTRAIT SCREEN_ORIENTATION_USER
* SCREEN_ORIENTATION_BEHIND SCREEN_ORIENTATION_SENSOR (default)
* SCREEN_ORIENTATION_NOSENSOR
*/
protected int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
protected OGLESContext ctx;
protected GLSurfaceView view = null;
protected boolean isGLThreadPaused = true;
private ImageView splashImageView = null;
private ImageView splashImageView = null;
private FrameLayout frameLayout = null;
final private String ESCAPE_EVENT = "TouchEscape";
@ -193,7 +204,6 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
logger.log(Level.INFO, "Settings: Width {0} Height {1}", new Object[]{s.getWidth(), s.getHeight()});
layoutDisplay();
} catch (Exception ex) {
handleError("Class " + appClass + " init failed", ex);
setContentView(new TextView(this));
@ -246,8 +256,8 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
if (app != null) {
app.stop(!isGLThreadPaused);
}
super.onDestroy();
logger.info("onDestroy");
super.onDestroy();
}
public Application getJmeApplication() {
@ -255,43 +265,44 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
}
/**
* Called when an error has occured. This is typically
* invoked when an uncaught exception is thrown in the render thread.
* @param errorMsg The error message, if any, or null.
* @param t Throwable object, or null.
* Called when an error has occurred.
* By default, will show an error message to the user
* and print the exception/error to the log.
*/
public void handleError(final String errorMsg, final Throwable t) {
String sTrace = "";
if (t != null && t.getStackTrace() != null) {
for (StackTraceElement ste : t.getStackTrace()) {
sTrace += "\tat " + ste.getClassName() + "." + ste.getMethodName() + "(";
if (ste.isNativeMethod()){
sTrace += "Native";
}else{
sTrace += ste.getLineNumber();
}
sTrace += ")\n";
}
String stackTrace = "";
String title = "Error";
if (t != null){
// Convert exception to string
StringWriter sw = new StringWriter(100);
t.printStackTrace(new PrintWriter(sw));
stackTrace = sw.toString();
title = t.toString();
}
final String finalTitle = title;
final String finalMsg = (errorMsg != null ? errorMsg : "Uncaught Exception")
+ "\n" + stackTrace;
final String stackTrace = sTrace;
logger.log(Level.SEVERE, t != null ? t.toString() : "OpenGL Exception");
logger.log(Level.SEVERE, "{0}{1}", new Object[]{errorMsg != null ? errorMsg + ": " : "", stackTrace});
logger.log(Level.SEVERE, finalMsg);
this.runOnUiThread(new Runnable() {
runOnUiThread(new Runnable() {
@Override
public void run() {
AlertDialog dialog = new AlertDialog.Builder(AndroidHarness.this) // .setIcon(R.drawable.alert_dialog_icon)
.setTitle(t != null ? (t.getMessage() != null ? (t.getMessage() + ": " + t.getClass().getName()) : t.getClass().getName()) : "OpenGL Exception").setPositiveButton("Kill", AndroidHarness.this).setMessage((errorMsg != null ? errorMsg + ": " : "") + stackTrace).create();
.setTitle(finalTitle)
.setPositiveButton("Kill", AndroidHarness.this)
.setMessage(finalMsg).create();
dialog.show();
}
});
}
/**
* Called by the android alert dialog, terminate the activity and OpenGL rendering
* Called by the android alert dialog, terminate the activity and OpenGL
* rendering
*
* @param dialog
* @param whichButton
*/
@ -312,53 +323,51 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
if (name.equals(ESCAPE_EVENT)) {
switch (evt.getType()) {
case KEY_UP:
this.runOnUiThread(new Runnable() {
runOnUiThread(new Runnable() {
@Override
public void run() {
AlertDialog dialog = new AlertDialog.Builder(AndroidHarness.this) // .setIcon(R.drawable.alert_dialog_icon)
.setTitle(exitDialogTitle).setPositiveButton("Yes", AndroidHarness.this).setNegativeButton("No", AndroidHarness.this).setMessage(exitDialogMessage).create();
.setTitle(exitDialogTitle)
.setPositiveButton("Yes", AndroidHarness.this)
.setNegativeButton("No", AndroidHarness.this)
.setMessage(exitDialogMessage).create();
dialog.show();
}
});
break;
default:
break;
}
}
}
public void layoutDisplay() {
logger.log(Level.INFO, "Splash Screen Picture Resource ID: {0}", splashPicID);
if (splashPicID != 0) {
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT,
Gravity.CENTER
);
frameLayout = new FrameLayout(this);
splashImageView = new ImageView(this);
Drawable drawable = this.getResources().getDrawable(splashPicID);
if (drawable instanceof NinePatchDrawable) {
splashImageView.setBackgroundDrawable(drawable);
} else {
splashImageView.setImageResource(splashPicID);
}
logger.log(Level.INFO, "Splash Screen Picture Resource ID: {0}", splashPicID);
if (splashPicID != 0) {
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT,
Gravity.CENTER);
frameLayout.addView(view);
frameLayout.addView(splashImageView, lp);
frameLayout = new FrameLayout(this);
splashImageView = new ImageView(this);
setContentView(frameLayout);
logger.log(Level.INFO, "Splash Screen Created");
Drawable drawable = this.getResources().getDrawable(splashPicID);
if (drawable instanceof NinePatchDrawable) {
splashImageView.setBackgroundDrawable(drawable);
} else {
logger.log(Level.INFO, "Splash Screen Skipped.");
setContentView(view);
splashImageView.setImageResource(splashPicID);
}
frameLayout.addView(view);
frameLayout.addView(splashImageView, lp);
setContentView(frameLayout);
logger.log(Level.INFO, "Splash Screen Created");
} else {
logger.log(Level.INFO, "Splash Screen Skipped.");
setContentView(view);
}
}
public void removeSplashScreen() {
@ -367,6 +376,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
if (frameLayout != null) {
if (splashImageView != null) {
this.runOnUiThread(new Runnable() {
@Override
public void run() {
splashImageView.setVisibility(View.INVISIBLE);

@ -739,8 +739,14 @@ public class OGLESShaderRenderer implements Renderer {
}
public void onFrame() {
if (!checkErrors){
int error = GLES20.glGetError();
if (error != GLES20.GL_NO_ERROR){
throw new RendererException("OpenGL Error " + error + ". Enable error checking for more info.");
}
}
objManager.deleteUnused(this);
// statistics.clearFrame();
// statistics.clearFrame();
}
public void setWorldMatrix(Matrix4f worldMatrix) {

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.system.android;
import android.app.Activity;
@ -60,268 +59,239 @@ import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
{
public class OGLESContext implements JmeContext, GLSurfaceView.Renderer {
private static final Logger logger = Logger.getLogger(OGLESContext.class.getName());
protected final AtomicBoolean created = new AtomicBoolean(false);
protected final AtomicBoolean renderable = new AtomicBoolean(false);
protected final AtomicBoolean needClose = new AtomicBoolean(false);
protected final AppSettings settings = new AppSettings(true);
/* >= OpenGL ES 2.0 (Android 2.2+) */
protected OGLESShaderRenderer renderer;
/*
* >= OpenGL ES 2.0 (Android 2.2+)
*/
protected OGLESShaderRenderer renderer;
protected Timer timer;
protected SystemListener listener;
protected boolean wasActive = false;
protected boolean autoFlush = true;
protected AndroidInput view;
private boolean firstDrawFrame = true;
private long milliStart;
private long milliDelta;
protected int frameRate = 33;
//protected int minFrameDuration = 1000 / frameRate; // Set a max FPS of 33
protected int minFrameDuration = 0; // No FPS cap
/**
* EGL_RENDERABLE_TYPE: EGL_OPENGL_ES_BIT = OpenGL ES 1.0 | EGL_OPENGL_ES2_BIT = OpenGL ES 2.0
* EGL_RENDERABLE_TYPE: EGL_OPENGL_ES_BIT = OpenGL ES 1.0 |
* EGL_OPENGL_ES2_BIT = OpenGL ES 2.0
*/
protected int clientOpenGLESVersion = 1;
protected boolean verboseLogging = false;
final private String ESCAPE_EVENT = "TouchEscape";
public OGLESContext() { }
public OGLESContext() {
}
@Override
public Type getType()
{
public Type getType() {
return Type.Display;
}
/**
* <code>createView</code>
* @param activity The Android activity which is parent for the GLSurfaceView
* <code>createView</code>
*
* @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));
public GLSurfaceView createView(Activity activity) {
return createView(new AndroidInput(activity));
}
/**
* <code>createView</code>
* @param view The Android input which will be used as the GLSurfaceView for this context
* <code>createView</code>
*
* @param view The Android input which will be used as the GLSurfaceView for
* this context
* @return GLSurfaceView The newly created view
*/
public GLSurfaceView createView(AndroidInput view)
{
public GLSurfaceView createView(AndroidInput view) {
return createView(view, ConfigType.FASTEST, false);
}
/**
* <code>createView</code> initializes the GLSurfaceView
* @param view The Android input which will be used as the GLSurfaceView for this context
* @param configType ConfigType.FASTEST (Default) | ConfigType.LEGACY | ConfigType.BEST
*
* @param view The Android input which will be used as the GLSurfaceView for
* this context
* @param configType ConfigType.FASTEST (Default) | ConfigType.LEGACY |
* ConfigType.BEST
* @param eglConfigVerboseLogging if true show all found configs
* @return GLSurfaceView The newly created view
*/
public GLSurfaceView createView(AndroidInput view, ConfigType configType, boolean eglConfigVerboseLogging)
{
*/
public GLSurfaceView createView(AndroidInput view, ConfigType configType, boolean eglConfigVerboseLogging) {
// Start to set up the view
this.view = view;
this.view = view;
verboseLogging = eglConfigVerboseLogging;
if (configType == ConfigType.LEGACY)
{
if (configType == ConfigType.LEGACY) {
// Hardcoded egl setup
clientOpenGLESVersion = 2;
clientOpenGLESVersion = 2;
view.setEGLContextClientVersion(2);
//RGB565, Depth16
view.setEGLConfigChooser(5, 6, 5, 0, 16, 0);
logger.info("ConfigType.LEGACY using RGB565");
}
else
{
} else {
EGL10 egl = (EGL10) EGLContext.getEGL();
EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
int[] version = new int[2];
if (egl.eglInitialize(display, version) == true)
{
if (egl.eglInitialize(display, version) == true) {
logger.info("Display EGL Version: " + version[0] + "." + version[1]);
}
// Create a config chooser
AndroidConfigChooser configChooser = new AndroidConfigChooser(configType, eglConfigVerboseLogging);
// Init chooser
if (!configChooser.findConfig(egl, display))
{
logger.severe("Unable to find suitable EGL config");
try {
// Create a config chooser
AndroidConfigChooser configChooser = new AndroidConfigChooser(configType, eglConfigVerboseLogging);
// Init chooser
if (!configChooser.findConfig(egl, display)) {
listener.handleError("Unable to find suitable EGL config", null);
return null;
}
clientOpenGLESVersion = configChooser.getClientOpenGLESVersion();
if (clientOpenGLESVersion < 2) {
listener.handleError("OpenGL ES 2.0 is not supported on this device", null);
return null;
}
// Requesting client version from GLSurfaceView which is extended by
// AndroidInput.
view.setEGLContextClientVersion(clientOpenGLESVersion);
view.setEGLConfigChooser(configChooser);
view.getHolder().setFormat(configChooser.getPixelFormat());
} finally {
if (display != null) {
egl.eglTerminate(display);
}
}
clientOpenGLESVersion = configChooser.getClientOpenGLESVersion();
if (clientOpenGLESVersion < 2)
{
logger.severe("OpenGL ES 2.0 is not supported on this device");
}
if (display != null)
egl.eglTerminate(display);
/*
* Requesting client version from GLSurfaceView which is extended by
* AndroidInput.
*/
view.setEGLContextClientVersion(clientOpenGLESVersion);
view.setEGLConfigChooser(configChooser);
view.getHolder().setFormat(configChooser.getPixelFormat());
}
view.setFocusableInTouchMode(true);
view.setFocusable(true);
view.getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU);
view.getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU);
view.setRenderer(this);
return view;
}
// renderer:initialize
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig cfg)
{
if (created.get() && renderer != null)
{
public void onSurfaceCreated(GL10 gl, EGLConfig cfg) {
if (created.get() && renderer != null) {
renderer.resetGLObjects();
}
else
{
if (!created.get())
{
logger.info("GL Surface created, doing JME3 init");
} else {
if (!created.get()) {
logger.info("GL Surface created, doing JME3 init");
initInThread();
}
else
{
} else {
logger.warning("GL Surface already created");
}
}
}
protected void initInThread()
{
created.set(true);
protected void initInThread() {
created.set(true);
logger.info("OGLESContext create");
logger.info("Running on thread: "+Thread.currentThread().getName());
logger.info("Running on thread: " + Thread.currentThread().getName());
final Context ctx = this.view.getContext();
// Setup unhandled Exception Handler
if (ctx instanceof AndroidHarness)
{
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
if (ctx instanceof AndroidHarness) {
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable thrown) {
((AndroidHarness)ctx).handleError("Exception thrown in " + thread.toString(), thrown);
((AndroidHarness) ctx).handleError("Exception thrown in " + thread.toString(), thrown);
}
});
}
else
{
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
} else {
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable thrown) {
listener.handleError("Exception thrown in " + thread.toString(), thrown);
}
});
}
if (clientOpenGLESVersion < 2)
{
if (clientOpenGLESVersion < 2) {
throw new UnsupportedOperationException("OpenGL ES 2.0 is not supported on this device");
}
timer = new AndroidTimer();
timer = new AndroidTimer();
renderer = new OGLESShaderRenderer();
renderer.setUseVA(true);
renderer.setVerboseLogging(verboseLogging);
renderer.initialize();
listener.initialize();
// Setup exit hook
if (ctx instanceof AndroidHarness)
{
Application app = ((AndroidHarness)ctx).getJmeApplication();
if (app.getInputManager() != null)
{
if (ctx instanceof AndroidHarness) {
Application app = ((AndroidHarness) ctx).getJmeApplication();
if (app.getInputManager() != null) {
app.getInputManager().addMapping(ESCAPE_EVENT, new TouchTrigger(TouchInput.KEYCODE_BACK));
app.getInputManager().addListener((AndroidHarness)ctx, new String[]{ESCAPE_EVENT});
app.getInputManager().addListener((AndroidHarness) ctx, new String[]{ESCAPE_EVENT});
}
}
needClose.set(false);
needClose.set(false);
renderable.set(true);
}
/**
* De-initialize in the OpenGL thread.
*/
protected void deinitInThread()
{
if (renderable.get())
{
protected void deinitInThread() {
if (renderable.get()) {
created.set(false);
if (renderer != null)
if (renderer != null) {
renderer.cleanup();
}
listener.destroy();
listener = null;
renderer = null;
timer = null;
renderer = null;
timer = null;
// do android specific cleaning here
logger.info("Display destroyed.");
renderable.set(false);
}
}
protected void applySettingsToRenderer(OGLESShaderRenderer renderer, AppSettings settings)
{
protected void applySettingsToRenderer(OGLESShaderRenderer renderer, AppSettings settings) {
logger.warning("setSettings.USE_VA: [" + settings.getBoolean("USE_VA") + "]");
logger.warning("setSettings.VERBOSE_LOGGING: [" + settings.getBoolean("VERBOSE_LOGGING") + "]");
renderer.setUseVA(settings.getBoolean("USE_VA"));
renderer.setVerboseLogging(settings.getBoolean("VERBOSE_LOGGING"));
}
protected void applySettings(AppSettings settings)
{
protected void applySettings(AppSettings settings) {
setSettings(settings);
if (renderer != null)
applySettingsToRenderer(renderer, this.settings);
if (renderer != null) {
applySettingsToRenderer(renderer, this.settings);
}
}
@Override
public void setSettings(AppSettings settings)
{
public void setSettings(AppSettings settings) {
this.settings.copyFrom(settings);
}
@Override
public void setSystemListener(SystemListener listener){
public void setSystemListener(SystemListener listener) {
this.listener = listener;
}
@ -344,7 +314,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
public KeyInput getKeyInput() {
return new DummyKeyInput();
}
@Override
public JoyInput getJoyInput() {
return null;
@ -354,35 +324,29 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
public TouchInput getTouchInput() {
return view;
}
@Override
public Timer getTimer()
{
public Timer getTimer() {
return timer;
}
@Override
public void setTitle(String title)
{
public void setTitle(String title) {
}
@Override
public boolean isCreated()
{
public boolean isCreated() {
return created.get();
}
@Override
public void setAutoFlushFrames(boolean enabled)
{
public void setAutoFlushFrames(boolean enabled) {
this.autoFlush = enabled;
}
// SystemListener:reshape
@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
public void onSurfaceChanged(GL10 gl, int width, int height) {
logger.info("GL Surface changed, width: " + width + " height: " + height);
settings.setResolution(width, height);
listener.reshape(width, height);
@ -390,101 +354,84 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
// SystemListener:update
@Override
public void onDrawFrame(GL10 gl)
{
if (needClose.get())
{
public void onDrawFrame(GL10 gl) {
if (needClose.get()) {
deinitInThread();
return;
}
if (renderable.get())
{
if (!created.get())
if (renderable.get()) {
if (!created.get()) {
throw new IllegalStateException("onDrawFrame without create");
}
milliStart = System.currentTimeMillis();
long milliStart = System.currentTimeMillis();
listener.update();
// call to AndroidHarness to remove the splash screen, if present.
// call after listener.update() to make sure no gap between
// splash screen going away and app display being shown.
if (firstDrawFrame) {
// call to AndroidHarness to remove the splash screen, if present.
// call after listener.update() to make sure no gap between
// splash screen going away and app display being shown.
if (firstDrawFrame) {
final Context ctx = this.view.getContext();
if (ctx instanceof AndroidHarness) {
((AndroidHarness)ctx).removeSplashScreen();
((AndroidHarness) ctx).removeSplashScreen();
}
firstDrawFrame = false;
}
if (autoFlush)
{
firstDrawFrame = false;
}
if (autoFlush) {
renderer.onFrame();
}
milliDelta = System.currentTimeMillis() - milliStart;
long milliDelta = System.currentTimeMillis() - milliStart;
// Enforce a FPS cap
if (milliDelta < minFrameDuration)
{
if (milliDelta < minFrameDuration) {
//logger.log(Level.INFO, "Time per frame {0}", milliDelta);
try {
Thread.sleep(minFrameDuration - milliDelta);
} catch (InterruptedException e) {
}
}
}
}
@Override
public boolean isRenderable()
{
public boolean isRenderable() {
return renderable.get();
}
@Override
public void create(boolean waitFor)
{
if (waitFor)
public void create(boolean waitFor) {
if (waitFor) {
waitFor(true);
}
}
public void create()
{
public void create() {
create(false);
}
@Override
public void restart()
{
public void restart() {
}
@Override
public void destroy(boolean waitFor)
{
public void destroy(boolean waitFor) {
needClose.set(true);
if (waitFor)
if (waitFor) {
waitFor(false);
}
}
public void destroy()
{
public void destroy() {
destroy(true);
}
protected void waitFor(boolean createdVal)
{
while (renderable.get() != createdVal){
protected void waitFor(boolean createdVal) {
while (renderable.get() != createdVal) {
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
@ -492,9 +439,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
}
}
public int getClientOpenGLESVersion()
{
public int getClientOpenGLESVersion() {
return clientOpenGLESVersion;
}
}

Loading…
Cancel
Save