Merge "hwc/overlay: Get rot dest dimensions instead of manipulating source"
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 942b8b2..de4cd05 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -109,8 +109,7 @@
             mRot = NULL;
             return false;
         }
-        info.format = (mRot)->getDstFormat();
-        updateSource(orient, info, sourceCrop);
+        updateSource(orient, info, sourceCrop, mRot);
         rotFlags |= ovutils::ROT_PREROTATED;
     }
     return true;
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index fdc3f2e..37b211d 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -2345,8 +2345,7 @@
             ALOGE("%s: configRotator failed!", __FUNCTION__);
             return -1;
         }
-        whf.format = (*rot)->getDstFormat();
-        updateSource(orient, whf, crop);
+        updateSource(orient, whf, crop, *rot);
         rotFlags |= ROT_PREROTATED;
     }
 
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index bf4582c..cc18686 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -1528,18 +1528,8 @@
 
     if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
         qdutils::MDSS_V5) {
-        uint32_t crop_w = (crop.right - crop.left);
-        uint32_t crop_h = (crop.bottom - crop.top);
-        if (ovutils::isYuv(whf.format)) {
-            ovutils::normalizeCrop((uint32_t&)crop.left, crop_w);
-            ovutils::normalizeCrop((uint32_t&)crop.top, crop_h);
-            // For interlaced, crop.h should be 4-aligned
-            if ((mdpFlags & ovutils::OV_MDP_DEINTERLACE) && (crop_h % 4))
-                crop_h = ovutils::aligndown(crop_h, 4);
-            crop.right = crop.left + crop_w;
-            crop.bottom = crop.top + crop_h;
-        }
-        Dim rotCrop(crop.left, crop.top, crop_w, crop_h);
+         Dim rotCrop(crop.left, crop.top, crop.right - crop.left,
+                crop.bottom - crop.top);
         rot->setCrop(rotCrop);
     }
 
@@ -1614,28 +1604,27 @@
 }
 
 void updateSource(eTransform& orient, Whf& whf,
-        hwc_rect_t& crop) {
-    Dim srcCrop(crop.left, crop.top,
+        hwc_rect_t& crop, Rotator *rot) {
+    Dim transformedCrop(crop.left, crop.top,
             crop.right - crop.left,
             crop.bottom - crop.top);
-    orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
-    preRotateSource(orient, whf, srcCrop);
     if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
         qdutils::MDSS_V5) {
-        // Source for overlay will be the cropped (and rotated)
-        crop.left = 0;
-        crop.top = 0;
-        crop.right = srcCrop.w;
-        crop.bottom = srcCrop.h;
-        // Set width & height equal to sourceCrop w & h
-        whf.w = srcCrop.w;
-        whf.h = srcCrop.h;
+        //B-family rotator internally could modify destination dimensions if
+        //downscaling is supported
+        whf = rot->getDstWhf();
+        transformedCrop = rot->getDstDimensions();
     } else {
-        crop.left = srcCrop.x;
-        crop.top = srcCrop.y;
-        crop.right = srcCrop.x + srcCrop.w;
-        crop.bottom = srcCrop.y + srcCrop.h;
+        //A-family rotator rotates entire buffer irrespective of crop, forcing
+        //us to recompute the crop based on transform
+        orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
+        preRotateSource(orient, whf, transformedCrop);
     }
+
+    crop.left = transformedCrop.x;
+    crop.top = transformedCrop.y;
+    crop.right = transformedCrop.x + transformedCrop.w;
+    crop.bottom = transformedCrop.y + transformedCrop.h;
 }
 
 int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
@@ -1701,8 +1690,7 @@
             ALOGE("%s: configRotator failed!", __FUNCTION__);
             return -1;
         }
-        whf.format = (*rot)->getDstFormat();
-        updateSource(orient, whf, crop);
+        updateSource(orient, whf, crop, *rot);
         rotFlags |= ovutils::ROT_PREROTATED;
     }
 
@@ -1807,8 +1795,7 @@
             ALOGE("%s: configRotator failed!", __FUNCTION__);
             return -1;
         }
-        whf.format = (*rot)->getDstFormat();
-        updateSource(orient, whf, crop);
+        updateSource(orient, whf, crop, *rot);
         rotFlags |= ROT_PREROTATED;
     }
 
@@ -1941,8 +1928,7 @@
             ALOGE("%s: configRotator failed!", __FUNCTION__);
             return -1;
         }
-        whf.format = (*rot)->getDstFormat();
-        updateSource(orient, whf, crop);
+        updateSource(orient, whf, crop, *rot);
         rotFlags |= ROT_PREROTATED;
     }
 
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index ad06e89..d2d1846 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -356,7 +356,7 @@
         ovutils::eIsFg& isFg, const ovutils::eDest& dest);
 
 void updateSource(ovutils::eTransform& orient, ovutils::Whf& whf,
-        hwc_rect_t& crop);
+        hwc_rect_t& crop, overlay::Rotator *rot);
 
 //Routine to configure low resolution panels (<= 2048 width)
 int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
diff --git a/liboverlay/overlayMdpRot.cpp b/liboverlay/overlayMdpRot.cpp
index f456029..bb985d7 100755
--- a/liboverlay/overlayMdpRot.cpp
+++ b/liboverlay/overlayMdpRot.cpp
@@ -19,6 +19,7 @@
 
 #include "overlayUtils.h"
 #include "overlayRotator.h"
+#include "gr.h"
 
 namespace ovutils = overlay::utils;
 
@@ -47,6 +48,24 @@
     return mRotImgInfo.dst.format;
 }
 
+//Added for completeness. Not expected to be called.
+utils::Whf MdpRot::getDstWhf() const {
+    int alW = 0, alH = 0;
+    int halFormat = ovutils::getHALFormat(mRotImgInfo.dst.format);
+    getBufferSizeAndDimensions(mRotImgInfo.dst.width, mRotImgInfo.dst.height,
+            halFormat, alW, alH);
+    return utils::Whf(alW, alH, mRotImgInfo.dst.format);
+}
+
+//Added for completeness. Not expected to be called.
+utils::Dim MdpRot::getDstDimensions() const {
+    int alW = 0, alH = 0;
+    int halFormat = ovutils::getHALFormat(mRotImgInfo.dst.format);
+    getBufferSizeAndDimensions(mRotImgInfo.dst.width, mRotImgInfo.dst.height,
+            halFormat, alW, alH);
+    return utils::Dim(0, 0, alW, alH);
+}
+
 uint32_t MdpRot::getSessId() const { return mRotImgInfo.session_id; }
 
 void MdpRot::setDownscale(int ds) {
diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp
index f7bc87a..5783dcb 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -63,6 +63,21 @@
     return mRotInfo.src.format;
 }
 
+utils::Whf MdssRot::getDstWhf() const {
+    //For Mdss dst_rect itself represents buffer dimensions. We ignore actual
+    //aligned values during buffer allocation. Also the driver overwrites the
+    //src.format field if destination format is different.
+    //This implementation detail makes it possible to retrieve w,h even before
+    //buffer allocation, which happens in queueBuffer.
+    return utils::Whf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h,
+            mRotInfo.src.format);
+}
+
+utils::Dim MdssRot::getDstDimensions() const {
+    return utils::Dim(mRotInfo.dst_rect.x, mRotInfo.dst_rect.y,
+            mRotInfo.dst_rect.w, mRotInfo.dst_rect.h);
+}
+
 uint32_t MdssRot::getSessId() const { return mRotInfo.id; }
 
 bool MdssRot::init() {
@@ -82,16 +97,10 @@
 }
 
 void MdssRot::setCrop(const utils::Dim& crop) {
-
     mRotInfo.src_rect.x = crop.x;
     mRotInfo.src_rect.y = crop.y;
     mRotInfo.src_rect.w = crop.w;
     mRotInfo.src_rect.h = crop.h;
-
-    mRotInfo.dst_rect.x = 0;
-    mRotInfo.dst_rect.y = 0;
-    mRotInfo.dst_rect.w = crop.w;
-    mRotInfo.dst_rect.h = crop.h;
 }
 
 void MdssRot::setDownscale(int /*ds*/) {
@@ -119,7 +128,22 @@
 }
 
 bool MdssRot::commit() {
+    if (utils::isYuv(mRotInfo.src.format)) {
+        utils::normalizeCrop(mRotInfo.src_rect.x, mRotInfo.src_rect.w);
+        utils::normalizeCrop(mRotInfo.src_rect.y, mRotInfo.src_rect.h);
+        // For interlaced, crop.h should be 4-aligned
+        if ((mRotInfo.flags & utils::OV_MDP_DEINTERLACE) and
+                (mRotInfo.src_rect.h % 4))
+            mRotInfo.src_rect.h = utils::aligndown(mRotInfo.src_rect.h, 4);
+    }
+
+    mRotInfo.dst_rect.x = 0;
+    mRotInfo.dst_rect.y = 0;
+    mRotInfo.dst_rect.w = mRotInfo.src_rect.w;
+    mRotInfo.dst_rect.h = mRotInfo.src_rect.h;
+
     doTransform();
+
     mRotInfo.flags |= MDSS_MDP_ROT_ONLY;
     mEnabled = true;
     if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) {
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index e0f542c..64387cd 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -74,9 +74,14 @@
     virtual void setTransform(const utils::eTransform& rot) = 0;
     virtual bool commit() = 0;
     virtual void setDownscale(int ds) = 0;
+    //Mem id and offset should be retrieved only after rotator kickoff
     virtual int getDstMemId() 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
     virtual uint32_t getDstFormat() const = 0;
+    virtual utils::Whf getDstWhf() const = 0;
+    virtual utils::Dim getDstDimensions() const = 0;
     virtual uint32_t getSessId() const = 0;
     virtual bool queueBuffer(int fd, uint32_t offset) = 0;
     virtual void dump() const = 0;
@@ -112,6 +117,8 @@
     virtual int getDstMemId() const;
     virtual uint32_t getDstOffset() const;
     virtual uint32_t getDstFormat() const;
+    virtual utils::Whf getDstWhf() const;
+    virtual utils::Dim getDstDimensions() const;
     virtual uint32_t getSessId() const;
     virtual bool queueBuffer(int fd, uint32_t offset);
     virtual void dump() const;
@@ -169,6 +176,8 @@
     virtual int getDstMemId() const;
     virtual uint32_t getDstOffset() const;
     virtual uint32_t getDstFormat() const;
+    virtual utils::Whf getDstWhf() const;
+    virtual utils::Dim getDstDimensions() const;
     virtual uint32_t getSessId() const;
     virtual bool queueBuffer(int fd, uint32_t offset);
     virtual void dump() const;
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index 2fcc4ef..530377b 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -543,6 +543,14 @@
         value--;
 }
 
+/* Prerotation adjusts crop co-ordinates to the new transformed values within
+ * destination buffer. This is necessary only when the entire buffer is rotated
+ * irrespective of crop (A-family). If only the crop portion of the buffer is
+ * rotated into a destination buffer matching the size of crop, we don't need to
+ * use this helper (B-family).
+ * @Deprecated as of now, retained for the case where a full buffer needs
+ * transform and also as a reference.
+ */
 void preRotateSource(const eTransform& tr, Whf& whf, Dim& srcCrop);
 void getDump(char *buf, size_t len, const char *prefix, const mdp_overlay& ov);
 void getDump(char *buf, size_t len, const char *prefix, const msmfb_img& ov);