mDirtyRegion is single threaded, but could be accessed from a hwc thread

We now have mInvalidateRegion which holds the region to invalidate, it
can be set from any thread as long as mInvalidateLock is held. We use
fine-grained locking here because mInvalidateRegion can be set from anywhere,
in particular frmo HWC callbacks.

Bug: 5466774
Change-Id: Iafca20aa3f5b25a87755e65bde7b769aa8f997bc
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4b2866c..ba8f630 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -788,6 +788,8 @@
         }
 
     unlockPageFlip(currentLayers);
+
+    mDirtyRegion.orSelf(getAndClearInvalidateRegion());
     mDirtyRegion.andSelf(screenRegion);
 }
 
@@ -1798,12 +1800,24 @@
 }
 
 void SurfaceFlinger::repaintEverything() {
-    Mutex::Autolock _l(mStateLock);
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
-    mDirtyRegion.set(hw.bounds());
+    const Rect bounds(hw.getBounds());
+    setInvalidateRegion(Region(bounds));
     signalEvent();
 }
 
+void SurfaceFlinger::setInvalidateRegion(const Region& reg) {
+    Mutex::Autolock _l(mInvalidateLock);
+    mInvalidateRegion = reg;
+}
+
+Region SurfaceFlinger::getAndClearInvalidateRegion() {
+    Mutex::Autolock _l(mInvalidateLock);
+    Region reg(mInvalidateRegion);
+    mInvalidateRegion.clear();
+    return reg;
+}
+
 // ---------------------------------------------------------------------------
 
 status_t SurfaceFlinger::renderScreenToTexture(DisplayID dpy,