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/liboverlay/Android.mk b/liboverlay/Android.mk
index ed2f503..a375284 100644
--- a/liboverlay/Android.mk
+++ b/liboverlay/Android.mk
@@ -6,7 +6,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES := $(common_libs) libqdutils libmemalloc
+LOCAL_SHARED_LIBRARIES := $(common_libs) libqdutils libmemalloc libsync
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdoverlay\"
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
LOCAL_SRC_FILES := \
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index 3861297..2995580 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -26,6 +26,8 @@
namespace overlay {
+//============Rotator=========================
+
Rotator::~Rotator() {}
Rotator* Rotator::getRotator() {
@@ -56,6 +58,9 @@
return TYPE_MDP;
}
+
+//============RotMem=========================
+
bool RotMem::close() {
bool ret = true;
for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) {
@@ -70,11 +75,46 @@
return ret;
}
+RotMem::Mem::Mem() : mCurrOffset(0) {
+ utils::memset0(mRotOffset);
+ for(int i = 0; i < ROT_NUM_BUFS; i++) {
+ mRelFence[i] = -1;
+ }
+}
+
+RotMem::Mem::~Mem() {
+ for(int i = 0; i < ROT_NUM_BUFS; i++) {
+ ::close(mRelFence[i]);
+ mRelFence[i] = -1;
+ }
+}
+
+void RotMem::Mem::setReleaseFd(const int& fence) {
+ int ret = 0;
+
+ if(mRelFence[mCurrOffset] >= 0) {
+ //Wait for previous usage of this buffer to be over.
+ //Can happen if rotation takes > vsync and a fast producer. i.e queue
+ //happens in subsequent vsyncs either because content is 60fps or
+ //because the producer is hasty sometimes.
+ ret = sync_wait(mRelFence[mCurrOffset], 1000);
+ if(ret < 0) {
+ ALOGE("%s: sync_wait error!! error no = %d err str = %s",
+ __FUNCTION__, errno, strerror(errno));
+ }
+ ::close(mRelFence[mCurrOffset]);
+ }
+ mRelFence[mCurrOffset] = fence;
+}
+
+//============RotMgr=========================
+
RotMgr::RotMgr() {
for(int i = 0; i < MAX_ROT_SESS; i++) {
mRot[i] = 0;
}
mUseCount = 0;
+ mRotDevFd = -1;
}
RotMgr::~RotMgr() {
@@ -118,6 +158,8 @@
}
}
mUseCount = 0;
+ ::close(mRotDevFd);
+ mRotDevFd = -1;
}
void RotMgr::getDump(char *buf, size_t len) {
@@ -131,4 +173,15 @@
strncat(buf, str, strlen(str));
}
+int RotMgr::getRotDevFd() {
+ //2nd check just in case
+ if(mRotDevFd < 0 && Rotator::getRotatorHwType() == Rotator::TYPE_MDP) {
+ mRotDevFd = ::open("/dev/msm_rotator", O_RDWR, 0);
+ if(mRotDevFd < 0) {
+ ALOGE("%s failed to open rotator device", __FUNCTION__);
+ }
+ }
+ return mRotDevFd;
+}
+
}
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 120721c..7f90160 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -38,6 +38,45 @@
namespace overlay {
+/*
+ Manages the case where new rotator memory needs to be
+ allocated, before previous is freed, due to resolution change etc. If we make
+ rotator memory to be always max size, irrespctive of source resolution then
+ we don't need this RotMem wrapper. The inner class is sufficient.
+*/
+struct RotMem {
+ // Max rotator memory allocations
+ enum { MAX_ROT_MEM = 2};
+
+ //Manages the rotator buffer offsets.
+ struct Mem {
+ Mem();
+ ~Mem();
+ bool valid() { return m.valid(); }
+ bool close() { return m.close(); }
+ uint32_t size() const { return m.bufSz(); }
+ void setReleaseFd(const int& fence);
+ // Max rotator buffers
+ enum { ROT_NUM_BUFS = 2 };
+ // rotator data info dst offset
+ uint32_t mRotOffset[ROT_NUM_BUFS];
+ int mRelFence[ROT_NUM_BUFS];
+ // current offset slot from mRotOffset
+ uint32_t mCurrOffset;
+ OvMem m;
+ };
+
+ RotMem() : _curr(0) {}
+ Mem& curr() { return m[_curr % MAX_ROT_MEM]; }
+ const Mem& curr() const { return m[_curr % MAX_ROT_MEM]; }
+ Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; }
+ RotMem& operator++() { ++_curr; return *this; }
+ void setReleaseFd(const int& fence) { curr().setReleaseFd(fence); }
+ bool close();
+ uint32_t _curr;
+ Mem m[MAX_ROT_MEM];
+};
+
class Rotator
{
public:
@@ -56,50 +95,19 @@
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); }
static Rotator *getRotator();
protected:
+ /* Rotator memory manager */
+ RotMem mMem;
explicit Rotator() {}
static uint32_t calcOutputBufSize(const utils::Whf& destWhf);
private:
/*Returns rotator h/w type */
static int getRotatorHwType();
-};
-
-/*
- Manages the case where new rotator memory needs to be
- allocated, before previous is freed, due to resolution change etc. If we make
- rotator memory to be always max size, irrespctive of source resolution then
- we don't need this RotMem wrapper. The inner class is sufficient.
-*/
-struct RotMem {
- // Max rotator memory allocations
- enum { MAX_ROT_MEM = 2};
-
- //Manages the rotator buffer offsets.
- struct Mem {
- Mem() : mCurrOffset(0) {utils::memset0(mRotOffset); }
- bool valid() { return m.valid(); }
- bool close() { return m.close(); }
- uint32_t size() const { return m.bufSz(); }
- // Max rotator buffers
- enum { ROT_NUM_BUFS = 2 };
- // rotator data info dst offset
- uint32_t mRotOffset[ROT_NUM_BUFS];
- // current offset slot from mRotOffset
- uint32_t mCurrOffset;
- OvMem m;
- };
-
- RotMem() : _curr(0) {}
- Mem& curr() { return m[_curr % MAX_ROT_MEM]; }
- const Mem& curr() const { return m[_curr % MAX_ROT_MEM]; }
- Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; }
- RotMem& operator++() { ++_curr; return *this; }
- bool close();
- uint32_t _curr;
- Mem m[MAX_ROT_MEM];
+ friend class RotMgr;
};
/*
@@ -155,8 +163,6 @@
utils::eTransform mOrientation;
/* rotator fd */
OvFD mFd;
- /* Rotator memory manager */
- RotMem mMem;
friend Rotator* Rotator::getRotator();
};
@@ -209,8 +215,6 @@
utils::eTransform mOrientation;
/* rotator fd */
OvFD mFd;
- /* Rotator memory manager */
- RotMem mMem;
/* Enable/Disable Mdss Rot*/
bool mEnabled;
@@ -233,9 +237,11 @@
* Expects a NULL terminated buffer of big enough size.
*/
void getDump(char *buf, size_t len);
+ int getRotDevFd(); //Called on A-fam only
private:
overlay::Rotator *mRot[MAX_ROT_SESS];
int mUseCount;
+ int mRotDevFd; //A-fam
};
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index 9bfa34e..c3d00f1 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -368,11 +368,6 @@
return fmt3D;
}
-bool isMdssRotator() {
- int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
- return (mdpVersion >= qdutils::MDSS_V5);
-}
-
void getDump(char *buf, size_t len, const char *prefix,
const mdp_overlay& ov) {
char str[256] = {'\0'};