2

I want to control the rendering rate of my GLSurfaceView.Renderer. I implemented a thread in the class that extends GLSurfaceView, and put it to sleep periodically in a while(true) loop, which did nothing to slow down the renderer. There's a good answer here that suggests putting the GL Thread to sleep by using a Thread.sleep within the Renderer.onDrawFrame() method. I'd like to handle it from outside the Renderer class. How can that be done when an explicit call requires passing in a GL10 object? Thanks.

Community
  • 1
  • 1
farm ostrich
  • 5,881
  • 14
  • 55
  • 81
  • As trivial as this sounds is it totally out of question to let onDrawFrame sleep once it gets called next time - meaning you could set a flag for it to happen? – harism May 04 '11 at 19:48

1 Answers1

4

Don't extend GLSurfaceView. If you're not already, keep the renderer as a variable in your activity class:

public class MyActivity extends Activity {

    protected GLSurfaceView mGLView;
    protected GraphicsRenderer graphicsRenderer; // keep reference to renderer

    protected void initGraphics() {

        graphicsRenderer = new GraphicsRenderer(this);

        mGLView = (GLSurfaceView) findViewById(R.id.graphics_glsurfaceview1);
        mGLView.setEGLConfigChooser(true);         
        mGLView.setRenderer(graphicsRenderer);

        graphicsRenderer.setFrameRate(30);


    }
}

Then you can create a method in your renderer to control the frame rate:

public class GraphicsRenderer  implements GLSurfaceView.Renderer {

    private long framesPerSecond;
    private long frameInterval; // the time it should take 1 frame to render
    private final long millisecondsInSecond = 1000;

    public void setFrameRate(long fps){

        framesPerSecond = fps;

        frameInterval= millisecondsInSeconds / framesPerSecond;

    }


    public void onDrawFrame(GL10 gl) {

        // get the time at the start of the frame
        long time = System.currentTimeMillis();

        // drawing code goes here

        // get the time taken to render the frame       
        long time2 = System.currentTimeMillis() - time;

        // if time elapsed is less than the frame interval
        if(time2 < frameInterval){          
            try {
                // sleep the thread for the remaining time until the interval has elapsed
                Thread.sleep(frameInterval - time2);
            } catch (InterruptedException e) {
                // Thread error
                e.printStackTrace();
            }
        } else {
            // framerate is slower than desired
        }
    }

}
James Coote
  • 1,975
  • 19
  • 29
  • 2
    Stalling onDrawFrame() may be problematic. Recent versions of Android synchronize onDrawFrame() with the "vsync" refresh on the device, so this can lead to choppy animation if the sleep() call is finishing right on the edge of the next frame. With onDrawFrame() being driven by an external clock, your ability to control the frame rate is essentially limited to rendering every N refreshes (e.g. draw every-other time onDrawFrame is called to cut the updates in half). sleep() may not be perfectly accurate. – fadden Feb 25 '13 at 21:22
  • Good point. I could swear there is a way to give a hint to the renderer for what frame rate you want, but I can't find any info on it now. For my own engine, I don't control frame rate, I just let it get on with it, but some people want to have more control – James Coote Feb 27 '13 at 14:54
  • 1
    If your game state is updated relatively infrequently, you can put the renderer into `RENDERMODE_WHEN_DIRTY` and just `requestRender()` whenever there's something new to draw. – fadden Feb 27 '13 at 21:38
  • this idea is good, to implement more, you need to 1. set RENDERMODE_WHEN_DIRTY 2. move start-end thread and thread.sleep to other thread 3. call requestRender() to manual reload it – Sruit A.Suk Jul 05 '20 at 09:09