Optimize calls to glCopyTexImage2D().

Change-Id: I34ee87bd4472864f440916e03a2894fae24bbe4a
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 7cf70f7..de27090 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -309,17 +309,12 @@
     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left, mHeight - bounds.bottom,
             bounds.getWidth(), bounds.getHeight(), 0);
 
-    // Clear the framebuffer where the layer will draw
-    glScissor(bounds.left, mHeight - bounds.bottom, bounds.getWidth(), bounds.getHeight());
-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-    glClear(GL_COLOR_BUFFER_BIT);
-
     if (flags & SkCanvas::kClipToLayer_SaveFlag) {
-        mSnapshot->clipTransformed(bounds);
+        if (mSnapshot->clipTransformed(bounds)) setScissorFromClip();
     }
 
-    // Restore the initial clip
-    setScissorFromClip();
+    // Enqueue the buffer coordinates to clear the corresponding region later
+    mLayers.push(new Rect(bounds));
 
     return true;
 }
@@ -371,6 +366,26 @@
     }
 }
 
+void OpenGLRenderer::clearLayerRegions() {
+    if (mLayers.size() == 0) return;
+
+    for (uint32_t i = 0; i < mLayers.size(); i++) {
+        Rect* bounds = mLayers.itemAt(i);
+
+        // Clear the framebuffer where the layer will draw
+        glScissor(bounds->left, mHeight - bounds->bottom,
+                bounds->getWidth(), bounds->getHeight());
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        delete bounds;
+    }
+    mLayers.clear();
+
+    // Restore the clip
+    setScissorFromClip();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Transforms
 ///////////////////////////////////////////////////////////////////////////////
@@ -612,6 +627,7 @@
             mode, false, true);
 
     const Rect& clip = mSnapshot->getLocalClip();
+    clearLayerRegions();
     fontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y);
 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@@ -651,6 +667,8 @@
 
     setupTextureAlpha8(texture, textureUnit, x, y, r, g, b, a, mode, true, true);
 
+    clearLayerRegions();
+
     // Draw the mesh
     glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
     glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
@@ -836,6 +854,8 @@
 
 void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
         int color, SkXfermode::Mode mode, bool ignoreTransform, bool ignoreBlending) {
+    clearLayerRegions();
+
     // If a shader is set, preserve only the alpha
     if (mShader) {
         color |= 0x00ffffff;
@@ -914,6 +934,8 @@
         GLuint texture, float alpha, SkXfermode::Mode mode, bool blend,
         GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount,
         bool swapSrcDst, bool ignoreTransform) {
+    clearLayerRegions();
+
     ProgramDescription description;
     description.hasTexture = true;
     if (mColorFilter) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index e7f933f..12ec276 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -29,6 +29,7 @@
 
 #include <utils/RefBase.h>
 #include <utils/ResourceTypes.h>
+#include <utils/Vector.h>
 
 #include "Extensions.h"
 #include "Matrix.h"
@@ -156,6 +157,12 @@
             int alpha, SkXfermode::Mode mode, int flags);
 
     /**
+     * Clears all the regions corresponding to the current list of layers.
+     * This method MUST be invoked before any drawing operation.
+     */
+    void clearLayerRegions();
+
+    /**
      * Draws a colored rectangle with the specified color. The specified coordinates
      * are transformed by the current snapshot's transform matrix.
      *
@@ -385,6 +392,10 @@
 
     // Various caches
     Caches& mCaches;
+
+    // List of rectangles to clear due to calls to saveLayer()
+    Vector<Rect*> mLayers;
+
 }; // class OpenGLRenderer
 
 }; // namespace uirenderer
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
index 83d16a5..f47b00f 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
@@ -87,7 +87,7 @@
         ListView list = (ListView) findViewById(R.id.list);
         list.setAdapter(adapter);
         list.setCacheColorHint(0);
-        
+
         registerForContextMenu(list);
     }