Better handle op size edge cases

bug:9464358

Previously, empty and unknown sized ops are assumed to fully cover
their clip. This is now corrected such that empty sized ops are
pre-rejected before defer. Additionally, unknown sized ops disable
overdraw avoidance.

Change-Id: Icf2ce24f98be5ea6299e24ffcf826790373564a1
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index f19d610..b3d2aec 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -470,6 +470,7 @@
     deferInfo.mergeable &= !recordingComplexClip();
 
     if (CC_LIKELY(mAvoidOverdraw) && mBatches.size() &&
+            op->state.mClipSideFlags != kClipSide_ConservativeFull &&
             deferInfo.opaqueOverBounds && op->state.mBounds.contains(mBounds)) {
         // avoid overdraw by resetting drawing state + discarding drawing ops
         discardDrawingBatches(mBatches.size() - 1);
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 290e4fa..6b7bac0 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -129,7 +129,10 @@
             return;
         }
 
-        if (!getLocalBounds(state.mBounds)) {
+        if (getLocalBounds(state.mBounds)) {
+            // valid empty bounds, don't bother deferring
+            if (state.mBounds.isEmpty()) return;
+        } else {
             // empty bounds signify bounds can't be calculated
             state.mBounds.setEmpty();
         }
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 05f43a9..ed6498f 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1395,9 +1395,9 @@
             }
             state.mBounds.set(clippedBounds);
         } else {
-            // If we don't have bounds, let's assume we're clipped
-            // to prevent merging
-            state.mClipSideFlags = kClipSide_Full;
+            // Empty bounds implies size unknown. Label op as conservatively clipped to disable
+            // overdraw avoidance (since we don't know what it overlaps)
+            state.mClipSideFlags = kClipSide_ConservativeFull;
             state.mBounds.set(currentClip);
         }
     }
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 5b7f90d..ab15879 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -86,7 +86,8 @@
     kClipSide_Top = 0x2,
     kClipSide_Right = 0x4,
     kClipSide_Bottom = 0x8,
-    kClipSide_Full = 0xF
+    kClipSide_Full = 0xF,
+    kClipSide_ConservativeFull = 0x1F
 };
 
 struct DeferredDisplayState {