/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.gameperformance; import java.util.List; import javax.microedition.khronos.opengles.GL; import android.annotation.NonNull; import android.content.Context; import android.opengl.GLES20; import android.opengl.Matrix; /** * Base class for all OpenGL based tests that use RenderPatch as a base. */ public abstract class RenderPatchOpenGLTest extends OpenGLTest { private final float[] COLOR = new float[] { 1.0f, 1.0f, 1.0f, 1.0f }; private final String VERTEX_SHADER = "uniform mat4 uMVPMatrix;" + "attribute vec4 vPosition;" + "attribute vec2 vTexture;" + "varying vec2 vTex;" + "void main() {" + " vTex = vTexture;" + " gl_Position = uMVPMatrix * vPosition;" + "}"; private final String FRAGMENT_SHADER = "precision mediump float;" + "uniform sampler2D uTexture;" + "uniform vec4 uColor;" + "varying vec2 vTex;" + "void main() {" + " vec4 color = texture2D(uTexture, vTex);" + " gl_FragColor = uColor * color;" + "}"; private List mRenderPatches; private int mProgram = -1; private int mMVPMatrixHandle; private int mTextureHandle; private int mPositionHandle; private int mColorHandle; private int mTextureCoordHandle; private final float[] mVPMatrix = new float[16]; public RenderPatchOpenGLTest(@NonNull GamePerformanceActivity activity) { super(activity); } protected void setRenderPatches(@NonNull List renderPatches) { mRenderPatches = renderPatches; } private void ensureInited() { if (mProgram >= 0) { return; } mProgram = OpenGLUtils.createProgram(VERTEX_SHADER, FRAGMENT_SHADER); // get handle to fragment shader's uColor member GLES20.glUseProgram(mProgram); OpenGLUtils.checkGlError("useProgram"); // get handle to shape's transformation matrix mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); OpenGLUtils.checkGlError("get uMVPMatrix"); mTextureHandle = GLES20.glGetUniformLocation(mProgram, "uTexture"); OpenGLUtils.checkGlError("uTexture"); // get handle to vertex shader's vPosition member mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); OpenGLUtils.checkGlError("vPosition"); mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram, "vTexture"); OpenGLUtils.checkGlError("vTexture"); mColorHandle = GLES20.glGetUniformLocation(mProgram, "uColor"); OpenGLUtils.checkGlError("uColor"); mTextureHandle = OpenGLUtils.createTexture(getContext(), R.drawable.logo); final float[] projectionMatrix = new float[16]; final float[] viewMatrix = new float[16]; final float ratio = getView().getRenderRatio(); Matrix.orthoM(projectionMatrix, 0, -ratio, ratio, -1, 1, -1, 1); Matrix.setLookAtM(viewMatrix, 0, 0, 0, -0.5f, 0f, 0f, 0f, 0f, 1.0f, 0.0f); Matrix.multiplyMM(mVPMatrix, 0, projectionMatrix, 0, viewMatrix, 0); } /** * Returns global color for patch. */ public float[] getColor() { return COLOR; } /** * Extra setup for particular tests. */ public void onBeforeDraw(GL gl) { } @Override public void draw(GL gl) { ensureInited(); GLES20.glUseProgram(mProgram); OpenGLUtils.checkGlError("useProgram"); GLES20.glDisable(GLES20.GL_BLEND); OpenGLUtils.checkGlError("disableBlend"); GLES20.glEnableVertexAttribArray(mPositionHandle); OpenGLUtils.checkGlError("enableVertexAttributes"); GLES20.glEnableVertexAttribArray(mTextureCoordHandle); OpenGLUtils.checkGlError("enableTexturesAttributes"); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureHandle); OpenGLUtils.checkGlError("setTexture"); GLES20.glUniform4fv(mColorHandle, 1, getColor(), 0); OpenGLUtils.checkGlError("setColor"); onBeforeDraw(gl); for (final RenderPatchAnimation renderPatchAnimation : mRenderPatches) { renderPatchAnimation.update(0.01f); GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, renderPatchAnimation.getTransform(mVPMatrix), 0); OpenGLUtils.checkGlError("setTransform"); GLES20.glVertexAttribPointer( mPositionHandle, RenderPatch.VERTEX_COORD_COUNT, GLES20.GL_FLOAT, false /* normalized */, RenderPatch.VERTEX_STRIDE, renderPatchAnimation.getRenderPatch().getVertexBuffer()); OpenGLUtils.checkGlError("setVertexAttribute"); GLES20.glVertexAttribPointer( mTextureCoordHandle, RenderPatch.TEXTURE_COORD_COUNT, GLES20.GL_FLOAT, false /* normalized */, RenderPatch.TEXTURE_STRIDE, renderPatchAnimation.getRenderPatch().getTextureBuffer()); OpenGLUtils.checkGlError("setTextureAttribute"); // Draw the patch. final int indicesCount = renderPatchAnimation.getRenderPatch().getIndexBuffer().capacity() / RenderPatch.SHORT_SIZE; GLES20.glDrawElements( GLES20.GL_TRIANGLES, indicesCount, GLES20.GL_UNSIGNED_SHORT, renderPatchAnimation.getRenderPatch().getIndexBuffer()); OpenGLUtils.checkGlError("drawPatch"); } GLES20.glDisableVertexAttribArray(mPositionHandle); GLES20.glDisableVertexAttribArray(mTextureCoordHandle); } }