Home | History | Annotate | Download | only in testlatency
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.testlatency;
     18 
     19 import android.content.Context;
     20 import android.opengl.GLSurfaceView;
     21 import android.util.AttributeSet;
     22 import android.util.Log;
     23 import android.view.KeyEvent;
     24 import android.view.MotionEvent;
     25 
     26 import java.nio.ByteBuffer;
     27 import java.nio.ByteOrder;
     28 import java.nio.FloatBuffer;
     29 
     30 import javax.microedition.khronos.egl.EGL10;
     31 import javax.microedition.khronos.egl.EGLConfig;
     32 import javax.microedition.khronos.egl.EGLContext;
     33 import javax.microedition.khronos.egl.EGLDisplay;
     34 import javax.microedition.khronos.opengles.GL10;
     35 
     36 import android.opengl.GLES20;
     37 
     38 /**
     39  * An implementation of SurfaceView that uses the dedicated surface for
     40  * displaying an OpenGL animation.  This allows the animation to run in a
     41  * separate thread, without requiring that it be driven by the update mechanism
     42  * of the view hierarchy.
     43  *
     44  * The application-specific rendering code is delegated to a GLView.Renderer
     45  * instance.
     46  */
     47 class TestLatencyView extends GLSurfaceView {
     48     private static String TAG = "TestLatencyiew";
     49     private float mX;
     50     private float mY;
     51     private float mDX;
     52     private float mDY;
     53     private long  mT;
     54     private long  mDT;
     55 
     56     public TestLatencyView(Context context) {
     57         super(context);
     58         setEGLContextClientVersion(2);
     59         setRenderer(new Renderer());
     60     }
     61 
     62     @Override
     63     public boolean onTouchEvent(MotionEvent event) {
     64         switch (event.getAction()) {
     65         case MotionEvent.ACTION_MOVE:
     66             float x = event.getX();
     67             float y = event.getY();
     68             long  t = event.getEventTime();
     69             synchronized(this) {
     70                 mDT = t - mT;
     71                 mT = t;
     72                 mDX = x - mX;
     73                 mX = x;
     74                 mDY = y - mY;
     75                 mY = y;
     76             }
     77             break;
     78         default:
     79             break;
     80         }
     81         return true;
     82     }
     83 
     84     private class Renderer implements GLSurfaceView.Renderer {
     85         private float mScaleX, mScaleY, mOffsetX, mOffsetY;
     86         private final float MS_PER_FRAME = 1000 / 60;
     87         public Renderer() {
     88             mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * 4)
     89                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
     90         }
     91 
     92 
     93         public void onDrawFrame(GL10 gl) {
     94             GLES20.glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
     95             GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
     96             GLES20.glUseProgram(mProgram);
     97             checkGlError("glUseProgram");
     98 
     99             float x, y, dx, dy;
    100             long t, dt;
    101             synchronized(TestLatencyView.this) {
    102                 x = mX;
    103                 y = mY;
    104                 dx = mDX;
    105                 dy = mDY;
    106                 dt = mDT;
    107             }
    108 
    109             if (dt > 0) {
    110                 dx = dx * MS_PER_FRAME / dt;
    111                 dy = dy * MS_PER_FRAME / dt;
    112             }
    113 
    114             GLES20.glEnableVertexAttribArray(mvPositionHandle);
    115             checkGlError("glEnableVertexAttribArray");
    116             GLES20.glEnableVertexAttribArray(mvColorHandle);
    117             checkGlError("glEnableVertexAttribArray");
    118             for(int step = 0; step < 8; step++) {
    119                 float sx = (x + dx * step) * mScaleX + mOffsetX;
    120                 float sy = (y + dy * step) * mScaleY + mOffsetY;
    121                 int cbase = step * 4;
    122 
    123                 for (int i = 0; i < mTriangleVerticesData.length; i += 6) {
    124                     mTriangleVerticesData2[i] = sx + mTriangleVerticesData[i];
    125                     mTriangleVerticesData2[i+1] = -sy + mTriangleVerticesData[i+1];
    126                     mTriangleVerticesData2[i+2] = mColors[cbase];
    127                     mTriangleVerticesData2[i+3] = mColors[cbase+1];
    128                     mTriangleVerticesData2[i+4] = mColors[cbase+2];
    129                     mTriangleVerticesData2[i+5] = mColors[cbase+3];
    130                 }
    131                 mTriangleVertices.position(0);
    132                 mTriangleVertices.put(mTriangleVerticesData2).position(0);
    133 
    134                 GLES20.glVertexAttribPointer(mvPositionHandle, 2, GLES20.GL_FLOAT, false, 6*4, mTriangleVertices);
    135                 checkGlError("glVertexAttribPointer mvPosition");
    136                 mTriangleVertices.put(mTriangleVerticesData2).position(2);
    137                 GLES20.glVertexAttribPointer(mvColorHandle, 4, GLES20.GL_FLOAT, false, 6*4, mTriangleVertices);
    138                 checkGlError("glVertexAttribPointer mvColor");
    139                 GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
    140                 checkGlError("glDrawArrays");
    141             }
    142         }
    143 
    144         public void onSurfaceChanged(GL10 gl, int width, int height) {
    145             GLES20.glViewport(0, 0, width, height);
    146             mScaleX = 2.0f / width;
    147             mScaleY = 2.0f / height;
    148             mOffsetX = -1f;
    149             mOffsetY = -1f;
    150         }
    151 
    152         public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    153             mProgram = createProgram(mVertexShader, mFragmentShader);
    154             if (mProgram == 0) {
    155                 return;
    156             }
    157             mvPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
    158             checkGlError("glGetAttribLocation");
    159             if (mvPositionHandle == -1) {
    160                 throw new RuntimeException("Could not get attrib location for vPosition");
    161             }
    162             mvColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
    163             checkGlError("glGetAttribLocation");
    164             if (mvColorHandle == -1) {
    165                 throw new RuntimeException("Could not get attrib location for vColor");
    166             }
    167         }
    168 
    169         private int loadShader(int shaderType, String source) {
    170             int shader = GLES20.glCreateShader(shaderType);
    171             if (shader != 0) {
    172                 GLES20.glShaderSource(shader, source);
    173                 GLES20.glCompileShader(shader);
    174                 int[] compiled = new int[1];
    175                 GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
    176                 if (compiled[0] == 0) {
    177                     Log.e(TAG, "Could not compile shader " + shaderType + ":");
    178                     Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
    179                     GLES20.glDeleteShader(shader);
    180                     shader = 0;
    181                 }
    182             }
    183             return shader;
    184         }
    185 
    186         private int createProgram(String vertexSource, String fragmentSource) {
    187             int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
    188             if (vertexShader == 0) {
    189                 return 0;
    190             }
    191 
    192             int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
    193             if (pixelShader == 0) {
    194                 return 0;
    195             }
    196 
    197             int program = GLES20.glCreateProgram();
    198             if (program != 0) {
    199                 GLES20.glAttachShader(program, vertexShader);
    200                 checkGlError("glAttachShader vertexShader");
    201                 GLES20.glAttachShader(program, pixelShader);
    202                 checkGlError("glAttachShader pixelShader");
    203                 GLES20.glLinkProgram(program);
    204                 int[] linkStatus = new int[1];
    205                 GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
    206                 if (linkStatus[0] != GLES20.GL_TRUE) {
    207                     Log.e(TAG, "Could not link program: ");
    208                     Log.e(TAG, GLES20.glGetProgramInfoLog(program));
    209                     GLES20.glDeleteProgram(program);
    210                     program = 0;
    211                 }
    212             }
    213             return program;
    214         }
    215 
    216         private void checkGlError(String op) {
    217             int error;
    218             while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
    219                 Log.e(TAG, op + ": glError " + error);
    220                 throw new RuntimeException(op + ": glError " + error);
    221             }
    222         }
    223 
    224         // X, Y, R G B A
    225         private final float[] mTriangleVerticesData = {
    226                 -0.025f, 0.3f, 0.0f, 1.0f, 0.0f, 1.0f,
    227                  0.0f  , 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
    228                  0.025f, 0.3f, 1.0f, 1.0f, 255.0f, 1.0f
    229                 };
    230 
    231         // Color cascade:
    232         private final float[] mColors = {
    233                 0.0f, 0.0f, 0.0f, 1.0f,
    234                 0.5f, 0.0f, 0.0f, 1.0f,
    235                 0.0f, 0.5f, 0.0f, 1.0f,
    236                 0.5f, 0.5f, 0.0f, 1.0f,
    237 
    238                 0.0f, 0.0f, 0.5f, 1.0f,
    239                 1.0f, 0.0f, 0.0f, 1.0f,
    240                 1.0f, 1.0f, 1.0f, 1.0f,
    241                 0.0f, 1.0f, 0.0f, 1.0f
    242         };
    243 
    244         private float[] mTriangleVerticesData2 = new float[mTriangleVerticesData.length];
    245         private FloatBuffer mTriangleVertices;
    246 
    247         private final String mVertexShader = "attribute vec4 aPosition;\n"
    248             + "attribute vec4 aColor;\n"
    249             + "varying vec4 vColor;\n"
    250             + "void main() {\n"
    251             + "  gl_Position = aPosition;\n"
    252             + "  vColor = aColor;\n"
    253             + "}\n";
    254 
    255         private final String mFragmentShader = "precision mediump float;\n"
    256             + "varying vec4 vColor;\n"
    257             + "void main() {\n"
    258             + "  gl_FragColor = vColor;\n"
    259             + "}\n";
    260 
    261         private int mProgram;
    262         private int mvPositionHandle;
    263         private int mvColorHandle;
    264 
    265     }
    266 }
    267 
    268