gq3
gq3

Reputation: 859

Android OpenGL responsiveness

I made a simple android application, which renders a square using openGL. The square can be moved using your finger. It works fine, but while moving the square around you can feel a considerable input lag, especially when doing circular motions. Are there any tricks to reduce or mask this lag?

Here's the code:

public class InputTestActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new InputTestView(this));
    }

    public class InputTestView extends GLSurfaceView {
        private InputTestRenderer renderer;

        private float prevX;
        private float prevY;

        public InputTestView(Context context) {
            super(context);
            renderer = new InputTestRenderer();
            setRenderer(renderer);
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();
            switch(event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                renderer.moveEye(prevX - x, prevY -y);
            case MotionEvent.ACTION_DOWN:
                prevX = x;
                prevY = y;
                break;
            }
            return true;
        }   
    }

    public class InputTestRenderer implements Renderer {
        private final float[] verts = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 0.0f };
        private final int nrOfVerts = verts.length / 3;
        private FloatBuffer vertBuf;

        private float eyeX;
        private float eyeY;

        public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

            gl.glColor4f(1, 0, 0, 1);

            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(verts.length * Float.SIZE / 8);
            byteBuffer.order(ByteOrder.nativeOrder());
            vertBuf = byteBuffer.asFloatBuffer();
            vertBuf.put(verts);
            vertBuf.position(0);
        }

        public void onSurfaceChanged(GL10 gl, int width, int height) {
            gl.glViewport(0, 0, width, height);

            gl.glMatrixMode(GL10.GL_PROJECTION);
            gl.glLoadIdentity();
            gl.glOrthof(-width / 2, width / 2, height / 2, -height / 2, 1, 100);
            gl.glMatrixMode(GL10.GL_MODELVIEW);
        }

        public void onDrawFrame(GL10 gl) {
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

            gl.glLoadIdentity();
            synchronized (this) {
                gl.glTranslatef(-eyeX, -eyeY, -10);
            }
            gl.glScalef(200, 200, 1);

            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertBuf);
            gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, nrOfVerts);
        }

        public synchronized void moveEye(float deltaX, float deltaY) {
            this.eyeX += deltaX;
            this.eyeY += deltaY;
        }
    }
}

Upvotes: 1

Views: 1553

Answers (1)

Reuben Scratton
Reuben Scratton

Reputation: 38707

Suspect your UI thread and your rendering thread are fighting for CPU time. Try adding this line to onSurfaceCreated() :

Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

Reducing the renderer's priority ensures that motion events get processed a bit more promptly. Seems to make a difference.

FWIW I dislike GLSurfaceView's design and prefer to aim for a set framerate, usually 50, using Handler.postDelayed() to schedule each frame to be drawn at 20ms intervals.

Upvotes: 1

Related Questions