Cleanup implementation of hardware layers.

The new implementation relies on OpenGLRenderer's existing layer
code instead of duplicating it. The new code is much cleaner, with
simpler and better APIs and allows tracking of drawn regions inside
layers. Region tracking is not yet enabled but this will be done
in a future CL.

Change-Id: Ie826121a2227de8252c77b992a61218defea5143
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 3563064..fde4f96 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -109,29 +109,22 @@
 
     Mutex::Autolock _l(mGarbageLock);
 
-    size_t count = mFboGarbage.size();
+    size_t count = mLayerGarbage.size();
     for (size_t i = 0; i < count; i++) {
-        GLuint fbo = mFboGarbage.itemAt(i);
-        if (fbo) glDeleteFramebuffers(1, &fbo);
-    }
-    mFboGarbage.clear();
+        Layer* layer = mLayerGarbage.itemAt(i);
+        if (layer) {
+            if (layer->fbo) glDeleteFramebuffers(1, &layer->fbo);
+            if (layer->texture) glDeleteTextures(1, &layer->texture);
 
-    count = mTextureGarbage.size();
-    for (size_t i = 0; i < count; i++) {
-        GLuint texture = mTextureGarbage.itemAt(i);
-        if (texture) glDeleteTextures(1, &texture);
+            delete layer;
+        }
     }
-    mTextureGarbage.clear();
+    mLayerGarbage.clear();
 }
 
-void Caches::deleteFboDeferred(GLuint fbo) {
+void Caches::deleteLayerDeferred(Layer* layer) {
     Mutex::Autolock _l(mGarbageLock);
-    mFboGarbage.push(fbo);
-}
-
-void Caches::deleteTextureDeferred(GLuint texture) {
-    Mutex::Autolock _l(mGarbageLock);
-    mTextureGarbage.push(texture);
+    mLayerGarbage.push(layer);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 34f48c9..a11b6bc 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -91,8 +91,7 @@
     GLuint mRegionMeshIndices;
 
     mutable Mutex mGarbageLock;
-    Vector<GLuint> mFboGarbage;
-    Vector<GLuint> mTextureGarbage;
+    Vector<Layer*> mLayerGarbage;
 
 public:
     /**
@@ -110,14 +109,9 @@
     void clearGarbage();
 
     /**
-     * Can be used to delete an FBO from a non EGL thread.
+     * Can be used to delete a layer from a non EGL thread.
      */
-    void deleteFboDeferred(GLuint fbo);
-
-    /**
-     * Can be used to delete a texture from a non EGL thread.
-     */
-    void deleteTextureDeferred(GLuint texture);
+    void deleteLayerDeferred(Layer* layer);
 
     /**
      * Binds the VBO used to render simple textured quads.
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index fdb4e8c..57df976 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -242,8 +242,7 @@
             }
             break;
             case DrawLayer: {
-                renderer.drawLayer(getInt(), getFloat(), getFloat(), getFloat(), getFloat(),
-                        getFloat(), getFloat(), getPaint());
+                renderer.drawLayer((Layer*) getInt(), getFloat(), getFloat(), getPaint());
             }
             break;
             case DrawBitmap: {
@@ -488,13 +487,10 @@
     addDisplayList(displayList);
 }
 
-void DisplayListRenderer::drawLayer(int texture, float left, float top, float right, float bottom,
-        float u, float v, SkPaint* paint) {
+void DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
     addOp(DisplayList::DrawLayer);
-    addInt(texture);
-    addBounds(left, top, right, bottom);
-    addFloat(u);
-    addFloat(v);
+    addInt((int) layer);
+    addPoint(x, y);
     addPaint(paint);
 }
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 62cb0e8..0822725 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -246,8 +246,7 @@
     bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
 
     void drawDisplayList(DisplayList* displayList);
-    void drawLayer(int texture, float left, float top, float right, float bottom,
-            float u, float v, SkPaint* paint);
+    void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index b838764..a25c95e 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -27,10 +27,10 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void LayerRenderer::prepare(bool opaque) {
-    LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mFbo);
+    LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo);
 
     glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &mPreviousFbo);
-    glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo);
 
     OpenGLRenderer::prepare(opaque);
 }
@@ -39,33 +39,33 @@
     OpenGLRenderer::finish();
     glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFbo);
 
-    LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mFbo);
+    LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->mFbo);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // Static functions
 ///////////////////////////////////////////////////////////////////////////////
 
-GLuint LayerRenderer::createLayer(uint32_t width, uint32_t height,
-        uint32_t* layerWidth, uint32_t* layerHeight, GLuint* texture) {
+Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
     LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height);
 
+    Layer* layer = new Layer(width, height);
+
     GLuint previousFbo;
     glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
 
-    GLuint fbo = 0;
-    glGenFramebuffers(1, &fbo);
-    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glGenFramebuffers(1, &layer->fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
 
     if (glGetError() != GL_NO_ERROR) {
         glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-        glDeleteBuffers(1, &fbo);
+        glDeleteBuffers(1, &layer->fbo);
         return 0;
     }
 
     glActiveTexture(GL_TEXTURE0);
-    glGenTextures(1, texture);
-    glBindTexture(GL_TEXTURE_2D, *texture);
+    glGenTextures(1, &layer->texture);
+    glBindTexture(GL_TEXTURE_2D, layer->texture);
 
     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
@@ -80,66 +80,81 @@
 
     if (glGetError() != GL_NO_ERROR) {
         glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-        glDeleteBuffers(1, &fbo);
-        glDeleteTextures(1, texture);
+        glDeleteBuffers(1, &layer->fbo);
+        glDeleteTextures(1, &layer->texture);
+        delete layer;
         return 0;
     }
 
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-                *texture, 0);
+            layer->texture, 0);
 
     if (glGetError() != GL_NO_ERROR) {
         glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-        glDeleteBuffers(1, &fbo);
-        glDeleteTextures(1, texture);
+        glDeleteBuffers(1, &layer->fbo);
+        glDeleteTextures(1, &layer->texture);
+        delete layer;
         return 0;
     }
 
     glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
 
-    *layerWidth = width;
-    *layerHeight = height;
+    layer->layer.set(0.0f, 0.0f, width, height);
+    layer->texCoords.set(0.0f, 1.0f, 1.0f, 0.0f);
+    layer->alpha = 255;
+    layer->mode = SkXfermode::kSrcOver_Mode;
+    layer->blend = !isOpaque;
+    layer->empty = false;
+    layer->colorFilter = NULL;
 
-    return fbo;
+    return layer;
 }
 
-void LayerRenderer::resizeLayer(GLuint fbo, GLuint texture, uint32_t width, uint32_t height,
-        uint32_t* layerWidth, uint32_t* layerHeight) {
-    LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", fbo, width, height);
+bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
+    if (layer) {
+        LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->fbo, width, height);
 
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, texture);
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, layer->texture);
 
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
-            GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
+                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
 
-    if (glGetError() != GL_NO_ERROR) {
-        glDeleteBuffers(1, &fbo);
-        glDeleteTextures(1, &texture);
+        if (glGetError() != GL_NO_ERROR) {
+            glDeleteBuffers(1, &layer->fbo);
+            glDeleteTextures(1, &layer->texture);
 
-        *layerWidth = 0;
-        *layerHeight = 0;
+            layer->width = 0;
+            layer->height = 0;
+            layer->fbo = 0;
+            layer->texture = 0;
 
-        return;
+            return false;
+        }
+
+        layer->width = width;
+        layer->height = height;
     }
-
-    *layerWidth = width;
-    *layerHeight = height;
+    return true;
 }
 
-void LayerRenderer::destroyLayer(GLuint fbo, GLuint texture) {
-    LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", fbo);
+void LayerRenderer::destroyLayer(Layer* layer) {
+    if (layer) {
+        LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo);
 
-    if (fbo) glDeleteFramebuffers(1, &fbo);
-    if (texture) glDeleteTextures(1, &texture);
+        if (layer->fbo) glDeleteFramebuffers(1, &layer->fbo);
+        if (layer->texture) glDeleteTextures(1, &layer->texture);
+
+        delete layer;
+    }
 }
 
-void LayerRenderer::destroyLayerDeferred(GLuint fbo, GLuint texture) {
-    LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", fbo);
+void LayerRenderer::destroyLayerDeferred(Layer* layer) {
+    if (layer) {
+        LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->fbo);
 
-    Caches& caches = Caches::getInstance();
-    if (fbo) caches.deleteFboDeferred(fbo);
-    if (texture) caches.deleteTextureDeferred(texture);
+        Caches::getInstance().deleteLayerDeferred(layer);
+    }
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index be68412..ed5d960 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -18,6 +18,7 @@
 #define ANDROID_HWUI_LAYER_RENDERER_H
 
 #include "OpenGLRenderer.h"
+#include "Layer.h"
 
 namespace android {
 namespace uirenderer {
@@ -39,7 +40,7 @@
 
 class LayerRenderer: public OpenGLRenderer {
 public:
-    LayerRenderer(GLuint fbo): mFbo(fbo) {
+    LayerRenderer(Layer* layer): mLayer(layer) {
     }
 
     ~LayerRenderer() {
@@ -48,15 +49,13 @@
     void prepare(bool opaque);
     void finish();
 
-    static GLuint createLayer(uint32_t width, uint32_t height,
-            uint32_t* layerWidth, uint32_t* layerHeight, GLuint* texture);
-    static void resizeLayer(GLuint fbo, GLuint texture, uint32_t width, uint32_t height,
-            uint32_t* layerWidth, uint32_t* layerHeight);
-    static void destroyLayer(GLuint fbo, GLuint texture);
-    static void destroyLayerDeferred(GLuint fbo, GLuint texture);
+    static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false);
+    static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
+    static void destroyLayer(Layer* layer);
+    static void destroyLayerDeferred(Layer* layer);
 
 private:
-    GLuint mFbo;
+    Layer* mLayer;
     GLuint mPreviousFbo;
 
 }; // class LayerRenderer
diff --git a/libs/hwui/OpenGLDebugRenderer.cpp b/libs/hwui/OpenGLDebugRenderer.cpp
index 1cf3d20..f71e5d6 100644
--- a/libs/hwui/OpenGLDebugRenderer.cpp
+++ b/libs/hwui/OpenGLDebugRenderer.cpp
@@ -54,6 +54,12 @@
     OpenGLRenderer::drawDisplayList(displayList);
 }
 
+void OpenGLDebugRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
+    mPrimitivesCount++;
+    StopWatch w("drawLayer");
+    OpenGLRenderer::drawLayer(layer, x, y, paint);
+}
+
 void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
         SkPaint* paint) {
     mPrimitivesCount++;
diff --git a/libs/hwui/OpenGLDebugRenderer.h b/libs/hwui/OpenGLDebugRenderer.h
index ee34d73..1cef267 100644
--- a/libs/hwui/OpenGLDebugRenderer.h
+++ b/libs/hwui/OpenGLDebugRenderer.h
@@ -41,6 +41,7 @@
             SkPaint* p, int flags);
 
     void drawDisplayList(DisplayList* displayList);
+    void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 9beb227..7f7deec 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -622,10 +622,12 @@
         setupDraw();
         setupDrawWithTexture();
         setupDrawColor(alpha, alpha, alpha, alpha);
+        setupDrawColorFilter();
         setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false);
         setupDrawProgram();
         setupDrawDirtyRegionsDisabled();
         setupDrawPureColorUniforms();
+        setupDrawColorFilterUniforms();
         setupDrawTexture(layer->texture);
         setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom);
         setupDrawMesh(&mesh[0].position[0], &mesh[0].texture[0]);
@@ -1485,28 +1487,22 @@
     finishDrawTexture();
 }
 
-void OpenGLRenderer::drawLayer(int texture, float left, float top, float right, float bottom,
-        float u, float v, SkPaint* paint) {
-    if (quickReject(left, top, right, bottom)) {
+void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
+    if (!layer || quickReject(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight())) {
         return;
     }
 
     glActiveTexture(gTextureUnits[0]);
-    if (!texture) return;
-
-    mCaches.unbindMeshBuffer();
-    resetDrawTextureTexCoords(0.0f, v, u, 0.0f);
 
     int alpha;
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
 
-    // TODO: Should get the blend info from the caller
-    drawTextureMesh(left, top, right, bottom, texture, alpha / 255.0f, mode, true,
-            &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
-            GL_TRIANGLE_STRIP, gMeshCount);
+    layer->alpha = alpha;
+    layer->mode = mode;
 
-    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
+    const Rect r(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight());
+    composeLayerRect(layer, r);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 5f45915..da27dac 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -95,8 +95,7 @@
     virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
 
     virtual void drawDisplayList(DisplayList* displayList);
-    virtual void drawLayer(int texture, float left, float top, float right, float bottom,
-            float u, float v, SkPaint* paint);
+    virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
@@ -133,6 +132,19 @@
      */
     virtual void composeLayer(sp<Snapshot> current, sp<Snapshot> previous);
 
+    /**
+     * Mark the layer as dirty at the specified coordinates. The coordinates
+     * are transformed with the supplied matrix.
+     */
+    virtual void dirtyLayer(const float left, const float top,
+            const float right, const float bottom, const mat4 transform);
+
+    /**
+     * Mark the layer as dirty at the specified coordinates.
+     */
+    virtual void dirtyLayer(const float left, const float top,
+            const float right, const float bottom);
+
 private:
     /**
      * Saves the current state of the renderer as a new snapshot.
@@ -402,18 +414,6 @@
         mDirtyClip = true;
     }
 
-    /**
-     * Mark the layer as dirty at the specified coordinates. The coordinates
-     * are transformed with the supplied matrix.
-     */
-    void dirtyLayer(const float left, const float top, const float right, const float bottom,
-            const mat4 transform);
-
-    /**
-     * Mark the layer as dirty at the specified coordinates.
-     */
-    void dirtyLayer(const float left, const float top, const float right, const float bottom);
-
     // Dimensions of the drawing surface
     int mWidth, mHeight;