Refactoring of Program ownership/lifecycle, and WIP Glop rendering path

Change-Id: I2549032790bddbc048b0bccc224ed8f386b4517c
diff --git a/libs/hwui/renderstate/MeshState.cpp b/libs/hwui/renderstate/MeshState.cpp
index 7820a66..022faf7d 100644
--- a/libs/hwui/renderstate/MeshState.cpp
+++ b/libs/hwui/renderstate/MeshState.cpp
@@ -39,6 +39,9 @@
 
     mQuadListIndices = 0;
     mShadowStripsIndices = 0;
+
+    // position attribute always enabled
+    glEnableVertexAttribArray(Program::kBindingPosition);
 }
 
 MeshState::~MeshState() {
@@ -83,21 +86,17 @@
 // Vertices
 ///////////////////////////////////////////////////////////////////////////////
 
-void MeshState::bindPositionVertexPointer(const Program* currentProgram, bool force,
-        const GLvoid* vertices, GLsizei stride) {
+void MeshState::bindPositionVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
     if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) {
-        GLuint slot = currentProgram->position;
-        glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
+        glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices);
         mCurrentPositionPointer = vertices;
         mCurrentPositionStride = stride;
     }
 }
 
-void MeshState::bindTexCoordsVertexPointer(const Program* currentProgram, bool force,
-        const GLvoid* vertices, GLsizei stride) {
+void MeshState::bindTexCoordsVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
     if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) {
-        GLuint slot = currentProgram->texCoords;
-        glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
+        glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices);
         mCurrentTexCoordsPointer = vertices;
         mCurrentTexCoordsStride = stride;
     }
diff --git a/libs/hwui/renderstate/MeshState.h b/libs/hwui/renderstate/MeshState.h
index 76f73d4..9b1021d 100644
--- a/libs/hwui/renderstate/MeshState.h
+++ b/libs/hwui/renderstate/MeshState.h
@@ -80,15 +80,15 @@
      * Binds an attrib to the specified float vertex pointer.
      * Assumes a stride of gTextureVertexStride and a size of 2.
      */
-    void bindPositionVertexPointer(const Program* currentProgram, bool force,
-            const GLvoid* vertices, GLsizei stride = kTextureVertexStride);
+    void bindPositionVertexPointer(bool force, const GLvoid* vertices,
+            GLsizei stride = kTextureVertexStride);
 
     /**
      * Binds an attrib to the specified float vertex pointer.
      * Assumes a stride of gTextureVertexStride and a size of 2.
      */
-    void bindTexCoordsVertexPointer(const Program* currentProgram, bool force,
-            const GLvoid* vertices, GLsizei stride = kTextureVertexStride);
+    void bindTexCoordsVertexPointer(bool force, const GLvoid* vertices,
+            GLsizei stride = kTextureVertexStride);
 
     /**
      * Resets the vertex pointers.
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index f913cd9..8eda7c9 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -127,12 +127,7 @@
 }
 
 void RenderState::interruptForFunctorInvoke() {
-    if (mCaches->currentProgram) {
-        if (mCaches->currentProgram->isInUse()) {
-            mCaches->currentProgram->remove();
-            mCaches->currentProgram = nullptr;
-        }
-    }
+    mCaches->setProgram(nullptr);
     mCaches->textureState().resetActiveTexture();
     meshState().unbindMeshBuffer();
     meshState().unbindIndicesBuffer();
@@ -179,7 +174,6 @@
     LOG_ALWAYS_FATAL_IF(!pthread_equal(mThreadId, curr), "Wrong thread!");
 }
 
-
 class DecStrongTask : public renderthread::RenderTask {
 public:
     DecStrongTask(VirtualLightRefBase* object) : mObject(object) {}
@@ -198,5 +192,82 @@
     mRenderThread.queue(new DecStrongTask(object));
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// Render
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Not yet supported:
+ *
+ * Textures + coordinates
+ * SkiaShader
+ * ColorFilter
+ *
+    // TODO: texture coord
+    // TODO: texture support
+    // TODO: skiashader support
+    // TODO: color filter support
+ */
+
+void RenderState::render(const Glop& glop) {
+    const Glop::Mesh& mesh = glop.mesh;
+    const Glop::Fill& shader = glop.fill;
+
+    // ---------- Shader + uniform setup ----------
+    mCaches->setProgram(shader.program);
+
+    Glop::Fill::Color color = shader.color;
+    shader.program->setColor(color.a, color.r, color.g, color.b);
+
+    shader.program->set(glop.transform.ortho,
+            glop.transform.modelView,
+            glop.transform.canvas,
+            glop.transform.offset);
+
+    // ---------- Mesh setup ----------
+    if (glop.mesh.vertexFlags & kTextureCoord_Attrib) {
+        // TODO: support textures
+        LOG_ALWAYS_FATAL("textures not yet supported");
+    } else {
+        meshState().disableTexCoordsVertexArray();
+    }
+    if (glop.mesh.vertexFlags & kColor_Attrib) {
+        LOG_ALWAYS_FATAL("color attribute not yet supported");
+        // TODO: enable color, disable when done
+    }
+    if (glop.mesh.vertexFlags & kAlpha_Attrib) {
+        LOG_ALWAYS_FATAL("alpha attribute not yet supported");
+        // TODO: enable alpha attribute, disable when done
+    }
+
+    /**
+    * Hard-coded vertex assumptions:
+     *     - required
+     *     - xy floats
+     *     - 0 offset
+     *     - in VBO
+     */
+    bool force = meshState().bindMeshBuffer(mesh.vertexBufferObject);
+    meshState().bindPositionVertexPointer(force, nullptr, mesh.stride);
+
+    /**
+     * Hard-coded index assumptions:
+     *     - optional
+     *     - 0 offset
+     *     - in IBO
+     */
+    meshState().bindIndicesBufferInternal(mesh.indexBufferObject);
+
+    // ---------- GL state setup ----------
+
+    if (glop.blend.mode != Glop::Blend::kDisable) {
+        blend().enable(glop.blend.mode, glop.blend.swapSrcDst);
+    } else {
+        blend().disable();
+    }
+
+    glDrawElements(glop.mesh.primitiveMode, glop.mesh.vertexCount, GL_UNSIGNED_BYTE, nullptr);
+}
+
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index 4180f44..2e28ff6 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -22,11 +22,12 @@
 #include <utils/Mutex.h>
 #include <utils/Functor.h>
 #include <utils/RefBase.h>
-
 #include <private/hwui/DrawGlInfo.h>
 #include <renderstate/Blend.h>
+
 #include "AssetAtlas.h"
 #include "Caches.h"
+#include "Glop.h"
 #include "renderstate/MeshState.h"
 #include "renderstate/PixelBufferState.h"
 #include "renderstate/Scissor.h"
@@ -83,6 +84,8 @@
     // more thinking...
     void postDecStrong(VirtualLightRefBase* object);
 
+    void render(const Glop& glop);
+
     AssetAtlas& assetAtlas() { return mAssetAtlas; }
     Blend& blend() { return *mBlend; }
     MeshState& meshState() { return *mMeshState; }
@@ -96,6 +99,9 @@
     void resumeFromFunctorInvoke();
     void assertOnGLThread();
 
+    void setupVertexAttributes(const Glop& glop);
+    void tearDownVertexAttributes(const Glop& glop);
+
     RenderState(renderthread::RenderThread& thread);
     ~RenderState();