1 /* 2 * Copyright (C) 2018 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 package android.gameperformance; 17 18 import java.util.ArrayList; 19 import java.util.List; 20 21 import javax.microedition.khronos.egl.EGLConfig; 22 import javax.microedition.khronos.opengles.GL10; 23 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.content.Context; 27 import android.opengl.GLES20; 28 import android.opengl.GLSurfaceView; 29 import android.util.Log; 30 31 public class CustomOpenGLView extends GLSurfaceView { 32 public final static String TAG = "CustomOpenGLView"; 33 34 private final List<Long> mFrameTimes; 35 private final Object mLock = new Object(); 36 private boolean mRenderReady = false; 37 private FrameDrawer mFrameDrawer = null; 38 39 private float mRenderRatio; 40 private int mRenderWidth; 41 private int mRenderHeight; 42 43 public interface FrameDrawer { drawFrame(@onNull GL10 gl)44 public void drawFrame(@NonNull GL10 gl); 45 } 46 CustomOpenGLView(@onNull Context context)47 public CustomOpenGLView(@NonNull Context context) { 48 super(context); 49 50 mFrameTimes = new ArrayList<Long>(); 51 52 setEGLContextClientVersion(2); 53 54 setRenderer(new GLSurfaceView.Renderer() { 55 @Override 56 public void onSurfaceCreated(GL10 gl, EGLConfig config) { 57 Log.i(TAG, "SurfaceCreated: " + config); 58 GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 59 gl.glClearDepthf(1.0f); 60 gl.glDisable(GL10.GL_DEPTH_TEST); 61 gl.glDepthFunc(GL10.GL_LEQUAL); 62 63 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, 64 GL10.GL_NICEST); 65 synchronized (mLock) { 66 mRenderReady = true; 67 mLock.notify(); 68 } 69 } 70 71 @Override 72 public void onSurfaceChanged(GL10 gl, int width, int height) { 73 Log.i(TAG, "SurfaceChanged: " + width + "x" + height); 74 GLES20.glViewport(0, 0, width, height); 75 setRenderBounds(width, height); 76 } 77 78 @Override 79 public void onDrawFrame(GL10 gl) { 80 GLES20.glClearColor(0.25f, 0.25f, 0.25f, 1.0f); 81 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 82 synchronized (mLock) { 83 if (mFrameDrawer != null) { 84 mFrameDrawer.drawFrame(gl); 85 } 86 mFrameTimes.add(System.currentTimeMillis()); 87 } 88 } 89 }); 90 setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); 91 } 92 setRenderBounds(int width, int height)93 public void setRenderBounds(int width, int height) { 94 mRenderWidth = width; 95 mRenderHeight = height; 96 mRenderRatio = (float) mRenderWidth / mRenderHeight; 97 } 98 getRenderRatio()99 public float getRenderRatio() { 100 return mRenderRatio; 101 } 102 getRenderWidth()103 public int getRenderWidth() { 104 return mRenderWidth; 105 } 106 getRenderHeight()107 public int getRenderHeight() { 108 return mRenderHeight; 109 } 110 111 /** 112 * Resets frame times in order to calculate FPS for the different test pass. 113 */ resetFrameTimes()114 public void resetFrameTimes() { 115 synchronized (mLock) { 116 mFrameTimes.clear(); 117 } 118 } 119 120 /** 121 * Returns current FPS based on collected frame times. 122 */ getFps()123 public double getFps() { 124 synchronized (mLock) { 125 if (mFrameTimes.size() < 2) { 126 return 0.0f; 127 } 128 return 1000.0 * mFrameTimes.size() / 129 (mFrameTimes.get(mFrameTimes.size() - 1) - mFrameTimes.get(0)); 130 } 131 } 132 133 /** 134 * Waits for render attached to the view. 135 */ waitRenderReady()136 public void waitRenderReady() { 137 synchronized (mLock) { 138 while (!mRenderReady) { 139 try { 140 mLock.wait(); 141 } catch (InterruptedException e) { 142 Thread.currentThread().interrupt(); 143 } 144 } 145 } 146 } 147 148 /** 149 * Sets/resets frame drawer. 150 */ setFrameDrawer(@ullable FrameDrawer frameDrawer)151 public void setFrameDrawer(@Nullable FrameDrawer frameDrawer) { 152 mFrameDrawer = frameDrawer; 153 } 154 } 155