Merge "hwc/overlay: Implement rotator caching"
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index f3243fc..944f152 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -1324,7 +1324,9 @@
rotData.acq_fen_fd_cnt = 1; //1 ioctl call per rot session
}
int ret = 0;
- ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
+ if(not ctx->mLayerRotMap[dpy]->isRotCached(i))
+ ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
+
if(ret < 0) {
ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed for rot sync, err=%s",
__FUNCTION__, strerror(errno));
@@ -2260,9 +2262,27 @@
reset();
}
+bool LayerRotMap::isRotCached(uint32_t index) const {
+ overlay::Rotator* rot = getRot(index);
+ hwc_layer_1_t* layer = getLayer(index);
+
+ if(rot and layer and layer->handle) {
+ private_handle_t *hnd = (private_handle_t *)(layer->handle);
+ return (rot->isRotCached(hnd->fd,(uint32_t)(hnd->offset)));
+ }
+ return false;
+}
+
void LayerRotMap::setReleaseFd(const int& fence) {
for(uint32_t i = 0; i < mCount; i++) {
- mRot[i]->setReleaseFd(dup(fence));
+ if(mRot[i] and mLayer[i] and mLayer[i]->handle) {
+ /* Ensure that none of the above (Rotator-instance,
+ * layer and layer-handle) are NULL*/
+ if(isRotCached(i))
+ mRot[i]->setPrevBufReleaseFd(dup(fence));
+ else
+ mRot[i]->setCurrBufReleaseFd(dup(fence));
+ }
}
}
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index ad71919..3648ba7 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -201,6 +201,7 @@
uint32_t getCount() const;
hwc_layer_1_t* getLayer(uint32_t index) const;
overlay::Rotator* getRot(uint32_t index) const;
+ bool isRotCached(uint32_t index) const;
void setReleaseFd(const int& fence);
private:
hwc_layer_1_t* mLayer[overlay::RotMgr::MAX_ROT_SESS];
diff --git a/liboverlay/overlayMdpRot.cpp b/liboverlay/overlayMdpRot.cpp
index 6105736..d322897 100755
--- a/liboverlay/overlayMdpRot.cpp
+++ b/liboverlay/overlayMdpRot.cpp
@@ -37,10 +37,18 @@
void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = (uint8_t)r; }
+int MdpRot::getSrcMemId() const {
+ return mRotDataInfo.src.memory_id;
+}
+
int MdpRot::getDstMemId() const {
return mRotDataInfo.dst.memory_id;
}
+uint32_t MdpRot::getSrcOffset() const {
+ return mRotDataInfo.src.offset;
+}
+
uint32_t MdpRot::getDstOffset() const {
return mRotDataInfo.dst.offset;
}
@@ -147,7 +155,6 @@
mRotImgInfo.enable = 0;
return false;
}
- save();
mRotDataInfo.session_id = mRotImgInfo.session_id;
}
return true;
@@ -238,7 +245,10 @@
}
bool MdpRot::queueBuffer(int fd, uint32_t offset) {
- if(enabled()) {
+ if(enabled() and (not isRotCached(fd,offset))) {
+ int prev_fd = getSrcMemId();
+ uint32_t prev_offset = getSrcOffset();
+
mRotDataInfo.src.memory_id = fd;
mRotDataInfo.src.offset = offset;
@@ -249,14 +259,17 @@
mRotDataInfo.dst.offset =
mMem.mRotOffset[mMem.mCurrIndex];
- mMem.mCurrIndex =
- (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
if(!overlay::mdp_wrapper::rotate(mFd.getFD(), mRotDataInfo)) {
ALOGE("MdpRot failed rotate");
dump();
+ mRotDataInfo.src.memory_id = prev_fd;
+ mRotDataInfo.src.offset = prev_offset;
return false;
}
+ save();
+ mMem.mCurrIndex =
+ (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
}
return true;
}
diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp
index 8e55362..87e134a 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -51,10 +51,18 @@
void MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; }
+int MdssRot::getSrcMemId() const {
+ return mRotData.data.memory_id;
+}
+
int MdssRot::getDstMemId() const {
return mRotData.dst_data.memory_id;
}
+uint32_t MdssRot::getSrcOffset() const {
+ return mRotData.data.offset;
+}
+
uint32_t MdssRot::getDstOffset() const {
return mRotData.dst_data.offset;
}
@@ -81,6 +89,19 @@
uint32_t MdssRot::getSessId() const { return mRotInfo.id; }
+void MdssRot::save() {
+ mLSRotInfo = mRotInfo;
+}
+
+bool MdssRot::rotConfChanged() const {
+ // 0 means same
+ if(0 == ::memcmp(&mRotInfo, &mLSRotInfo,
+ sizeof (mdp_overlay))) {
+ return false;
+ }
+ return true;
+}
+
bool MdssRot::init() {
if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) {
ALOGE("MdssRot failed to init fb0");
@@ -164,7 +185,10 @@
}
bool MdssRot::queueBuffer(int fd, uint32_t offset) {
- if(enabled()) {
+ if(enabled() and (not isRotCached(fd,offset))) {
+ int prev_fd = getSrcMemId();
+ uint32_t prev_offset = getSrcOffset();
+
mRotData.data.memory_id = fd;
mRotData.data.offset = offset;
@@ -175,14 +199,17 @@
mRotData.dst_data.offset =
mMem.mRotOffset[mMem.mCurrIndex];
- mMem.mCurrIndex =
- (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
if(!overlay::mdp_wrapper::play(mFd.getFD(), mRotData)) {
ALOGE("MdssRot play failed!");
dump();
+ mRotData.data.memory_id = prev_fd;
+ mRotData.data.offset = prev_offset;
return false;
}
+ save();
+ mMem.mCurrIndex =
+ (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
}
return true;
}
@@ -260,6 +287,7 @@
void MdssRot::reset() {
ovutils::memset0(mRotInfo);
+ ovutils::memset0(mLSRotInfo);
ovutils::memset0(mRotData);
mRotData.data.memory_id = -1;
mRotInfo.id = MSMFB_NEW_REQUEST;
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index 06e9074..b55f06a 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -29,6 +29,17 @@
//============Rotator=========================
+Rotator::Rotator() {
+ char property[PROPERTY_VALUE_MAX];
+ mRotCacheDisabled = false;
+ if((property_get("debug.rotcache.disable", property, NULL) > 0) &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+ (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ /* Used in debugging to turnoff rotator caching */
+ mRotCacheDisabled = true;
+ }
+}
+
Rotator::~Rotator() {}
Rotator* Rotator::getRotator() {
@@ -70,6 +81,20 @@
return TYPE_MDP;
}
+bool Rotator::isRotCached(int fd, uint32_t offset) const {
+ if(mRotCacheDisabled or rotConfChanged() or rotDataChanged(fd,offset))
+ return false;
+ return true;
+}
+
+bool Rotator::rotDataChanged(int fd, uint32_t offset) const {
+ /* fd and offset are the attributes of the current rotator input buffer.
+ * At this instance, getSrcMemId() and getSrcOffset() return the
+ * attributes of the previous rotator input buffer */
+ if( (fd == getSrcMemId()) and (offset == getSrcOffset()) )
+ return false;
+ return true;
+}
//============RotMem=========================
@@ -98,7 +123,7 @@
}
}
-void RotMem::setReleaseFd(const int& fence) {
+void RotMem::setCurrBufReleaseFd(const int& fence) {
int ret = 0;
if(mRelFence[mCurrIndex] >= 0) {
@@ -116,6 +141,20 @@
mRelFence[mCurrIndex] = fence;
}
+void RotMem::setPrevBufReleaseFd(const int& fence) {
+ uint32_t numRotBufs = mem.numBufs();
+ uint32_t prevIndex = (mCurrIndex + numRotBufs - 1) % (numRotBufs);
+
+ if(mRelFence[prevIndex] >= 0) {
+ /* No need of any wait as nothing will be written into this
+ * buffer by the rotator (this func is called when rotator is
+ * in cache mode) */
+ ::close(mRelFence[prevIndex]);
+ }
+
+ mRelFence[prevIndex] = fence;
+}
+
//============RotMgr=========================
RotMgr * RotMgr::sRotMgr = NULL;
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 3f09a23..e045b44 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -52,7 +52,8 @@
bool close();
bool valid() { return mem.valid(); }
uint32_t size() const { return mem.bufSz(); }
- void setReleaseFd(const int& fence);
+ void setCurrBufReleaseFd(const int& fence);
+ void setPrevBufReleaseFd(const int& fence);
// rotator data info dst offset
uint32_t mRotOffset[ROT_NUM_BUFS];
@@ -72,9 +73,20 @@
virtual void setFlags(const utils::eMdpFlags& flags) = 0;
virtual void setTransform(const utils::eTransform& rot) = 0;
virtual bool commit() = 0;
+ /* return true if the current rotator state is cached */
+ virtual bool isRotCached(int fd, uint32_t offset) const;
+ /* return true if current rotator config is same as the last round*/
+ virtual bool rotConfChanged() const = 0;
+ /* return true if the current rotator input buffer fd and offset
+ * are same as the last round */
+ virtual bool rotDataChanged(int fd, uint32_t offset) const;
virtual void setDownscale(int ds) = 0;
+ /* returns the src buffer of the rotator for the previous/current round,
+ * depending on when it is called(before/after the queuebuffer)*/
+ virtual int getSrcMemId() const = 0;
//Mem id and offset should be retrieved only after rotator kickoff
virtual int getDstMemId() const = 0;
+ virtual uint32_t getSrcOffset() const = 0;
virtual uint32_t getDstOffset() const = 0;
//Destination width, height, format, position should be retrieved only after
//rotator configuration is committed via commit API
@@ -85,7 +97,12 @@
virtual bool queueBuffer(int fd, uint32_t offset) = 0;
virtual void dump() const = 0;
virtual void getDump(char *buf, size_t len) const = 0;
- void setReleaseFd(const int& fence) { mMem.setReleaseFd(fence); }
+ inline void setCurrBufReleaseFd(const int& fence) {
+ mMem.setCurrBufReleaseFd(fence);
+ }
+ inline void setPrevBufReleaseFd(const int& fence) {
+ mMem.setPrevBufReleaseFd(fence);
+ }
static Rotator *getRotator();
/* Returns downscale by successfully applying constraints
* Returns 0 if target doesnt support rotator downscaling
@@ -98,10 +115,11 @@
protected:
/* Rotator memory manager */
RotMem mMem;
- explicit Rotator() {}
+ Rotator();
static uint32_t calcOutputBufSize(const utils::Whf& destWhf);
private:
+ bool mRotCacheDisabled;
/*Returns rotator h/w type */
static int getRotatorHwType();
friend class RotMgr;
@@ -119,8 +137,11 @@
virtual void setFlags(const utils::eMdpFlags& flags);
virtual void setTransform(const utils::eTransform& rot);
virtual bool commit();
+ virtual bool rotConfChanged() const;
virtual void setDownscale(int ds);
+ virtual int getSrcMemId() const;
virtual int getDstMemId() const;
+ virtual uint32_t getSrcOffset() const;
virtual uint32_t getDstOffset() const;
virtual uint32_t getDstFormat() const;
virtual utils::Whf getDstWhf() const;
@@ -143,9 +164,6 @@
void doTransform();
/* reset underlying data, basically memset 0 */
void reset();
- /* return true if current rotator config is different
- * than last known config */
- bool rotConfChanged() const;
/* save mRotImgInfo to be last known good config*/
void save();
/* Calculates the rotator's o/p buffer size post the transform calcs and
@@ -191,8 +209,11 @@
virtual void setFlags(const utils::eMdpFlags& flags);
virtual void setTransform(const utils::eTransform& rot);
virtual bool commit();
+ virtual bool rotConfChanged() const;
virtual void setDownscale(int ds);
+ virtual int getSrcMemId() const;
virtual int getDstMemId() const;
+ virtual uint32_t getSrcOffset() const;
virtual uint32_t getDstOffset() const;
virtual uint32_t getDstFormat() const;
virtual utils::Whf getDstWhf() const;
@@ -215,6 +236,8 @@
void doTransform();
/* reset underlying data, basically memset 0 */
void reset();
+ /* save mRotInfo to be last known good config*/
+ void save();
/* Calculates the rotator's o/p buffer size post the transform calcs and
* knowing the o/p format depending on whether fastYuv is enabled or not */
uint32_t calcOutputBufSize();
@@ -241,7 +264,9 @@
const uint32_t& downscale);
/* MdssRot info structure */
- mdp_overlay mRotInfo;
+ mdp_overlay mRotInfo;
+ /* Last saved MdssRot info structure*/
+ mdp_overlay mLSRotInfo;
/* MdssRot data structure */
msmfb_overlay_data mRotData;
/* Orientation */