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/Composers.cpp b/cmds/flatland/Composers.cpp
new file mode 100644
index 0000000..8365a31
--- /dev/null
+++ b/cmds/flatland/Composers.cpp
@@ -0,0 +1,282 @@
+/*
+ * 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 {
+
+class Blitter {
+public:
+
+    bool setUp(GLHelper* helper) {
+        bool result;
+
+        result = helper->getShaderProgram("Blit", &mBlitPgm);
+        if (!result) {
+            return false;
+        }
+
+        mPosAttribLoc = glGetAttribLocation(mBlitPgm, "position");
+        mUVAttribLoc = glGetAttribLocation(mBlitPgm, "uv");
+        mUVToTexUniformLoc = glGetUniformLocation(mBlitPgm, "uvToTex");
+        mObjToNdcUniformLoc = glGetUniformLocation(mBlitPgm, "objToNdc");
+        mBlitSrcSamplerLoc = glGetUniformLocation(mBlitPgm, "blitSrc");
+        mModColorUniformLoc = glGetUniformLocation(mBlitPgm, "modColor");
+
+        return true;
+    }
+
+    bool blit(GLuint texName, const float* texMatrix,
+            int32_t x, int32_t y, uint32_t w, uint32_t h) {
+        float modColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+        return modBlit(texName, texMatrix, modColor, x, y, w, h);
+    }
+
+    bool modBlit(GLuint texName, const float* texMatrix, float* modColor,
+            int32_t x, int32_t y, uint32_t w, uint32_t h) {
+        glUseProgram(mBlitPgm);
+
+        GLint vp[4];
+        glGetIntegerv(GL_VIEWPORT, vp);
+        float screenToNdc[16] = {
+            2.0f/float(vp[2]),  0.0f,               0.0f,   0.0f,
+            0.0f,               -2.0f/float(vp[3]), 0.0f,   0.0f,
+            0.0f,               0.0f,               1.0f,   0.0f,
+            -1.0f,              1.0f,               0.0f,   1.0f,
+        };
+        const float pos[] = {
+            float(x),   float(y),
+            float(x+w), float(y),
+            float(x),   float(y+h),
+            float(x+w), float(y+h),
+        };
+        const float uv[] = {
+            0.0f, 0.0f,
+            1.0f, 0.0f,
+            0.0f, 1.0f,
+            1.0f, 1.0f,
+        };
+
+        glVertexAttribPointer(mPosAttribLoc, 2, GL_FLOAT, GL_FALSE, 0, pos);
+        glVertexAttribPointer(mUVAttribLoc, 2, GL_FLOAT, GL_FALSE, 0, uv);
+        glEnableVertexAttribArray(mPosAttribLoc);
+        glEnableVertexAttribArray(mUVAttribLoc);
+
+        glUniformMatrix4fv(mObjToNdcUniformLoc, 1, GL_FALSE, screenToNdc);
+        glUniformMatrix4fv(mUVToTexUniformLoc, 1, GL_FALSE, texMatrix);
+        glUniform4fv(mModColorUniformLoc, 1, modColor);
+
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_EXTERNAL_OES, texName);
+        glUniform1i(mBlitSrcSamplerLoc, 0);
+
+        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+        glDisableVertexAttribArray(mPosAttribLoc);
+        glDisableVertexAttribArray(mUVAttribLoc);
+
+        if (glGetError() != GL_NO_ERROR) {
+            fprintf(stderr, "GL error!\n");
+        }
+
+        return true;
+    }
+
+private:
+    GLuint mBlitPgm;
+    GLint mPosAttribLoc;
+    GLint mUVAttribLoc;
+    GLint mUVToTexUniformLoc;
+    GLint mObjToNdcUniformLoc;
+    GLint mBlitSrcSamplerLoc;
+    GLint mModColorUniformLoc;
+};
+
+class ComposerBase : public Composer {
+public:
+    virtual ~ComposerBase() {}
+
+    virtual bool setUp(const LayerDesc& desc,
+            GLHelper* helper) {
+        mLayerDesc = desc;
+        return setUp(helper);
+    }
+
+    virtual void tearDown() {
+    }
+
+    virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) {
+        return true;
+    }
+
+protected:
+    virtual bool setUp(GLHelper* helper) {
+        return true;
+    }
+
+    LayerDesc mLayerDesc;
+};
+
+Composer* nocomp() {
+    class NoComp : public ComposerBase {
+    };
+    return new NoComp();
+}
+
+Composer* opaque() {
+    class OpaqueComp : public ComposerBase {
+        virtual bool setUp(GLHelper* helper) {
+            return mBlitter.setUp(helper);
+        }
+
+        virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) {
+            float texMatrix[16];
+            glc->getTransformMatrix(texMatrix);
+
+            int32_t x = mLayerDesc.x;
+            int32_t y = mLayerDesc.y;
+            int32_t w = mLayerDesc.width;
+            int32_t h = mLayerDesc.height;
+
+            return mBlitter.blit(texName, texMatrix, x, y, w, h);
+        }
+
+        Blitter mBlitter;
+    };
+    return new OpaqueComp();
+}
+
+Composer* opaqueShrink() {
+    class OpaqueComp : public ComposerBase {
+        virtual bool setUp(GLHelper* helper) {
+            mParity = false;
+            return mBlitter.setUp(helper);
+        }
+
+        virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) {
+            float texMatrix[16];
+            glc->getTransformMatrix(texMatrix);
+
+            int32_t x = mLayerDesc.x;
+            int32_t y = mLayerDesc.y;
+            int32_t w = mLayerDesc.width;
+            int32_t h = mLayerDesc.height;
+
+            mParity = !mParity;
+            if (mParity) {
+                x += w / 128;
+                y += h / 128;
+                w -= w / 64;
+                h -= h / 64;
+            }
+
+            return mBlitter.blit(texName, texMatrix, x, y, w, h);
+        }
+
+        Blitter mBlitter;
+        bool mParity;
+    };
+    return new OpaqueComp();
+}
+
+Composer* blend() {
+    class BlendComp : public ComposerBase {
+        virtual bool setUp(GLHelper* helper) {
+            return mBlitter.setUp(helper);
+        }
+
+        virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) {
+            bool result;
+
+            float texMatrix[16];
+            glc->getTransformMatrix(texMatrix);
+
+            float modColor[4] = { .75f, .75f, .75f, .75f };
+
+            int32_t x = mLayerDesc.x;
+            int32_t y = mLayerDesc.y;
+            int32_t w = mLayerDesc.width;
+            int32_t h = mLayerDesc.height;
+
+            glEnable(GL_BLEND);
+            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+            result = mBlitter.modBlit(texName, texMatrix, modColor,
+                    x, y, w, h);
+            if (!result) {
+                return false;
+            }
+
+            glDisable(GL_BLEND);
+
+            return true;
+        }
+
+        Blitter mBlitter;
+    };
+    return new BlendComp();
+}
+
+Composer* blendShrink() {
+    class BlendShrinkComp : public ComposerBase {
+        virtual bool setUp(GLHelper* helper) {
+            mParity = false;
+            return mBlitter.setUp(helper);
+        }
+
+        virtual bool compose(GLuint texName, const sp<GLConsumer>& glc) {
+            bool result;
+
+            float texMatrix[16];
+            glc->getTransformMatrix(texMatrix);
+
+            float modColor[4] = { .75f, .75f, .75f, .75f };
+
+            int32_t x = mLayerDesc.x;
+            int32_t y = mLayerDesc.y;
+            int32_t w = mLayerDesc.width;
+            int32_t h = mLayerDesc.height;
+
+            mParity = !mParity;
+            if (mParity) {
+                x += w / 128;
+                y += h / 128;
+                w -= w / 64;
+                h -= h / 64;
+            }
+
+            glEnable(GL_BLEND);
+            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+            result = mBlitter.modBlit(texName, texMatrix, modColor,
+                    x, y, w, h);
+            if (!result) {
+                return false;
+            }
+
+            glDisable(GL_BLEND);
+
+            return true;
+        }
+
+        Blitter mBlitter;
+        bool mParity;
+    };
+    return new BlendShrinkComp();
+}
+
+} // namespace android