1 /* 2 * Copyright (C) 2016 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 android.view.cts; 18 19 import android.opengl.GLSurfaceView; 20 import android.util.Log; 21 22 import javax.microedition.khronos.egl.EGLConfig; 23 import javax.microedition.khronos.opengles.GL10; 24 25 public class DisplayRefreshRateCtsActivity extends GLSurfaceViewCtsActivity { 26 private static final String TAG = "DisplayRefreshRateAct"; 27 28 public class FpsResult { 29 private float mFps; 30 private boolean mValid = false; 31 private boolean mRestartRequested = false; 32 33 public final synchronized void notifyResult(float fps) { 34 if (!mValid) { 35 mFps = fps; 36 mValid = true; 37 notifyAll(); 38 } 39 } 40 41 public final synchronized float waitResult() { 42 while (!mValid) { 43 try { 44 wait(); 45 } catch (InterruptedException e) {/* ignore and retry */} 46 } 47 return mFps; 48 } 49 50 public synchronized void restart() { 51 mRestartRequested = true; 52 mValid = false; 53 } 54 public synchronized boolean restartNecessary() { 55 return mRestartRequested; 56 } 57 public synchronized void ackRestart() { 58 mRestartRequested = false; 59 } 60 } 61 62 private class Renderer implements GLSurfaceView.Renderer { 63 // Measurement knobs. 64 // NB: Some devices need a surprisingly long warmup period before the 65 // framerate becomes stable. 66 private static final float WARMUP_SECONDS = 2.0f; 67 private static final float TEST_SECONDS = 8.0f; 68 69 // Test states 70 private static final int STATE_START = 0; 71 private static final int STATE_WARMUP = 1; 72 private static final int STATE_TEST = 2; 73 private static final int STATE_DONE = 3; 74 75 private FpsResult mResult; 76 private int mState = STATE_START; 77 private float mStartTime = 0.0f; 78 private int mNumFrames = 0; 79 80 public Renderer(FpsResult result) { 81 mResult = result; 82 } 83 84 public void onDrawFrame(GL10 gl) { 85 float t = (float)System.nanoTime() * 1.0e-9f; 86 switch (mState) { 87 case STATE_START: 88 mStartTime = t; 89 mState = STATE_WARMUP; 90 break; 91 92 case STATE_WARMUP: 93 if ((t - mStartTime) >= WARMUP_SECONDS) { 94 mStartTime = t; 95 mNumFrames = 0; 96 mState = STATE_TEST; 97 } 98 break; 99 100 case STATE_TEST: 101 mNumFrames++; 102 float elapsed = t - mStartTime; 103 if (elapsed >= TEST_SECONDS) { 104 mResult.notifyResult((float)mNumFrames / elapsed); 105 mState = STATE_DONE; 106 } 107 break; 108 109 case STATE_DONE: 110 if (mResult.restartNecessary()) { 111 mResult.ackRestart(); 112 mState = STATE_START; 113 Log.d(TAG, "restarting"); 114 } 115 break; 116 } 117 118 // prevent unwanted optimizations or hidden costs (e.g. reading 119 // previous frame on tilers). 120 gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 121 gl.glClear(gl.GL_COLOR_BUFFER_BIT); 122 } 123 124 public void onSurfaceChanged(GL10 gl, int width, int height) { 125 // Do nothing. 126 } 127 128 public void onSurfaceCreated(GL10 gl, EGLConfig config) { 129 // Do nothing. 130 } 131 } 132 133 private FpsResult mResult = new FpsResult(); 134 135 @Override 136 protected void configureGLSurfaceView() { 137 mView.setRenderer(new Renderer(mResult)); 138 mView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); 139 } 140 141 public FpsResult getFpsResult() { 142 return mResult; 143 } 144 } 145