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