Merge "gralloc: Do not map framebuffer memory unless needed"
diff --git a/common.mk b/common.mk
index 74d6032..cefe060 100644
--- a/common.mk
+++ b/common.mk
@@ -37,10 +37,9 @@
 
 # Executed only on QCOM BSPs
 ifeq ($(TARGET_USES_QCOM_BSP),true)
-# On jb_mr2- dont enable QCOM Display features
-ifneq ($(call is-platform-sdk-version-at-least,18),true)
-# This flag is used to compile out any features that depend on framework changes
+# Enable QCOM Display features
     common_flags += -DQCOM_BSP
+ifneq ($(call is-platform-sdk-version-at-least,18),true)
     common_flags += -DANDROID_JELLYBEAN_MR1=1
 endif
 endif
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index 23b336c..5fd68da 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -129,10 +129,10 @@
         case HAL_PIXEL_FORMAT_RGB_888:       return MDP_RGB_888;
         case HAL_PIXEL_FORMAT_RGBA_8888:     return MDP_RGBA_8888;
         case HAL_PIXEL_FORMAT_BGRA_8888:     return MDP_BGRA_8888;
-        case HAL_PIXEL_FORMAT_YCrCb_422_SP:  return MDP_Y_CBCR_H2V1;
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  return MDP_Y_CBCR_H2V2;
-        case HAL_PIXEL_FORMAT_YCbCr_422_SP:  return MDP_Y_CRCB_H2V1;
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP:  return MDP_Y_CRCB_H2V2;
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:  return MDP_Y_CRCB_H2V1;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  return MDP_Y_CRCB_H2V2;
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:  return MDP_Y_CBCR_H2V1;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:  return MDP_Y_CBCR_H2V2;
         case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: return MDP_Y_CBCR_H2V2_ADRENO;
         case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: return MDP_Y_CBCR_H2V2_ADRENO;
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: return MDP_Y_CBCR_H2V2;
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_copybit.h b/libhwcomposer/hwc_copybit.h
index a2d6405..31de9ee 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -21,7 +21,7 @@
 #define HWC_COPYBIT_H
 #include "hwc_utils.h"
 
-#define NUM_RENDER_BUFFERS 2
+#define NUM_RENDER_BUFFERS 3
 
 namespace qhwc {
 
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index d4ce253..2103cb4 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -52,6 +52,7 @@
 
 void MDPComp::dump(android::String8& buf)
 {
+    Locker::Autolock _l(mMdpCompLock);
     dumpsys_log(buf,"HWC Map for Dpy: %s \n",
                 mDpy ? "\"EXTERNAL\"" : "\"PRIMARY\"");
     dumpsys_log(buf,"PREV_FRAME: layerCount:%2d    mdpCount:%2d \
@@ -756,6 +757,9 @@
                  __FUNCTION__);
         return 0;
     }
+
+    Locker::Autolock _l(mMdpCompLock);
+
     //reset old data
     mCurrentFrame.reset(numLayers);
 
@@ -894,6 +898,8 @@
         return false;
     }
 
+    Locker::Autolock _l(mMdpCompLock);
+
     /* reset Invalidator */
     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
         idleInvalidator->markForSleep();
@@ -1077,6 +1083,8 @@
         return false;
     }
 
+    Locker::Autolock _l(mMdpCompLock);
+
     /* reset Invalidator */
     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
         idleInvalidator->markForSleep();
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 908a658..ea7c7b1 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -174,6 +174,7 @@
     static IdleInvalidator *idleInvalidator;
     struct FrameInfo mCurrentFrame;
     struct LayerCache mCachedFrame;
+    mutable Locker mMdpCompLock;
 };
 
 class MDPCompLowRes : public MDPComp {
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 {
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'};
diff --git a/liboverlay/pipes/overlayGenPipe.cpp b/liboverlay/pipes/overlayGenPipe.cpp
index f5d4475..3ab0d19 100644
--- a/liboverlay/pipes/overlayGenPipe.cpp
+++ b/liboverlay/pipes/overlayGenPipe.cpp
@@ -33,8 +33,8 @@
 
 namespace overlay {
 
-GenericPipe::GenericPipe(int dpy) : mFbNum(dpy), mRot(0), mRotUsed(false),
-        mRotDownscaleOpt(false), mPreRotated(false), pipeState(CLOSED) {
+GenericPipe::GenericPipe(int dpy) : mFbNum(dpy), mRotDownscaleOpt(false),
+    pipeState(CLOSED) {
     init();
 }
 
@@ -45,9 +45,7 @@
 bool GenericPipe::init()
 {
     ALOGE_IF(DEBUG_OVERLAY, "GenericPipe init");
-    mRotUsed = false;
     mRotDownscaleOpt = false;
-    mPreRotated = false;
     if(mFbNum)
         mFbNum = Overlay::getInstance()->getExtFbNum();
 
@@ -63,9 +61,6 @@
         return false;
     }
 
-    //get a new rotator object, take ownership
-    mRot = Rotator::getRotator();
-
     return true;
 }
 
@@ -81,21 +76,12 @@
         ret = false;
     }
 
-    delete mRot;
-    mRot = 0;
-
     setClosed();
     return ret;
 }
 
 void GenericPipe::setSource(const utils::PipeArgs& args) {
-    //Cache if user wants 0-rotation
-    mRotUsed = args.rotFlags & utils::ROT_0_ENABLED;
     mRotDownscaleOpt = args.rotFlags & utils::ROT_DOWNSCALE_ENABLED;
-    mPreRotated = args.rotFlags & utils::ROT_PREROTATED;
-    if(mPreRotated) mRotUsed = false;
-    mRot->setSource(args.whf);
-    mRot->setFlags(args.mdpFlags);
     mCtrlData.ctrl.setSource(args);
 }
 
@@ -104,10 +90,6 @@
 }
 
 void GenericPipe::setTransform(const utils::eTransform& orient) {
-    //Rotation could be enabled by user for zero-rot or the layer could have
-    //some transform. Mark rotation enabled in either case.
-    mRotUsed |= ((orient & utils::OVERLAY_TRANSFORM_ROT_90) && !mPreRotated);
-    mRot->setTransform(orient);
     mCtrlData.ctrl.setTransform(orient);
 }
 
@@ -129,39 +111,11 @@
         ovutils::Dim dst(mCtrlData.ctrl.getPosition());
         downscale_factor = ovutils::getDownscaleFactor(
                 src.w, src.h, dst.w, dst.h);
-        mRotUsed |= (downscale_factor && !mPreRotated);
-    }
-
-
-    if(mRotUsed) {
-        mRot->setDownscale(downscale_factor);
-        //If wanting to use rotator, start it.
-        if(!mRot->commit()) {
-            ALOGE("GenPipe Rotator commit failed");
-            //If rot commit fails, flush rotator session, memory, fd and create
-            //a hollow rotator object
-            delete mRot;
-            mRot = Rotator::getRotator();
-            pipeState = CLOSED;
-            return false;
-        }
-        /* Set the mdp src format to the output format of the rotator.
-         * The output format of the rotator might be different depending on
-         * whether fastyuv mode is enabled in the rotator.
-         */
-        mCtrlData.ctrl.updateSrcFormat(mRot->getDstFormat());
     }
 
     mCtrlData.ctrl.setDownscale(downscale_factor);
     ret = mCtrlData.ctrl.commit();
 
-    //If mdp commit fails, flush rotator session, memory, fd and create a hollow
-    //rotator object
-    if(ret == false) {
-        delete mRot;
-        mRot = Rotator::getRotator();
-    }
-
     pipeState = ret ? OPEN : CLOSED;
     return ret;
 }
@@ -174,26 +128,7 @@
     // set pipe id from ctrl to data
     mCtrlData.data.setPipeId(pipeId);
 
-    int finalFd = fd;
-    uint32_t finalOffset = offset;
-    //If rotator is to be used, queue to it, so it can ROTATE.
-    if(mRotUsed) {
-        if(!mRot->queueBuffer(fd, offset)) {
-            ALOGE("GenPipe Rotator play failed");
-            return false;
-        }
-        //Configure MDP's source buffer as the current output buffer of rotator
-        if(mRot->getDstMemId() != -1) {
-            finalFd = mRot->getDstMemId();
-            finalOffset = mRot->getDstOffset();
-        } else {
-            //Could be -1 for NullRotator, if queue above succeeds.
-            //Need an actual rotator. Modify overlay State Traits.
-            //Not fatal, keep queuing to MDP without rotation.
-            ALOGE("Null rotator in use, where an actual is required");
-        }
-    }
-    return mCtrlData.data.queueBuffer(finalFd, finalOffset);
+    return mCtrlData.data.queueBuffer(fd, offset);
 }
 
 int GenericPipe::getCtrlFd() const {
@@ -209,18 +144,15 @@
 {
     ALOGE("== Dump Generic pipe start ==");
     ALOGE("pipe state = %d", (int)pipeState);
-    OVASSERT(mRot, "GenericPipe should have a valid Rot");
     mCtrlData.ctrl.dump();
     mCtrlData.data.dump();
-    mRot->dump();
+
     ALOGE("== Dump Generic pipe end ==");
 }
 
 void GenericPipe::getDump(char *buf, size_t len) {
     mCtrlData.ctrl.getDump(buf, len);
     mCtrlData.data.getDump(buf, len);
-    if(mRotUsed && mRot)
-        mRot->getDump(buf, len);
 }
 
 bool GenericPipe::isClosed() const  {
diff --git a/liboverlay/pipes/overlayGenPipe.h b/liboverlay/pipes/overlayGenPipe.h
index 5463eb8..9a66632 100644
--- a/liboverlay/pipes/overlayGenPipe.h
+++ b/liboverlay/pipes/overlayGenPipe.h
@@ -31,7 +31,6 @@
 #define OVERLAY_GENERIC_PIPE_H
 
 #include "overlayUtils.h"
-#include "overlayRotator.h"
 #include "overlayCtrlData.h"
 
 namespace overlay {
@@ -86,14 +85,9 @@
     int mFbNum;
     /* Ctrl/Data aggregator */
     CtrlData mCtrlData;
-    Rotator* mRot;
-    //Whether rotator is used for 0-rot or otherwise
-    bool mRotUsed;
     //Whether we will do downscale opt. This is just a request. If the frame is
     //not a candidate, we might not do it.
     bool mRotDownscaleOpt;
-    //Whether the source is prerotated.
-    bool mPreRotated;
     /* Pipe open or closed */
     enum ePipeState {
         CLOSED,
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index 04dcf9f..1dd317f 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -50,6 +50,7 @@
     mFeatures = 0;
     //TODO get this from driver, default for A-fam to 8
     mMDPDownscale = 8;
+    mFd = fb_fd;
 
     if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_finfo) < 0) {
         ALOGE("FBIOGET_FSCREENINFO failed");
@@ -103,7 +104,6 @@
         panel_type = *ptype;
     }
     mPanelType = panel_type;
-    close(fb_fd);
     mMDPVersion = mdp_version;
     mHasOverlay = false;
     if((mMDPVersion >= MDP_V4_0) ||
@@ -135,6 +135,10 @@
     }
 }
 
+MDPVersion::~MDPVersion() {
+    close(mFd);
+}
+
 bool MDPVersion::supportsDecimation() {
     return mFeatures & MDP_DECIMATION_EN;
 }
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index e26f4d3..316899f 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -89,7 +89,7 @@
 {
 public:
     MDPVersion();
-    ~MDPVersion() { }
+    ~MDPVersion();
     int getMDPVersion() {return mMDPVersion;}
     char getPanelType() {return mPanelType;}
     bool hasOverlay() {return mHasOverlay;}
@@ -104,6 +104,7 @@
     int getLeftSplit() { return mSplit.left(); }
     int getRightSplit() { return mSplit.right(); }
 private:
+    int mFd;
     int mMDPVersion;
     char mPanelType;
     bool mHasOverlay;