flatland: add a GPU hardware benchmark
This change adds a GPU benchmark named 'flatland' that is intended to measure
GPU performance of UI rendering and compositing scenarios at a fixed a clock
frequency. This initial version includes only window compositing scenarios.
Change-Id: I5577863aa3be5c6da8b49cb5d53cc49dec2f7081
diff --git a/cmds/flatland/Renderers.cpp b/cmds/flatland/Renderers.cpp
new file mode 100644
index 0000000..f1e5488
--- /dev/null
+++ b/cmds/flatland/Renderers.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include "Flatland.h"
+#include "GLHelper.h"
+
+namespace android {
+
+static float colors[][4] = {
+ { .85f, .14f, .44f, 1.0f },
+ { .91f, .72f, .10f, 1.0f },
+ { .04f, .66f, .42f, 1.0f },
+ { .84f, .39f, .68f, 1.0f },
+ { .38f, .53f, .78f, 1.0f },
+};
+
+static size_t g_colorIndex;
+
+const float* genColor() {
+ float* color = colors[g_colorIndex];
+ g_colorIndex = (g_colorIndex + 1) % NELEMS(colors);
+ return color;
+}
+
+void resetColorGenerator() {
+ g_colorIndex = 0;
+}
+
+class GradientRenderer {
+
+public:
+
+ bool setUp(GLHelper* helper) {
+ bool result;
+
+ result = helper->getShaderProgram("Gradient", &mGradPgm);
+ if (!result) {
+ return false;
+ }
+
+ result = helper->getDitherTexture(&mDitherTexName);
+ if (!result) {
+ return false;
+ }
+
+ mPosAttribLoc = glGetAttribLocation(mGradPgm, "position");
+ mUVAttribLoc = glGetAttribLocation(mGradPgm, "uv");
+ mUVToInterpUniformLoc = glGetUniformLocation(mGradPgm, "uvToInterp");
+ mObjToNdcUniformLoc = glGetUniformLocation(mGradPgm, "objToNdc");
+ mDitherKernelSamplerLoc = glGetUniformLocation(mGradPgm, "ditherKernel");
+ mInvDitherKernelSizeUniformLoc = glGetUniformLocation(mGradPgm,
+ "invDitherKernelSize");
+ mInvDitherKernelSizeSqUniformLoc = glGetUniformLocation(mGradPgm,
+ "invDitherKernelSizeSq");
+ mColor0UniformLoc = glGetUniformLocation(mGradPgm, "color0");
+ mColor1UniformLoc = glGetUniformLocation(mGradPgm, "color1");
+
+ return true;
+ }
+
+ void tearDown() {
+ }
+
+ bool drawGradient() {
+ float identity[16] = {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f,
+ };
+ const float pos[] = {
+ -1.0f, -1.0f,
+ 1.0f, -1.0f,
+ -1.0f, 1.0f,
+ 1.0f, 1.0f,
+ };
+ const float uv[] = {
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ };
+ const float* color0 = genColor();
+ const float* color1 = genColor();
+
+ glUseProgram(mGradPgm);
+
+ glVertexAttribPointer(mPosAttribLoc, 2, GL_FLOAT, GL_FALSE, 0, pos);
+ glVertexAttribPointer(mUVAttribLoc, 2, GL_FLOAT, GL_FALSE, 0, uv);
+ glEnableVertexAttribArray(mPosAttribLoc);
+ glEnableVertexAttribArray(mUVAttribLoc);
+
+ float invDitherKernelSize = 1.0f / float(GLHelper::DITHER_KERNEL_SIZE);
+ float invDitherKernelSizeSq = invDitherKernelSize * invDitherKernelSize;
+
+ glUniformMatrix4fv(mObjToNdcUniformLoc, 1, GL_FALSE, identity);
+ glUniformMatrix4fv(mUVToInterpUniformLoc, 1, GL_FALSE, identity);
+ glUniform1f(mInvDitherKernelSizeUniformLoc, invDitherKernelSize);
+ glUniform1f(mInvDitherKernelSizeSqUniformLoc, invDitherKernelSizeSq);
+ glUniform4fv(mColor0UniformLoc, 1, color0);
+ glUniform4fv(mColor1UniformLoc, 1, color1);
+
+ if (glGetError() != GL_NO_ERROR) {
+ fprintf(stderr, "GL error! 0\n");
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, mDitherTexName);
+
+ if (glGetError() != GL_NO_ERROR) {
+ fprintf(stderr, "GL error! 1\n");
+ }
+
+ glUniform1i(mDitherKernelSamplerLoc, 0);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glDisableVertexAttribArray(mPosAttribLoc);
+ glDisableVertexAttribArray(mUVAttribLoc);
+
+ if (glGetError() != GL_NO_ERROR) {
+ fprintf(stderr, "GL error! 2\n");
+ }
+
+ return true;
+ }
+
+ GLuint mGradPgm;
+ GLuint mDitherTexName;
+ GLuint mPosAttribLoc;
+ GLuint mUVAttribLoc;
+ GLuint mObjToNdcUniformLoc;
+ GLuint mUVToInterpUniformLoc;
+ GLuint mDitherKernelSamplerLoc;
+ GLuint mInvDitherKernelSizeUniformLoc;
+ GLuint mInvDitherKernelSizeSqUniformLoc;
+ GLuint mColor0UniformLoc;
+ GLuint mColor1UniformLoc;
+};
+
+Renderer* staticGradient() {
+ class NoRenderer : public Renderer {
+ virtual bool setUp(GLHelper* helper) {
+ mIsFirstFrame = true;
+ mGLHelper = helper;
+ return mGradientRenderer.setUp(helper);
+ }
+
+ virtual void tearDown() {
+ mGradientRenderer.tearDown();
+ }
+
+ virtual bool render(EGLSurface surface) {
+ if (mIsFirstFrame) {
+ bool result;
+ mIsFirstFrame = false;
+
+ result = mGLHelper->makeCurrent(surface);
+ if (!result) {
+ return false;
+ }
+
+ result = mGradientRenderer.drawGradient();
+ if (!result) {
+ return false;
+ }
+
+ result = mGLHelper->swapBuffers(surface);
+ if (!result) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool mIsFirstFrame;
+ GLHelper* mGLHelper;
+ GradientRenderer mGradientRenderer;
+ };
+ return new NoRenderer;
+}
+
+
+} // namespace android