Fix drawing issues with layers.

Prior to this change layers would clip their content incorrectly. They would
also not apply alpha properly.

Change-Id: Id7b3aaa7dbdc51de68fe050e64458f68e40503fd
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 825de25..c13ed15 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -195,7 +195,7 @@
     static final String LOG_TAG = "TextView";
     static final boolean DEBUG_EXTRACT = false;
     
-    private static int PRIORITY = 100;
+    private static final int PRIORITY = 100;
 
     private ColorStateList mTextColor;
     private int mCurTextColor;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 0a5ff57..3440687 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -41,7 +41,7 @@
 #define DEFAULT_PATH_CACHE_SIZE 6.0f
 #define DEFAULT_PATCH_CACHE_SIZE 100
 #define DEFAULT_GRADIENT_CACHE_SIZE 0.5f
-#define DEFAULT_DROP_SHADOW_CACHE_SIZE 1.0f
+#define DEFAULT_DROP_SHADOW_CACHE_SIZE 2.0f
 
 #define REQUIRED_TEXTURE_UNITS_COUNT 3
 
@@ -251,13 +251,13 @@
         mOrthoMatrix.load(current->orthoMatrix);
     }
 
+    mSaveCount--;
+    mSnapshot = previous;
+
     if (restoreLayer) {
         composeLayer(current, previous);
     }
 
-    mSaveCount--;
-    mSnapshot = previous;
-
     if (restoreClip) {
         setScissorFromClip();
     }
@@ -287,7 +287,11 @@
         mode = SkXfermode::kSrcOver_Mode;
     }
 
-    createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags);
+    if (alpha > 0 && !mSnapshot->invisible) {
+        createLayer(mSnapshot, left, top, right, bottom, alpha, mode, flags);
+    } else {
+        mSnapshot->invisible = true;
+    }
 
     return count;
 }
@@ -295,7 +299,11 @@
 int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
         int alpha, int flags) {
     int count = saveSnapshot();
-    createLayer(mSnapshot, left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags);
+    if (alpha > 0 && !mSnapshot->invisible) {
+        createLayer(mSnapshot, left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags);
+    } else {
+        mSnapshot->invisible = true;
+    }
     return count;
 }
 
@@ -328,7 +336,6 @@
     snapshot->flags |= Snapshot::kFlagIsLayer;
     snapshot->layer = layer;
     snapshot->fbo = layer->fbo;
-
     snapshot->transform.loadTranslate(-left, -top, 0.0f);
     snapshot->setClip(0.0f, 0.0f, right - left, bottom - top);
     snapshot->viewport.set(0.0f, 0.0f, right - left, bottom - top);
@@ -340,8 +347,7 @@
 
     // Change the ortho projection
     glViewport(0, 0, right - left, bottom - top);
-    // Don't flip the FBO, it will get flipped when drawing back to the framebuffer
-    mOrthoMatrix.loadOrtho(0.0f, right - left, 0.0f, bottom - top, -1.0f, 1.0f);
+    mOrthoMatrix.loadOrtho(0.0f, right - left, bottom - top, 0.0f, -1.0f, 1.0f);
 
     return true;
 }
@@ -363,9 +369,14 @@
     Layer* layer = current->layer;
     const Rect& rect = layer->layer;
 
+    // FBOs are already drawn with a top-left origin, don't flip the texture
+    resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
+
     drawTextureRect(rect.left, rect.top, rect.right, rect.bottom,
             layer->texture, layer->alpha, layer->mode, layer->blend);
 
+    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
+
     LayerSize size(rect.getWidth(), rect.getHeight());
     // Failing to add the layer to the cache should happen only if the
     // layer is too large
@@ -422,6 +433,8 @@
 }
 
 bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
+    if (mSnapshot->invisible) return true;
+
     Rect r(left, top, right, bottom);
     mSnapshot->transform.mapRect(r);
     return !mSnapshot->clipRect.intersects(r);
@@ -527,6 +540,7 @@
 }
 
 void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
+    if (mSnapshot->invisible) return;
     const Rect& clip = mSnapshot->clipRect;
     drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
 }
@@ -556,7 +570,8 @@
 
 void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
         float x, float y, SkPaint* paint) {
-    if (text == NULL || count == 0 || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) {
+    if (mSnapshot->invisible || text == NULL || count == 0 ||
+            (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) {
         return;
     }
 
@@ -614,6 +629,8 @@
 }
 
 void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
+    if (mSnapshot->invisible) return;
+
     GLuint textureUnit = 0;
     glActiveTexture(gTextureUnits[textureUnit]);
 
@@ -621,6 +638,13 @@
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
 
+    const float x = texture->left - texture->offset;
+    const float y = texture->top - texture->offset;
+
+    if (quickReject(x, y, x + texture->width, y + texture->height)) {
+        return;
+    }
+
     int alpha;
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
@@ -631,9 +655,6 @@
     const GLfloat g = a * ((color >>  8) & 0xFF) / 255.0f;
     const GLfloat b = a * ((color      ) & 0xFF) / 255.0f;
 
-    const float x = texture->left - texture->offset;
-    const float y = texture->top - texture->offset;
-
     setupTextureAlpha8(texture, textureUnit, x, y, r, g, b, a, mode, true, true);
 
     // Draw the mesh
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 21b2bef..97e7cae 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -42,7 +42,7 @@
  */
 class Snapshot: public LightRefBase<Snapshot> {
 public:
-    Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0) { }
+    Snapshot(): invisible(false), flags(0), previous(NULL), layer(NULL), fbo(0) { }
 
     /**
      * Copies the specified snapshot. Only the transform and clip rectangle
@@ -54,6 +54,7 @@
             height(s->height),
             transform(s->transform),
             clipRect(s->clipRect),
+            invisible(s->invisible),
             flags(0),
             previous(s),
             layer(NULL),
@@ -165,6 +166,11 @@
     Rect clipRect;
 
     /**
+     * If true, the layer won't be rendered.
+     */
+    bool invisible;
+
+    /**
      * Dirty flags.
      */
     int flags;