1 /*
2  * Copyright (C) 2019 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.List;
19 
20 import javax.microedition.khronos.opengles.GL;
21 
22 import android.annotation.NonNull;
23 import android.content.Context;
24 import android.opengl.GLES20;
25 import android.opengl.Matrix;
26 
27 /**
28  * Base class for all OpenGL based tests that use RenderPatch as a base.
29  */
30 public abstract class RenderPatchOpenGLTest extends OpenGLTest {
31     private final float[] COLOR = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
32 
33     private final String VERTEX_SHADER =
34             "uniform mat4 uMVPMatrix;"
35                     + "attribute vec4 vPosition;"
36                     + "attribute vec2 vTexture;"
37                     + "varying vec2 vTex;"
38                     + "void main() {"
39                     + "  vTex = vTexture;"
40                     + "  gl_Position = uMVPMatrix * vPosition;"
41                     + "}";
42 
43     private final String FRAGMENT_SHADER =
44             "precision mediump float;"
45                     + "uniform sampler2D uTexture;"
46                     + "uniform vec4 uColor;"
47                     + "varying vec2 vTex;"
48                     + "void main() {"
49                     + "  vec4 color = texture2D(uTexture, vTex);"
50                     + "  gl_FragColor = uColor * color;"
51                     + "}";
52 
53     private List<RenderPatchAnimation> mRenderPatches;
54 
55     private int mProgram = -1;
56     private int mMVPMatrixHandle;
57     private int mTextureHandle;
58     private int mPositionHandle;
59     private int mColorHandle;
60     private int mTextureCoordHandle;
61 
62     private final float[] mVPMatrix = new float[16];
63 
RenderPatchOpenGLTest(@onNull GamePerformanceActivity activity)64     public RenderPatchOpenGLTest(@NonNull GamePerformanceActivity activity) {
65         super(activity);
66     }
67 
setRenderPatches(@onNull List<RenderPatchAnimation> renderPatches)68     protected void setRenderPatches(@NonNull List<RenderPatchAnimation> renderPatches) {
69         mRenderPatches = renderPatches;
70     }
71 
ensureInited()72     private void ensureInited() {
73         if (mProgram >= 0) {
74             return;
75         }
76 
77         mProgram = OpenGLUtils.createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
78 
79         // get handle to fragment shader's uColor member
80         GLES20.glUseProgram(mProgram);
81         OpenGLUtils.checkGlError("useProgram");
82 
83         // get handle to shape's transformation matrix
84         mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
85         OpenGLUtils.checkGlError("get uMVPMatrix");
86 
87         mTextureHandle = GLES20.glGetUniformLocation(mProgram, "uTexture");
88         OpenGLUtils.checkGlError("uTexture");
89         // get handle to vertex shader's vPosition member
90         mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
91         OpenGLUtils.checkGlError("vPosition");
92         mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram, "vTexture");
93         OpenGLUtils.checkGlError("vTexture");
94         mColorHandle = GLES20.glGetUniformLocation(mProgram, "uColor");
95         OpenGLUtils.checkGlError("uColor");
96 
97         mTextureHandle = OpenGLUtils.createTexture(getContext(), R.drawable.logo);
98 
99         final float[] projectionMatrix = new float[16];
100         final float[] viewMatrix = new float[16];
101 
102         final float ratio = getView().getRenderRatio();
103         Matrix.orthoM(projectionMatrix, 0, -ratio, ratio, -1, 1, -1, 1);
104         Matrix.setLookAtM(viewMatrix, 0, 0, 0, -0.5f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
105         Matrix.multiplyMM(mVPMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
106     }
107 
108     /**
109      * Returns global color for patch.
110      */
getColor()111     public float[] getColor() {
112         return COLOR;
113     }
114 
115     /**
116      * Extra setup for particular tests.
117      */
onBeforeDraw(GL gl)118     public void onBeforeDraw(GL gl) {
119     }
120 
121     @Override
draw(GL gl)122     public void draw(GL gl) {
123         ensureInited();
124 
125         GLES20.glUseProgram(mProgram);
126         OpenGLUtils.checkGlError("useProgram");
127 
128         GLES20.glDisable(GLES20.GL_BLEND);
129         OpenGLUtils.checkGlError("disableBlend");
130 
131         GLES20.glEnableVertexAttribArray(mPositionHandle);
132         OpenGLUtils.checkGlError("enableVertexAttributes");
133 
134         GLES20.glEnableVertexAttribArray(mTextureCoordHandle);
135         OpenGLUtils.checkGlError("enableTexturesAttributes");
136 
137         GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureHandle);
138         OpenGLUtils.checkGlError("setTexture");
139 
140         GLES20.glUniform4fv(mColorHandle, 1, getColor(), 0);
141         OpenGLUtils.checkGlError("setColor");
142 
143         onBeforeDraw(gl);
144 
145         for (final RenderPatchAnimation renderPatchAnimation : mRenderPatches) {
146 
147             renderPatchAnimation.update(0.01f);
148             GLES20.glUniformMatrix4fv(mMVPMatrixHandle,
149                                       1,
150                                       false,
151                                       renderPatchAnimation.getTransform(mVPMatrix),
152                                       0);
153             OpenGLUtils.checkGlError("setTransform");
154 
155             GLES20.glVertexAttribPointer(
156                     mPositionHandle,
157                     RenderPatch.VERTEX_COORD_COUNT,
158                     GLES20.GL_FLOAT,
159                     false /* normalized */,
160                     RenderPatch.VERTEX_STRIDE,
161                     renderPatchAnimation.getRenderPatch().getVertexBuffer());
162             OpenGLUtils.checkGlError("setVertexAttribute");
163 
164             GLES20.glVertexAttribPointer(
165                     mTextureCoordHandle,
166                     RenderPatch.TEXTURE_COORD_COUNT,
167                     GLES20.GL_FLOAT,
168                     false /* normalized */,
169                     RenderPatch.TEXTURE_STRIDE,
170                     renderPatchAnimation.getRenderPatch().getTextureBuffer());
171             OpenGLUtils.checkGlError("setTextureAttribute");
172 
173             // Draw the patch.
174             final int indicesCount =
175                     renderPatchAnimation.getRenderPatch().getIndexBuffer().capacity() /
176                     RenderPatch.SHORT_SIZE;
177             GLES20.glDrawElements(
178                     GLES20.GL_TRIANGLES,
179                     indicesCount,
180                     GLES20.GL_UNSIGNED_SHORT,
181                     renderPatchAnimation.getRenderPatch().getIndexBuffer());
182             OpenGLUtils.checkGlError("drawPatch");
183         }
184 
185         GLES20.glDisableVertexAttribArray(mPositionHandle);
186         GLES20.glDisableVertexAttribArray(mTextureCoordHandle);
187     }
188 }