Perform early intersect to avoid unnecessary draws

Change-Id: I48d61c4488e622f93733d8e53a50c93e6a20166d
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 7054851..ec95863 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -910,8 +910,6 @@
             if (canDraw()) {
                 if (!hasDirtyRegions()) {
                     dirty = null;
-                } else if (dirty != null) {
-                    dirty.intersect(0, 0, mWidth, mHeight);
                 }
                 attachInfo.mIgnoreDirtyState = true;
                 attachInfo.mDrawingTime = SystemClock.uptimeMillis();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 28737fc..f831d85f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -771,19 +771,29 @@
         return mLayoutRequested;
     }
 
+    void invalidate() {
+        mDirty.set(0, 0, mWidth, mHeight);
+        scheduleTraversals();
+    }
+
     public void invalidateChild(View child, Rect dirty) {
+        invalidateChildInParent(null, dirty);
+    }
+
+    public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
         checkThread();
         if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty);
+
         if (dirty == null) {
-            // Fast invalidation for GL-enabled applications; GL must redraw everything
             invalidate();
-            return;
+            return null;
         }
+
         if (mCurScrollY != 0 || mTranslator != null) {
             mTempRect.set(dirty);
             dirty = mTempRect;
             if (mCurScrollY != 0) {
-               dirty.offset(0, -mCurScrollY);
+                dirty.offset(0, -mCurScrollY);
             }
             if (mTranslator != null) {
                 mTranslator.translateRectInAppWindowToScreen(dirty);
@@ -792,19 +802,24 @@
                 dirty.inset(-1, -1);
             }
         }
-        if (!mDirty.isEmpty() && !mDirty.contains(dirty)) {
+
+        final Rect localDirty = mDirty;
+        if (!localDirty.isEmpty() && !localDirty.contains(dirty)) {
             mAttachInfo.mSetIgnoreDirtyState = true;
             mAttachInfo.mIgnoreDirtyState = true;
         }
-        mDirty.union(dirty);
+
+        // Add the new dirty rect to the current one
+        localDirty.union(dirty.left, dirty.top, dirty.right, dirty.bottom);
+        // Intersect with the bounds of the window to skip
+        // updates that lie outside of the visible region
+        localDirty.intersect(0, 0, mWidth, mHeight);
+
         if (!mWillDrawSoon) {
             scheduleTraversals();
         }
-    }
-    
-    void invalidate() {
-        mDirty.set(0, 0, mWidth, mHeight);
-        scheduleTraversals();
+
+        return null;
     }
 
     void setStopped(boolean stopped) {
@@ -815,13 +830,8 @@
             }
         }
     }
-    
-    public ViewParent getParent() {
-        return null;
-    }
 
-    public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {
-        invalidateChild(null, dirty);
+    public ViewParent getParent() {
         return null;
     }
 
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 0ada1fb..ec911b0 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -352,8 +352,7 @@
                // check for empty first
         return this.left < this.right && this.top < this.bottom
                // now check for containment
-               && left <= r.left && top <= r.top
-               && right >= r.right && bottom >= r.bottom;
+               && left <= r.left && top <= r.top && right >= r.right && bottom >= r.bottom;
     }
 
     /**
@@ -375,20 +374,11 @@
      *              return false and do not change this rectangle.
      */
     public boolean intersect(int left, int top, int right, int bottom) {
-        if (this.left < right && left < this.right
-                && this.top < bottom && top < this.bottom) {
-            if (this.left < left) {
-                this.left = left;
-            }
-            if (this.top < top) {
-                this.top = top;
-            }
-            if (this.right > right) {
-                this.right = right;
-            }
-            if (this.bottom > bottom) {
-                this.bottom = bottom;
-            }
+        if (this.left < right && left < this.right && this.top < bottom && top < this.bottom) {
+            if (this.left < left) this.left = left;
+            if (this.top < top) this.top = top;
+            if (this.right > right) this.right = right;
+            if (this.bottom > bottom) this.bottom = bottom;
             return true;
         }
         return false;
@@ -422,8 +412,7 @@
      *              false and do not change this rectangle.
      */
     public boolean setIntersect(Rect a, Rect b) {
-        if (a.left < b.right && b.left < a.right
-                && a.top < b.bottom && b.top < a.bottom) {
+        if (a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom) {
             left = Math.max(a.left, b.left);
             top = Math.max(a.top, b.top);
             right = Math.min(a.right, b.right);
@@ -448,8 +437,7 @@
      *              no event is this rectangle modified.
      */
     public boolean intersects(int left, int top, int right, int bottom) {
-        return this.left < right && left < this.right
-               && this.top < bottom && top < this.bottom;
+        return this.left < right && left < this.right && this.top < bottom && top < this.bottom;
     }
 
     /**
@@ -463,8 +451,7 @@
      *              either of the rectangles modified.
      */
     public static boolean intersects(Rect a, Rect b) {
-        return a.left < b.right && b.left < a.right
-               && a.top < b.bottom && b.top < a.bottom;
+        return a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom;
     }
 
     /**
@@ -480,14 +467,10 @@
     public void union(int left, int top, int right, int bottom) {
         if ((left < right) && (top < bottom)) {
             if ((this.left < this.right) && (this.top < this.bottom)) {
-                if (this.left > left)
-                    this.left = left;
-                if (this.top > top)
-                    this.top = top;
-                if (this.right < right)
-                    this.right = right;
-                if (this.bottom < bottom)
-                    this.bottom = bottom;
+                if (this.left > left) this.left = left;
+                if (this.top > top) this.top = top;
+                if (this.right < right) this.right = right;
+                if (this.bottom < bottom) this.bottom = bottom;
             } else {
                 this.left = left;
                 this.top = top;