hwc: Reset layer-to-rotator map and fences on configuration failure

When a rotator or mdp configuration for a display fails, reset the
layer-to-rotator mappings for that display and reset the release
fences for the rotator objects used for that display.

Note: The rotator itself is offline and not tied to any mixer. It is
from the mappings that we deduce which rotator object was used for
layers of which display. Also we don't delete rotator objects held
for a specific display, since during stability runs, failures could
repeat each round and we end up allocating and deallocating memory
unnecessarily. The rotator objects will be deleted automatically
when not required anymore.

Change-Id: I9a67f02574be30be3b96b3575f60530cb1c89e10
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index ce18695..dde4815 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -168,6 +168,8 @@
                 sourceCrop, mdpFlags, rotFlags);
         if(!ret) {
             ALOGE("%s: preRotate for external Failed!", __FUNCTION__);
+            ctx->mOverlay->clear(mDpy);
+            ctx->mLayerRotMap[mDpy]->clear();
             return false;
         }
         //For the mdp, since either we are pre-rotating or MDP does flips
@@ -182,6 +184,7 @@
         if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
                     NULL, mDest) < 0) {
             ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy);
+            ctx->mLayerRotMap[mDpy]->clear();
             ret = false;
         }
     }
@@ -353,6 +356,9 @@
             ALOGE("%s: commit fails for right", __FUNCTION__);
             ret = false;
         }
+        if(ret == false) {
+            ctx->mLayerRotMap[mDpy]->clear();
+        }
     }
     return ret;
 }
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 1167f3a..29c2fb3 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -1517,6 +1517,7 @@
         if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
             ctx->mOverlay->clear(dpy);
+            ctx->mLayerRotMap[dpy]->clear();
             return -1;
         }
         ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1534,6 +1535,7 @@
 
     if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
         ALOGE("%s: commit failed for low res panel", __FUNCTION__);
+        ctx->mLayerRotMap[dpy]->clear();
         return -1;
     }
     return 0;
@@ -1643,6 +1645,7 @@
         if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
             ctx->mOverlay->clear(dpy);
+            ctx->mLayerRotMap[dpy]->clear();
             return -1;
         }
         ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1708,6 +1711,7 @@
         if(configMdp(ctx->mOverlay, pargL, orient,
                 tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
             ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
+            ctx->mLayerRotMap[dpy]->clear();
             return -1;
         }
     }
@@ -1723,6 +1727,7 @@
         if(configMdp(ctx->mOverlay, pargR, orient,
                 tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
             ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
+            ctx->mLayerRotMap[dpy]->clear();
             return -1;
         }
     }
@@ -1947,6 +1952,21 @@
     mCount = 0;
 }
 
+void LayerRotMap::clear() {
+    for (uint32_t i = 0; i < mCount; i++) {
+        //mCount represents rotator objects for just this display.
+        //We could have popped mCount topmost objects from mRotMgr, but if each
+        //round has the same failure, typical of stability runs, it would lead
+        //to unnecessary memory allocation, deallocation each time. So we let
+        //the rotator objects be around, but just knock off the fences they
+        //hold. Ultimately the rotator objects will be GCed when not required.
+        //Also resetting fences is required if at least one rotation round has
+        //succeeded before. It'll be a NOP otherwise.
+        mRot[i]->resetReleaseFd();
+    }
+    reset();
+}
+
 void LayerRotMap::setReleaseFd(const int& fence) {
     for(uint32_t i = 0; i < mCount; i++) {
         mRot[i]->setReleaseFd(dup(fence));
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 29b38fc..2503e43 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -142,7 +142,11 @@
     LayerRotMap() { reset(); }
     enum { MAX_SESS = 3 };
     void add(hwc_layer_1_t* layer, overlay::Rotator *rot);
+    //Resets the mapping of layer to rotator
     void reset();
+    //Clears mappings and existing rotator fences
+    //Intended to be used during errors
+    void clear();
     uint32_t getCount() const;
     hwc_layer_1_t* getLayer(uint32_t index) const;
     overlay::Rotator* getRot(uint32_t index) const;
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index 7b3dda1..4b6a8bc 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -107,6 +107,12 @@
     mRelFence[mCurrOffset] = fence;
 }
 
+void RotMem::Mem::resetReleaseFd() {
+    //Will wait for previous offline rotation to finish, close fence fd
+    //and reset
+    setReleaseFd(-1);
+}
+
 //============RotMgr=========================
 
 RotMgr::RotMgr() {
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 7c1095f..6bb94a6 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -56,6 +56,7 @@
         bool close() { return m.close(); }
         uint32_t size() const { return m.bufSz(); }
         void setReleaseFd(const int& fence);
+        void resetReleaseFd();
         // Max rotator buffers
         enum { ROT_NUM_BUFS = 2 };
         // rotator data info dst offset
@@ -72,6 +73,7 @@
     Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; }
     RotMem& operator++() { ++_curr; return *this; }
     void setReleaseFd(const int& fence) { curr().setReleaseFd(fence); }
+    void resetReleaseFd() { curr().resetReleaseFd(); }
     bool close();
     uint32_t _curr;
     Mem m[MAX_ROT_MEM];
@@ -96,6 +98,7 @@
     virtual void dump() const = 0;
     virtual void getDump(char *buf, size_t len) const = 0;
     void setReleaseFd(const int& fence) { mMem.setReleaseFd(fence); }
+    void resetReleaseFd() { mMem.resetReleaseFd(); }
     static Rotator *getRotator();
 
 protected: