Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android : Fixing rendering for all FPS (> 60 or < 60) - Thread to trigger rendering manually #2125

Draft
wants to merge 12 commits into
base: dev
Choose a base branch
from
17 changes: 5 additions & 12 deletions core/platform/android/java/src/org/axmol/lib/AxmolActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -229,16 +229,8 @@ private void resume() {
mGLSurfaceView.onResume();
rendererPaused = false;
}
mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
}

private void resumeIfHasFocus() {
//It is possible for the app to receive the onWindowsFocusChanged(true) event
//even though it is locked or asleep
boolean readyToPlay = !isDeviceLocked() && !isDeviceAsleep();

if(hasFocus && readyToPlay) {
resume();
else {
mGLSurfaceView.onGainFocus();
}
}

Expand All @@ -247,8 +239,8 @@ protected void onPause() {
Log.d(TAG, "onPause()");
paused = true;
super.onPause();
mGLSurfaceView.onLooseFocus();
AxmolEngine.onPause();
mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}

@Override
Expand Down Expand Up @@ -324,7 +316,8 @@ public void init() {
//if (isAndroidEmulator())
// this.mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

this.mGLSurfaceView.setRenderer(new AxmolRenderer());
this.mGLSurfaceView.setRenderer(new AxmolRenderer(this.mGLSurfaceView));
this.mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
this.mGLSurfaceView.setEditText(edittext);

// Set framelayout as the content view
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,21 @@ public void run() {
// Methods
// ===========================================================

public void onLooseFocus() {
AlexandreK38 marked this conversation as resolved.
Show resolved Hide resolved
this.queueEvent(new Runnable() {
@Override
public void run() {
AxmolGLSurfaceView.this.mRenderer.handleOnLooseFocus();
}
});
}
public void onGainFocus() {
this.queueEvent(new Runnable() {
@Override
public void run() { AxmolGLSurfaceView.this.mRenderer.handleOnGainFocus(); }
});
}

// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
Expand Down
114 changes: 91 additions & 23 deletions core/platform/android/java/src/org/axmol/lib/AxmolRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,56 @@ of this software and associated documentation files (the "Software"), to deal
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class AxmolRenderer implements GLSurfaceView.Renderer {

private static class RendererThread extends Thread {

private GLSurfaceView gameSurfaceView;
private AxmolRenderer renderer;
private boolean pausing = false;
private Object monitor = new Object();

public RendererThread(GLSurfaceView gameSurfaceView, AxmolRenderer renderer) {
this.gameSurfaceView = gameSurfaceView;
this.renderer = renderer;
}

public void onPause(){
pausing = true;
}

public void onResume(){
pausing = false;
synchronized (monitor) {
monitor.notify();
}
}

@Override
public void run() {
while (true) {
synchronized (monitor) {
if(pausing) {
try {
monitor.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

if (renderer.isReadyForRendering()) {
renderer.prepareForRendering();
this.gameSurfaceView.requestRender();
}
}
}
}

// ===========================================================
// Constants
// ===========================================================

private final static long NANOSECONDSPERSECOND = 1000000000L;
private final static long NANOSECONDSPERMICROSECOND = 1000000L;

// The final animation interval which is used in 'onDrawFrame'
private static long sAnimationInterval = (long) (1.0f / 60f * AxmolRenderer.NANOSECONDSPERSECOND);
Expand All @@ -48,11 +92,19 @@ public class AxmolRenderer implements GLSurfaceView.Renderer {
private int mScreenHeight;
private boolean mNativeInitCompleted = false;
private boolean mIsPaused = false;
private boolean mIsReady = true;
private boolean mRendererThreadIsPaused = false;
private RendererThread mRendererThread = null;

// ===========================================================
// Constructors
// ===========================================================

public AxmolRenderer(GLSurfaceView surfaceView) {
super();
this.mRendererThread = new RendererThread(surfaceView, this);
}

// ===========================================================
// Getter & Setter
// ===========================================================
Expand All @@ -66,6 +118,15 @@ public void setScreenWidthAndHeight(final int surfaceWidth, final int surfaceHei
this.mScreenHeight = surfaceHeight;
}

public boolean isReadyForRendering(){
return mIsReady && System.nanoTime() - mLastTickInNanoSeconds >= AxmolRenderer.sAnimationInterval;
}

public void prepareForRendering(){
mIsReady = false;
}


// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
Expand All @@ -75,6 +136,8 @@ public void onSurfaceCreated(final GL10 GL10, final EGLConfig EGLConfig) {
AxmolRenderer.nativeInit(this.mScreenWidth, this.mScreenHeight);
this.mLastTickInNanoSeconds = System.nanoTime();

mRendererThread.start();

if (mNativeInitCompleted) {
// This must be from an OpenGL context loss
nativeOnContextLost();
Expand All @@ -90,28 +153,9 @@ public void onSurfaceChanged(final GL10 GL10, final int width, final int height)

@Override
public void onDrawFrame(final GL10 gl) {
/*
* Fix 60fps limiting doesn't work when high-end device is working in 120fps mode.
*/
if (AxmolRenderer.sAnimationInterval <= 1.0f / 1200.0f * AxmolRenderer.NANOSECONDSPERSECOND) {
AxmolRenderer.nativeRender();
} else {
final long now = System.nanoTime();
final long interval = now - this.mLastTickInNanoSeconds;

/*
* Render time MUST be counted in, or the FPS will slower than appointed.
*/
this.mLastTickInNanoSeconds = now;
AxmolRenderer.nativeRender();

if (interval < AxmolRenderer.sAnimationInterval) {
try {
Thread.sleep((AxmolRenderer.sAnimationInterval - interval) / AxmolRenderer.NANOSECONDSPERMICROSECOND);
} catch (final Exception e) {
}
}
}
mLastTickInNanoSeconds = System.nanoTime();
AxmolRenderer.nativeRender();
mIsReady = true;
}

// ===========================================================
Expand Down Expand Up @@ -164,17 +208,41 @@ public void handleOnPause() {
if (!mNativeInitCompleted)
return;

pauseRendererThread();
AxmolRenderer.nativeOnPause();
mIsPaused = true;
}

public void handleOnResume() {
resumeRendererThread();
if (mIsPaused) {
AxmolRenderer.nativeOnResume();
mIsPaused = false;
}
}

public void handleOnLooseFocus() {
pauseRendererThread();
}

public void handleOnGainFocus() {
resumeRendererThread();
}

private void pauseRendererThread() {
if(!mRendererThreadIsPaused) {
mRendererThread.onPause();
mRendererThreadIsPaused = true;
}
}

private void resumeRendererThread() {
if(mRendererThreadIsPaused) {
mRendererThread.onResume();
mRendererThreadIsPaused = false;
}
}

private static native void nativeInsertText(final String text);
private static native void nativeDeleteBackward();
private static native String nativeGetContentText();
Expand Down