the visible region sent to HWC was garbage

we used to have a visibleRegion object per layer, but now
it's per screen; so at somepoint the code got changed to
calculate the per-screen visible region on the stack and that's
what got passed to HWC.

we're now setting the visibleRegionScreen at each frame and
freeing at after the HWC set() call. We use the underlaying
SharedBuffer so that in most cases we don't have to allocate,
free or copy memory around.

Bug: 7089478
Change-Id: I24fa556c76613a225d9fe7a6c6b727bb476144d8
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 283d149..23290e3 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -573,9 +573,12 @@
         reinterpret_cast<Rect&>(getLayer()->sourceCrop) = crop;
     }
     virtual void setVisibleRegionScreen(const Region& reg) {
-        getLayer()->visibleRegionScreen.rects =
-                reinterpret_cast<hwc_rect_t const *>(
-                        reg.getArray(&getLayer()->visibleRegionScreen.numRects));
+        // Region::getSharedBuffer creates a reference to the underlying
+        // SharedBuffer of this Region, this reference is freed
+        // in onDisplayed()
+        hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
+        SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects);
+        visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
     }
     virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
         if (buffer == 0 || buffer->handle == 0) {
@@ -586,6 +589,16 @@
             getLayer()->handle = buffer->handle;
         }
     }
+    virtual void onDisplayed() {
+        hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
+        SharedBuffer const* sb = SharedBuffer::bufferFromData(visibleRegion.rects);
+        if (sb) {
+            sb->release();
+            // not technically needed but safer
+            visibleRegion.numRects = 0;
+            visibleRegion.rects = NULL;
+        }
+    }
 };
 
 /*
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 8852ab6..a49a023 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -130,6 +130,7 @@
         virtual void setVisibleRegionScreen(const Region& reg) = 0;
         virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
         virtual void setAcquireFenceFd(int fenceFd) = 0;
+        virtual void onDisplayed() = 0;
     };
 
     /*