Very low fps on Android

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
pverlaine999
Posts: 16
Joined: Wed May 04, 2011 12:30 pm

Very low fps on Android

Post by pverlaine999 »

Hi,

I'm new to Irrlicht, so please bear with me :)

I just get the latest source code of Irrlicht for Android, build it without problem on Ubuntu 11.04, using NDK r5.

Then I tried to port that first tutorial to Android, I got everything up and running on my Samsung T959 (Vibrant), but I got extremely low fps. The highest I got is about 5 fps, but it just runs at 1 fps.

I downloaded the quake3 example provided here, it runs at 56 or 57 fps, and looks smooth.

I'm trying to understand what went wrong with my code. Here is is (the C codes are just copied and pasted, basically):

Code: Select all

#include <jni.h>
#include <android/log.h>
#include <irrlicht.h>
#include <importgl.h>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

int importGLInit();
void importGLDeinit();

// global variables
int  gWindowWidth  = 320;
int  gWindowHeight = 480;
stringc gSdCardPath = "/sdcard/";


IrrlichtDevice *device = NULL;
IVideoDriver* driver = NULL;

ISceneManager* smgr = NULL;
IGUIEnvironment* guienv = NULL;

/* For JNI: C++ compiler need this */
extern "C" {

	/** Activity onCreate */
	void Java_com_test_TestIrrActivity_nativeOnCreate( JNIEnv*  env )
	{
		__android_log_print(ANDROID_LOG_INFO, "TestIrr", "nativeOnCreate() called");
	}

	/** Activity onPause */
	void Java_com_test_TestIrrActivity_nativeOnPause( JNIEnv*  env )
	{
		__android_log_print(ANDROID_LOG_INFO, "TestIrr", "nativeOnPause() called");
	}

	/** Activity onResume */
	void Java_com_test_TestIrrActivity_nativeOnResume( JNIEnv*  env )
	{
		__android_log_print(ANDROID_LOG_INFO, "TestIrr", "nativeOnResume() called");
	}

	/** Activity onDestroy */
	void Java_com_test_TestIrrActivity_nativeOnDestroy( JNIEnv*  env )
	{
		__android_log_print(ANDROID_LOG_INFO, "TestIrr", "nativeOnDestroy() called");
		importGLDeinit();
	}

	void init()
	{
	    smgr = device->getSceneManager();
	    guienv = device->getGUIEnvironment();

	    __android_log_print(ANDROID_LOG_INFO, "TestIrr", "Adding static text to guienv");

	    guienv->addStaticText(L"Hello World! This is the Irrlicht Software renderer!",
	                    rect<s32>(10,10,260,22), true);

	    __android_log_print(ANDROID_LOG_INFO, "TestIrr", "Getting animated mesh");

        IAnimatedMesh* mesh = smgr->getMesh("/sdcard/Irrlicht/sydney.md2");
        if (!mesh)
        {
                device->drop();
                return;
        }
        __android_log_print(ANDROID_LOG_INFO, "TestIrr", "Mesh type = %d", mesh->getMeshType());

        IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh );

        if (node)
        {
        	__android_log_print(ANDROID_LOG_INFO, "TestIrr", "Disable lighting and apply texture");

        	node->setMaterialFlag(EMF_LIGHTING, false);
        	node->setMD2Animation(scene::EMAT_STAND);
        	node->setMaterialTexture( 0, driver->getTexture("/sdcard/Irrlicht/sydney.bmp") );
        }

        __android_log_print(ANDROID_LOG_INFO, "TestIrr", "Adding a camera");
        smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0));
        __android_log_print(ANDROID_LOG_INFO, "TestIrr", "init() done");
	}

	void Java_com_test_TestIrrActivity_nativeInitGL( JNIEnv*  env )
	{
	    importGLInit();
	    device = createDevice( video::EDT_OGLES1, dimension2d<u32>(gWindowWidth, gWindowHeight), 16, false, false, false, 0);
	    driver = device->getVideoDriver();

		__android_log_print(ANDROID_LOG_INFO, "TestIrr", "createDevice r=%d w=%d h=%d", device, gWindowWidth, gWindowHeight);
		__android_log_print(ANDROID_LOG_INFO, "TestIrr", "getVideoDriver r=%d", driver);

	    if (!device)
	        __android_log_print(ANDROID_LOG_INFO, "TestIrr", "No device");
	    if (!driver)
	        __android_log_print(ANDROID_LOG_INFO, "TestIrr", "No driver");

	    __android_log_print(ANDROID_LOG_INFO, "TestIrr", "nativeInitGL() done");
	}

	void Java_com_test_TestIrrActivity_nativeResize( JNIEnv*  env, jobject  thiz, jint w, jint h )
	{
	    __android_log_print(ANDROID_LOG_INFO, "TestIrr", "resize w=%d h=%d", w, h);
	    gWindowWidth  = w;
	    gWindowHeight = h;
	    irr::core::dimension2d<unsigned int> size;
	    size.Width = w;
	    size.Height = h;
	    device->getVideoDriver()->OnResize(size);
	}

	static int counter = 0;

	void Java_com_test_TestIrrActivity_nativeDrawIteration( JNIEnv*  env )
	{
		__android_log_print(ANDROID_LOG_INFO, "TestIrr", "nativeDrawIteration() called");

		device->run();
		if (counter == 0)
			init();

		driver->beginScene(true, true, SColor(255,100,101,140));
		smgr->drawAll();
		guienv->drawAll();
		driver->endScene();

		int fps = driver->getFPS();
	    __android_log_print(ANDROID_LOG_INFO, "TestIrr", "TestIrr fps=%d", fps);

	}

}
And Java codes here:

Code: Select all

package com.test;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

public class TestIrrActivity extends Activity {
	private GLSurfaceView mGLView;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mGLView = new TestSurfaceView(this);
        setContentView(mGLView);
        nativeOnCreate();
    }
    
    @Override
    protected void onPause() 
    {
    	super.onPause();
    	mGLView.onPause();
    	nativeOnPause();
    }
    
    @Override
    protected void onResume() 
    {
    	super.onResume();
    	mGLView.onResume();
    	nativeOnResume();
    }
    
    @Override    
    public void onDestroy() 
    {
        nativeOnDestroy();
        super.onDestroy();
    }
    
    static 
    {
    	System.loadLibrary("irrlicht");
        System.loadLibrary("test_irr");
    }
    
    public native void nativeOnCreate();
    public native void nativeOnPause();
    public native void nativeOnResume();
    public native void nativeOnDestroy();

    public native void nativeInitGL();
    public native void nativeResize(int w, int h);
    
    public static native void nativeDrawIteration();
}

Code: Select all

package com.test;

import android.opengl.GLSurfaceView;
import android.view.MotionEvent;

public class TestSurfaceView extends GLSurfaceView
{
	TestIrrActivity activity;
    TestIrrRenderer renderer;

	public TestSurfaceView(TestIrrActivity context)
	{
		super(context);
		this.activity = context;
		renderer = new TestIrrRenderer(activity);
		setRenderer(renderer);
	}

    public boolean onTouchEvent(final MotionEvent event) 
    {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            activity.nativeOnPause();
        }
        return true;
    }
    
}

Code: Select all

package com.test;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView.Renderer;

public class TestIrrRenderer implements Renderer
{
    private int mWindowWidth;
    private int mWindowHeight;

    TestIrrActivity activity;

    public TestIrrRenderer(TestIrrActivity activity)
    {
    	this.activity = activity;
    }
    
	public void onDrawFrame(GL10 gl)
	{
		activity.nativeDrawIteration();
	}

	public void onSurfaceChanged(GL10 gl, int width, int height)
	{
        mWindowWidth = width;
        mWindowHeight = height;
        activity.nativeResize(width, height);
	}

	public void onSurfaceCreated(GL10 gl, EGLConfig config)
	{
		activity.nativeInitGL();
	}
}

The codes are simple enough, and the important parts (the C codes) are copied from the tutorial. So I don't understand why it is so slow.

My Samsung T959 is running Android 2.1.

Thanks for any advice.

Paul
pverlaine999
Posts: 16
Joined: Wed May 04, 2011 12:30 pm

Post by pverlaine999 »

And the size of the application is humongous! Even though I compiled Irrlicht Android and my test program with

Code: Select all

NDK_DEBUG = 0
, after the installation, Android shows that the size of my application is 30.58MB!!!

And the thing is, Android also shows the following flags on the program:

Code: Select all

FLAG_DEBUGGABLE
FLAG_HAS_CODE
FLAG_ALLOW_CLEAR_USER_DAT
FLAG_SUPPORTS_NORMAL_SCREENS
FLAG_VM_SAFE_MODE
My AndroidManifest.xml does not have the

Code: Select all

android:debuggable
flag, and I specifically built the C codes with

Code: Select all

NDK_DEBUG = 0
.

So what is going on?

Thanks for any advice.

Paul
renzhi
Posts: 3
Joined: Fri May 06, 2011 2:43 am

Post by renzhi »

Looking at your code in the following:

Code: Select all

   static int counter = 0;

   void Java_com_test_TestIrrActivity_nativeDrawIteration( JNIEnv*  env )
   {
      __android_log_print(ANDROID_LOG_INFO, "TestIrr", "nativeDrawIteration() called");

      device->run();
      if (counter == 0)
         init();

      driver->beginScene(true, true, SColor(255,100,101,140));
      smgr->drawAll();
      guienv->drawAll();
      driver->endScene();

      int fps = driver->getFPS();
       __android_log_print(ANDROID_LOG_INFO, "TestIrr", "TestIrr fps=%d", fps);

   } 
You re-initialized every time a frame is drawn. The variable counter is never incremented.

You can simple call init() at the end of nativeInitGL(), and get away with this counter thing. It is better this way too, try to pause your game and resume again too see why.
pverlaine999
Posts: 16
Joined: Wed May 04, 2011 12:30 pm

Post by pverlaine999 »

Aaahhhh, stupid me!

Thanks a lot for spotting my stupidity.

:oops:
Post Reply