5

I have some trubles with my framerate using a SurfaceView. Im doing the tipical stuff i found in some tutorials (all of them said the same), but i cant reach a decent framerate on my samsung galaxy S (the old one, i9000).

Here's the code i have for the loop thread. FPS is initialized at 30.

@Override
public void run() {
    long ticksPS = 1000/FPS;
    long startTime;
    long sleepTime;
    //fps checker
    long contms=0;
    long lasttimecheck = System.currentTimeMillis();
    int fps=0;
    while (running) {
        long time =  System.currentTimeMillis();
        if(contms>1000) {
            Log.v("FPS",String.valueOf(fps));
            contms=time-lasttimecheck;
            fps=1;
        }
        else {
            fps++;
            contms+=time-lasttimecheck;
        }
        lasttimecheck = time;

        Canvas c = null;
        startTime =time;
        try {
            c = view.getHolder().lockCanvas();
            synchronized (view.getHolder()) {
                view.onDraw(c);
            }
        } finally {
            if (c != null) {
                view.getHolder().unlockCanvasAndPost(c);
            }
        }
        sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
        try {
            if (sleepTime > 10)
                   sleep(sleepTime);
            else {
                Log.w("LOWFPS",String.valueOf(contms));
                sleep(10);
            }
     } catch (Exception e) {}
    }
}

In the surfaceView, I initialize the holder with holder.setFormat(PixelFormat.RGBA_8888); but i dont know if i have to do something with the bitmaps to avoid useless CPU work (I save the bitmaps in local variables, then I draw them). The game is simple, it should run much faster.

The framerate is quite random, sometimes it works smoothie, sometimes it doesnt, but always under the 30FPS.

Any ideas???

EDIT WITH ONDRAW EXPLANATION

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(bg, 0, 0, null); //1
    stars.draw(canvas,dx,dy);      //2
    if(playing.on()) reactors.draw_reaccio(canvas,dx,dy); //3
    gotes.draw(canvas,dx,dy);     //4
    reactors.draw(canvas,dx,dy);  //5
    sg.draw(canvas);  //6         
    sr.draw(canvas);  //7
    eraser.draw(canvas);  //8
    playing.draw(canvas); //9
    opcions.draw(canvas); //10
}

1) Drawing the background (480x800) 2) this is a class that contains a list of "getHeight()" basic objects (stars) with its coordenates (x,y) and the ID with the associated image (about 9 different stars images) 3) it draws n*2 circles, one with fill and another with stroke per related object (about 20 or so) 4) It draws the main object of the game, little drops with an animation. There are 9 different kind of drops, and each of them have 5 related images of the animation (should i put the 5 images in 1 maybe?) 5) same as drops but without animation 6 to 10) irrelevant, it just draw an image

I guess the slowness is due to: (2) because of the number of stars (4) becouse of the animation, witch change every 2-3 frames to a different image and maybe it is too much for memory, i guess i should merge all the images in just 1.

The framerate is about 20-22 FPS with S. Galaxy S i9000

Carles
  • 451
  • 5
  • 16
  • I'm getting similar problems here on my brand new Galaxy Nexus. My app heavily uses SurfaceView and works fine on every other device. On ICS it's unusable, even with hardware acceleration forced in settings. – Kleptine Dec 30 '11 at 05:42
  • Could you post the drawing code itself? To determine time/CPU-intensive parts of your app, use TraceView: http://developer.android.com/guide/developing/debugging/debugging-tracing.html – molnarm Dec 30 '11 at 17:41
  • Please post the whole class, otherwise noone can judiciously analyze your code flow. – poitroae Jan 02 '12 at 14:59
  • Turns out I had a different problem actually. SurfaceViews with hardwareAcceleration enabled (on ICS by default) become slow if the bitmaps change often. – Kleptine Jan 05 '12 at 06:44

2 Answers2

3

If you disable the drawing, how much fps do you achieve ? Just to check how much the display pipeline is hogging.

I had tried following create 5 bitmaps of size 720 x 480 : pix format RGB565 display them on a SurfaceView from a loop similar to yours. The only difference is that I had "prepared bitmaps" and wasn't drawing them in a loop. This is what was achieved on a Nexus-S phone

FPS : 55 (I tried to run the loop as fast, without regulation)

Cpu load : 85%

This is when I decided to render my SurfaceView from JNI :) !!

Do a similar experiment and see how much your device is able to throttle "without" drawing operations. If it looks good, then you can profile whether you can fit-in your your drawing operations within the budget.

peasea
  • 346
  • 2
  • 4
  • I ended up having a different problem actually, but I'll award you the bounty as it's probably the best way to go about solving the orginial poster's issue. – Kleptine Jan 05 '12 at 22:26
0

Things to consider : How long does you draw routine take?

If you have problems with it running under 30 FPS, I would reconsider having it sleep. This is not an exact thing and could sleep less or more according to the API, so I would remove this for now and let it run as fast as it can.

I agree with above, please post drawing code or comment it out the the call to the draw routine and see what FPS you're running at.

In general, from a sampling stand point you may see it jitter in value if only measuring over 1 seconds.

Many drawing back ends only work in even divisors of 60. So if you were doing a lot of stuff it's possible one or two extra calls will bring you from 60/1 = 60 fps to 60/2 = 30 fps.

nmjohn
  • 1,432
  • 7
  • 16