hwc: Update rotator object handling in error cases
Earlier, on configuration errors, we simply drained the fences held
by current rotator objects and went to GPU comp. The rotator objects
were deleted in the subsequent rounds, if they remained unused.
If we don't use GPU comp on failure but use other strategies, then we
need to mark the rotator objects for a display for reuse, so that
other strategies can use them.
Also any failure resets on overlay or rotator need to happen from
functions that call configuration helpers rather than the helper
themselves. Leaving cleanup to black-box helpers is not desirable.
Change-Id: I59b5b1bb774b82ee85a037e934c9d2d023db30af
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index baef9d2..a290225 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -1317,6 +1317,7 @@
if(!programMDP(ctx, list)) {
reset(numLayers, list);
ctx->mOverlay->clear(mDpy);
+ ctx->mLayerRotMap[mDpy]->clear();
ret = -1;
goto exit;
} else { //Success
@@ -1348,6 +1349,7 @@
if(!programMDP(ctx, list)) {
reset(numLayers, list);
ctx->mOverlay->clear(mDpy);
+ ctx->mLayerRotMap[mDpy]->clear();
ret = -1;
goto exit;
}
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index f0ba2e6..472fe59 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -134,7 +134,7 @@
ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
overlay::Overlay::initOverlay();
ctx->mOverlay = overlay::Overlay::getInstance();
- ctx->mRotMgr = new RotMgr();
+ ctx->mRotMgr = RotMgr::getInstance();
//Is created and destroyed only once for primary
//For external it could get created and destroyed multiple times depending
@@ -1540,8 +1540,6 @@
//Configure rotator for pre-rotation
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);
@@ -1559,7 +1557,6 @@
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;
@@ -1668,8 +1665,6 @@
//Configure rotator for pre-rotation
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);
@@ -1737,7 +1732,6 @@
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;
}
}
@@ -1753,7 +1747,6 @@
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;
}
}
@@ -1800,7 +1793,6 @@
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
- ctx->mOverlay->clear(dpy);
return -1;
}
ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1979,17 +1971,7 @@
}
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();
- }
+ RotMgr::getInstance()->markUnusedTop(mCount);
reset();
}
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index 4b6a8bc..d912dc7 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -107,13 +107,15 @@
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::sRotMgr = NULL;
+
+RotMgr* RotMgr::getInstance() {
+ if(sRotMgr == NULL) {
+ sRotMgr = new RotMgr();
+ }
+ return sRotMgr;
+}
RotMgr::RotMgr() {
for(int i = 0; i < MAX_ROT_SESS; i++) {
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 6bb94a6..2bbfb91 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -56,7 +56,6 @@
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
@@ -73,7 +72,6 @@
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];
@@ -98,7 +96,6 @@
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:
@@ -230,21 +227,29 @@
//Maximum sessions based on VG pipes, since rotator is used only for videos.
//Even though we can have 4 mixer stages, that much may be unnecessary.
enum { MAX_ROT_SESS = 3 };
- RotMgr();
+
~RotMgr();
void configBegin();
void configDone();
overlay::Rotator *getNext();
void clear(); //Removes all instances
+ //Resets the usage of top count objects, making them available for reuse
+ void markUnusedTop(const uint32_t& count) { mUseCount -= count; }
/* Returns rot dump.
* Expects a NULL terminated buffer of big enough size.
*/
void getDump(char *buf, size_t len);
int getRotDevFd();
int getNumActiveSessions() { return mUseCount; }
+
+ static RotMgr *getInstance();
+
private:
+ RotMgr();
+ static RotMgr *sRotMgr;
+
overlay::Rotator *mRot[MAX_ROT_SESS];
- int mUseCount;
+ uint32_t mUseCount;
int mRotDevFd;
};