Disable shadow overdraw avoidance in the inverse clip case

The caster is effectivly transparent, so skip the optimization just as
is done for alpha < 1.0

Change-Id: I3d294222adf0137e20c1fb5808313d487e92e0a8
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 9e367fc..239a5bc 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1548,14 +1548,16 @@
 };
 
 /**
- * Not a canvas operation, used only by 3d / z ordering logic in DisplayList::iterate()
+ * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
  */
 class DrawShadowOp : public DrawOp {
 public:
-    DrawShadowOp(const mat4& transformXY, const mat4& transformZ, float alpha,
+    DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
+            float casterAlpha, bool casterUnclipped,
             float fallbackWidth, float fallbackHeight,
             const SkPath* outline, const SkPath* revealClip)
-            : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ), mAlpha(alpha),
+            : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ),
+            mCasterAlpha(casterAlpha), mCasterUnclipped(casterUnclipped),
             mFallbackWidth(fallbackWidth), mFallbackHeight(fallbackHeight),
             mOutline(outline), mRevealClip(revealClip) {}
 
@@ -1572,7 +1574,8 @@
             Op(casterPerimeter, *mRevealClip, kIntersect_PathOp, &casterPerimeter);
         }
 
-        return renderer.drawShadow(mTransformXY, mTransformZ, mAlpha, &casterPerimeter);
+        return renderer.drawShadow(mTransformXY, mTransformZ,
+                mCasterAlpha, mCasterUnclipped, &casterPerimeter);
     }
 
     virtual void output(int level, uint32_t logFlags) const {
@@ -1584,7 +1587,8 @@
 private:
     const mat4 mTransformXY;
     const mat4 mTransformZ;
-    const float mAlpha;
+    const float mCasterAlpha;
+    const bool mCasterUnclipped;
     const float mFallbackWidth;
     const float mFallbackHeight;
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index d808735..619f331 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -3203,7 +3203,7 @@
 }
 
 status_t OpenGLRenderer::drawShadow(const mat4& casterTransformXY, const mat4& casterTransformZ,
-        float casterAlpha, const SkPath* casterPerimeter) {
+        float casterAlpha, bool casterUnclipped, const SkPath* casterPerimeter) {
     if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
 
     // TODO: use quickRejectWithScissor. For now, always force enable scissor.
@@ -3260,7 +3260,7 @@
     Rect casterBounds(casterPerimeter->getBounds());
     casterTransformXY.mapRect(casterBounds);
 
-    bool isCasterOpaque = (casterAlpha == 1.0f);
+    bool isCasterOpaque = (casterAlpha == 1.0f) && casterUnclipped;
     // draw caster's shadows
     if (mCaches.propertyAmbientShadowStrength > 0) {
         paint.setARGB(casterAlpha * mCaches.propertyAmbientShadowStrength, 0, 0, 0);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 054767e..2debd2e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -210,7 +210,7 @@
     virtual status_t drawRects(const float* rects, int count, const SkPaint* paint);
 
     status_t drawShadow(const mat4& casterTransformXY, const mat4& casterTransformZ,
-            float casterAlpha, const SkPath* casterPerimeter);
+            float casterAlpha, bool casterUnclipped, const SkPath* casterPerimeter);
 
     virtual void resetShader();
     virtual void setupShader(SkiaShader* shader);
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index e39e5ae..c24a7a1 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -416,8 +416,17 @@
                     const SkPath* revealClipPath = revealClip.hasConvexClip()
                             ?  revealClip.getPath() : NULL; // only pass the reveal clip's path if it's convex
 
+                    /**
+                     * The drawing area of the caster is always the same as the its perimeter (which
+                     * the shadow system uses) *except* in the inverse clip case. Inform the shadow
+                     * system that the caster's drawing area (as opposed to its perimeter) has been
+                     * clipped, so that it knows the caster can't be opaque.
+                     */
+                    bool casterUnclipped = !revealClip.willClip() || revealClip.hasConvexClip();
+
                     DisplayListOp* shadowOp  = new (alloc) DrawShadowOp(
-                            shadowMatrixXY, shadowMatrixZ, caster->properties().getAlpha(),
+                            shadowMatrixXY, shadowMatrixZ,
+                            caster->properties().getAlpha(), casterUnclipped,
                             caster->properties().getWidth(), caster->properties().getHeight(),
                             outlinePath, revealClipPath);
                     handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());