hwc: Sync for rotator
Implement sync for rotator.
If a buffer is rotated, it can be used by producer soon after
rotation (and it wont have to wait until vsync).
Mdp waits for the rotator buffer's release fence to signal
to start display.
Hwc waits for previous access to rotator buffer by MDP to finish
before using it
Change-Id: I5664806a17c44d58af62a2825ce454089fcd31cf
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 244e0d6..e322357 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -105,6 +105,8 @@
ctx->mFBUpdate[i]->reset();
if(ctx->mCopyBit[i])
ctx->mCopyBit[i]->reset();
+ if(ctx->mLayerRotMap[i])
+ ctx->mLayerRotMap[i]->reset();
}
}
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 46e25dc..90038f2 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -157,7 +157,9 @@
for (uint32_t i = 0; i < MAX_DISPLAYS; i++) {
ctx->mHwcDebug[i] = new HwcDebug(i);
+ ctx->mLayerRotMap[i] = new LayerRotMap();
}
+
MDPComp::init(ctx);
ctx->vstate.enable = false;
@@ -227,6 +229,10 @@
delete ctx->mHwcDebug[i];
ctx->mHwcDebug[i] = NULL;
}
+ if(ctx->mLayerRotMap[i]) {
+ delete ctx->mLayerRotMap[i];
+ ctx->mLayerRotMap[i] = NULL;
+ }
}
@@ -620,18 +626,25 @@
}
int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
- int fd) {
+ int fd) {
int ret = 0;
- struct mdp_buf_sync data;
int acquireFd[MAX_NUM_APP_LAYERS];
int count = 0;
int releaseFd = -1;
int fbFd = -1;
- memset(&data, 0, sizeof(data));
+ int rotFd = -1;
bool swapzero = false;
+ int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
+
+ struct mdp_buf_sync data;
+ memset(&data, 0, sizeof(data));
+ //Until B-family supports sync for rotator
+#ifdef MDSS_TARGET
data.flags = MDP_BUF_SYNC_FLAG_WAIT;
+#endif
data.acq_fen_fd = acquireFd;
data.rel_fen_fd = &releaseFd;
+
char property[PROPERTY_VALUE_MAX];
if(property_get("debug.egl.swapinterval", property, "1") > 0) {
if(atoi(property) == 0)
@@ -641,10 +654,35 @@
if(dpy)
isExtAnimating = ctx->listStats[dpy].isDisplayAnimating;
- //Accumulate acquireFenceFds
+ //Send acquireFenceFds to rotator
+#ifdef MDSS_TARGET
+ //TODO B-family
+#else
+ //A-family
+ int rotFd = ctx->mRotMgr->getRotDevFd();
+ struct msm_rotator_buf_sync rotData;
+
+ for(uint32_t i = 0; i < ctx->mLayerRotMap[dpy]->getCount(); i++) {
+ memset(&rotData, 0, sizeof(rotData));
+ int& acquireFenceFd =
+ ctx->mLayerRotMap[dpy]->getLayer(i)->acquireFenceFd;
+ rotData.acq_fen_fd = acquireFenceFd;
+ rotData.session_id = ctx->mLayerRotMap[dpy]->getRot(i)->getSessId();
+ ioctl(rotFd, MSM_ROTATOR_IOCTL_BUFFER_SYNC, &rotData);
+ close(acquireFenceFd);
+ //For MDP to wait on.
+ acquireFenceFd = dup(rotData.rel_fen_fd);
+ //A buffer is free to be used by producer as soon as its copied to
+ //rotator.
+ ctx->mLayerRotMap[dpy]->getLayer(i)->releaseFenceFd =
+ rotData.rel_fen_fd;
+ }
+#endif
+
+ //Accumulate acquireFenceFds for MDP
for(uint32_t i = 0; i < list->numHwLayers; i++) {
if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
- list->hwLayers[i].acquireFenceFd != -1) {
+ list->hwLayers[i].acquireFenceFd >= 0) {
if(UNLIKELY(swapzero))
acquireFd[count++] = -1;
else
@@ -653,19 +691,20 @@
if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
if(UNLIKELY(swapzero))
acquireFd[count++] = -1;
- else if(fd != -1) {
+ else if(fd >= 0) {
//set the acquireFD from fd - which is coming from c2d
acquireFd[count++] = fd;
// Buffer sync IOCTL should be async when using c2d fence is
// used
data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
- } else if(list->hwLayers[i].acquireFenceFd != -1)
+ } else if(list->hwLayers[i].acquireFenceFd >= 0)
acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
}
}
data.acq_fen_fd_cnt = count;
fbFd = ctx->dpyAttr[dpy].fd;
+
//Waits for acquire fences, returns a release fence
if(LIKELY(!swapzero)) {
uint64_t start = systemTime();
@@ -686,9 +725,9 @@
if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
//Populate releaseFenceFds.
- if(UNLIKELY(swapzero))
+ if(UNLIKELY(swapzero)) {
list->hwLayers[i].releaseFenceFd = -1;
- else if(isExtAnimating) {
+ } else if(isExtAnimating) {
// Release all the app layer fds immediately,
// if animation is in progress.
hwc_layer_1_t const* layer = &list->hwLayers[i];
@@ -697,8 +736,10 @@
list->hwLayers[i].releaseFenceFd = dup(releaseFd);
} else
list->hwLayers[i].releaseFenceFd = -1;
- } else
+ } else if(list->hwLayers[i].releaseFenceFd < 0) {
+ //If rotator has not already populated this field.
list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+ }
}
}
@@ -709,11 +750,22 @@
if (ctx->mCopyBit[dpy])
ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
+
+#ifdef MDSS_TARGET
+ //TODO When B is implemented remove #ifdefs from here
+ //The API called applies to RotMem buffers
+#else
+ //A-family
+ //Signals when MDP finishes reading rotator buffers.
+ ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
+#endif
+
// if external is animating, close the relaseFd
if(isExtAnimating) {
close(releaseFd);
releaseFd = -1;
}
+
if(UNLIKELY(swapzero)){
list->retireFenceFd = -1;
close(releaseFd);
@@ -950,6 +1002,7 @@
ctx->mOverlay->clear(dpy);
return -1;
}
+ ctx->mLayerRotMap[dpy]->add(layer, *rot);
whf.format = (*rot)->getDstFormat();
updateSource(orient, whf, crop);
rotFlags |= ovutils::ROT_PREROTATED;
@@ -1025,6 +1078,7 @@
ctx->mOverlay->clear(dpy);
return -1;
}
+ ctx->mLayerRotMap[dpy]->add(layer, *rot);
whf.format = (*rot)->getDstFormat();
updateSource(orient, whf, crop);
rotFlags |= ROT_PREROTATED;
@@ -1158,4 +1212,25 @@
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDSS_MDP_BWC_EN);
}
+void LayerRotMap::add(hwc_layer_1_t* layer, Rotator *rot) {
+ if(mCount >= MAX_SESS) return;
+ mLayer[mCount] = layer;
+ mRot[mCount] = rot;
+ mCount++;
+}
+
+void LayerRotMap::reset() {
+ for (int i = 0; i < MAX_SESS; i++) {
+ mLayer[i] = 0;
+ mRot[i] = 0;
+ }
+ mCount = 0;
+}
+
+void LayerRotMap::setReleaseFd(const int& fence) {
+ for(uint32_t i = 0; i < mCount; i++) {
+ mRot[i]->setReleaseFd(dup(fence));
+ }
+}
+
};//namespace qhwc
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 916a59d..4146787 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -121,6 +121,36 @@
HWC_COPYBIT = 0x00000002,
};
+class LayerRotMap {
+public:
+ LayerRotMap() { reset(); }
+ enum { MAX_SESS = 3 };
+ void add(hwc_layer_1_t* layer, overlay::Rotator *rot);
+ void reset();
+ uint32_t getCount() const;
+ hwc_layer_1_t* getLayer(uint32_t index) const;
+ overlay::Rotator* getRot(uint32_t index) const;
+ void setReleaseFd(const int& fence);
+private:
+ hwc_layer_1_t* mLayer[MAX_SESS];
+ overlay::Rotator* mRot[MAX_SESS];
+ uint32_t mCount;
+};
+
+inline uint32_t LayerRotMap::getCount() const {
+ return mCount;
+}
+
+inline hwc_layer_1_t* LayerRotMap::getLayer(uint32_t index) const {
+ if(index >= mCount) return NULL;
+ return mLayer[index];
+}
+
+inline overlay::Rotator* LayerRotMap::getRot(uint32_t index) const {
+ if(index >= mCount) return NULL;
+ return mRot[index];
+}
+
// -----------------------------------------------------------------------------
// Utility functions - implemented in hwc_utils.cpp
void dumpLayer(hwc_layer_1_t const* l);
@@ -301,7 +331,6 @@
hwc_rect_t mPrevCropVideo;
hwc_rect_t mPrevDestVideo;
int mPrevTransformVideo;
-
//Securing in progress indicator
bool mSecuring;
//External Display configuring progress indicator
@@ -318,6 +347,7 @@
int mExtOrientation;
//Flags the transition of a video session
bool mVideoTransFlag;
+ qhwc::LayerRotMap *mLayerRotMap[MAX_DISPLAYS];
};
namespace qhwc {