Control the frame rate?

777 views
Skip to first unread message

U A

unread,
Dec 10, 2011, 11:45:32 AM12/10/11
to GLWallpaperService
Any tips on controlling the frame rate?

Right now what I'm doing is using RENDERMODE_WHEN_DIRTY, creating a
Handler, and using its postDelayed()---just like the Cube sample
wallpaper from Google. However, as far as I can tell, a Handler
doesn't really apply since we're using a GL surface.

I've also noticed that RENDERMODE_CONTINOUSLY seems faster. However, I
need a way to max out the frame rate.

digitdroid

unread,
Dec 10, 2011, 12:19:35 PM12/10/11
to GLWallpaperService
Standard framerate for opengl ~60fps on most android devices.
I'm adjust my lwp's animations speed from average fps (10 last frames
used), i.e.
you see the same animation speed with 20, 30, 50 or 60 fps on
different devices.

Josh Gooderham

unread,
Dec 10, 2011, 12:30:07 PM12/10/11
to glwallpap...@googlegroups.com
I just use a Timer. I let the user change the framerate in settings and if it's non-zero I setup a Timer to call a requestRender(), otherwise I just use RENDERMODE_CONTINUOUSLY

This is what my typical Engine class looks like. All the rendering is handled by a controller class.

        @Override
        public void onCreate( SurfaceHolder surfaceHolder ) {

            super.onCreate( surfaceHolder );

            setGLWrapper( controller.onCreate() );
            setRenderer( controller.renderer() );

            setupDirtyTimer();
        }

        private void setupDirtyTimer() {

            killDirtyTimer();

            if ( controller.currentFrameRate() > 0 ) {

                setRenderMode( RENDERMODE_WHEN_DIRTY );

                dirtyTask = new TimerTask() {

                    @Override
                    public void run() {

                        // Log.d( TAG, "tick" );
                        requestRender();
                    }
                };
                dirtyTimer = new Timer();
                dirtyTimer.schedule( dirtyTask, 0, 1000 / controller.currentFrameRate() );

            } else {

                setRenderMode( RENDERMODE_CONTINUOUSLY );
            }
        }

        public void killDirtyTimer() {

            // kill the timer
            if ( dirtyTimer != null ) {
                dirtyTimer.cancel();
                dirtyTimer = null;
            }
        }

        @Override
        public void onPause() {

            killDirtyTimer();

            super.onPause();
        }

        @Override
        public void onResume() {

            super.onResume();

            setupDirtyTimer();
        }

I imagine there's a more elegant solution if you have a solid understanding of threading but I still can't wrap my head around that stuff and I'm pretty sure a Timer is like poor man's threading anyway.

This is or should be a fairly standard feature in most live wallpapers. It would be nice if we could get a clean, elegant and common solution hashed out.

Josh
https://market.android.com/developer?pub=gentlemandroid
http://www.gentlemandroid.com/

Josh Gooderham

unread,
Dec 10, 2011, 12:31:43 PM12/10/11
to glwallpap...@googlegroups.com
Oh and a few declarations, if that wasn't clear:

    class MyEngine extends GLEngine {

        private Timer dirtyTimer;
        private TimerTask dirtyTask;
...

Josh Gooderham

unread,
Dec 10, 2011, 12:36:55 PM12/10/11
to glwallpap...@googlegroups.com
And hey, because I tend to hit Send much too prematurely with this much coffee in my body...

Now that I look at it I think the name might be confusing. Just so it's clear, controller.currentFrameRate() returns the user's desired framerate, which was already loaded elsewhere from the paper's preferences. It isn't the current running framerate or anything.

U A

unread,
Dec 10, 2011, 2:04:44 PM12/10/11
to GLWallpaperService
Yeah that's exactly what I was thinking---an "elegant" way of handling
the frame rate.

Your method is similar to mine except that yours is probably slightly
more accurate --- a Handler has extra processing since it deals with
the UI, while a timer task doesn't. However, I suspect that because of
thread timing issues, the most accurate/fastest way is probably to
just let GLthread draw itself as fast as possible and slow it down as
necessary.

Will investigate---taking the average of previous frames sounds
promising and will report back later.

On Dec 10, 12:31 pm, Josh Gooderham <joshgooder...@gmail.com> wrote:
> Oh and a few declarations, if that wasn't clear:
>
>     class MyEngine extends GLEngine {
>
>         private Timer dirtyTimer;
>         private TimerTask dirtyTask;
> ...
>

> Joshhttps://market.android.com/developer?pub=gentlemandroidhttp://www.gentlemandroid.com/

U A

unread,
Dec 22, 2011, 10:26:58 AM12/22/11
to GLWallpaperService
I did eventually do some research and what I discovered is that your
way of using a timer is fine.

Here's what you can use:

1. use RENDER_DIRTY and a thread timer

2. let the wallpaper run as fast as possible (using
RENDER_CONTINUOUSLY) then slow it down using Thread.sleep(). See
here:

http://stackoverflow.com/questions/4772693/how-to-limit-framerate-when-using-androids-glsurfaceview-rendermode-continuousl

3. if your physics will get out of whack if it runs too slow, then
take a look here for tips:

http://obviam.net/index.php/the-android-game-loop/
http://gafferongames.com/game-physics/fix-your-timestep/

The first one has a real good explanation of FPS and UPS. The second
one is more math orientated.


On Dec 11, 3:04 am, U A <urisrssfe...@gmail.com> wrote:
> Yeah that's exactly what I was thinking---an "elegant" way of handling
> the frame rate.
>
> Your method is similar to mine except that yours is probably slightly
> more accurate --- a Handler has extra processing since it deals with
> the UI, while a timer task doesn't. However, I suspect that because of
> thread timing issues, the most accurate/fastest way is probably to
> just let GLthread draw itself as fast as possible and slow it down as
> necessary.
>
> Will investigate---taking the average of previous frames sounds
> promising and will report back later.
>
> On Dec 10, 12:31 pm, Josh Gooderham <joshgooder...@gmail.com> wrote:
>
> > Oh and a few declarations, if that wasn't clear:
>
> >     class MyEngine extends GLEngine {
>
> >         private Timer dirtyTimer;
> >         private TimerTask dirtyTask;
> > ...
>
> > Joshhttps://market.android.com/developer?pub=gentlemandroidhttp://www.gen...

Josh Gooderham

unread,
Dec 22, 2011, 2:13:12 PM12/22/11
to glwallpap...@googlegroups.com
Interesting.

So is everything a thread in android? Can you just do Thread.sleep() anywhere you want? For some reason I just thought threads were different and that unless you spawned one specifically, like with a Timer, you weren't using threading. Is this a Linux thing?

Those other links are pretty great too. Thanks
Reply all
Reply to author
Forward
0 new messages