display: Add support orientation control on ext display

- The required orientation on External can be set using the
  properyt sys.ext_orientation.
- Values can be HAL_TRANSFORM_ROT_90, HAL_TRANSFORM_ROT_270
- According to the value set, the FB_TARGET for External will
  be rotated and positioned as per aspect ratio on Ext
- For YUV(video layer) it just calculates the position, as the
  rotation should be the source orientation
- This feature is supported only for low resolution panel.

Change-Id: I3d532ee0cb8dca3c37869537b55cd8044fd9047e
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 439432e..b9be4d4 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -19,12 +19,17 @@
  */
 
 #define DEBUG_FBUPDATE 0
+#include <cutils/properties.h>
 #include <gralloc_priv.h>
+#include <overlayRotator.h>
 #include "hwc_fbupdate.h"
 #include "mdp_version.h"
+#include "external.h"
 
 using namespace qdutils;
 
+using overlay::Rotator;
+
 namespace qhwc {
 
 namespace ovutils = overlay::utils;
@@ -38,6 +43,7 @@
 
 inline void IFBUpdate::reset() {
     mModeOn = false;
+    mRot = NULL;
 }
 
 //================= Low res====================================
@@ -87,46 +93,71 @@
         mDest = dest;
 
         ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
-
+        ovutils::eIsFg isFg = ovutils::IS_FG_OFF;
         ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
 
-        ovutils::PipeArgs parg(mdpFlags,
-                               info,
-                               zOrder,
-                               ovutils::IS_FG_OFF,
-                               ovutils::ROT_FLAGS_NONE);
-        ov.setSource(parg, dest);
-
         hwc_rect_t sourceCrop = layer->sourceCrop;
         hwc_rect_t displayFrame = layer->displayFrame;
-        if(extOnlyLayerIndex == -1) {
+        int transform = layer->transform;
+        int fbWidth  = ctx->dpyAttr[mDpy].xres;
+        int fbHeight = ctx->dpyAttr[mDpy].yres;
+        int rotFlags = ovutils::ROT_FLAGS_NONE;
+
+        ovutils::eTransform orient =
+                    static_cast<ovutils::eTransform>(transform);
+        if(mDpy && ctx->mExtOrientation) {
+            // If there is a external orientation set, use that
+            transform = ctx->mExtOrientation;
+            orient = static_cast<ovutils::eTransform >(ctx->mExtOrientation);
+        }
+
+        // Dont do wormhole calculation when extorientation is set on External
+        if((!mDpy || (mDpy && !ctx->mExtOrientation))
+                               && extOnlyLayerIndex == -1) {
             getNonWormholeRegion(list, sourceCrop);
             displayFrame = sourceCrop;
         }
-
-        // x,y,w,h
-        ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
-                           sourceCrop.right - sourceCrop.left,
-                           sourceCrop.bottom - sourceCrop.top);
-        ov.setCrop(dcrop, dest);
-
-        int transform = layer->transform;
-        ovutils::eTransform orient =
-            static_cast<ovutils::eTransform>(transform);
-        ov.setTransform(orient, dest);
-
         ovutils::Dim dpos(displayFrame.left,
                           displayFrame.top,
                           displayFrame.right - displayFrame.left,
                           displayFrame.bottom - displayFrame.top);
         // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
-        if(mDpy)
+        if(mDpy && !ctx->mExtOrientation)
             getActionSafePosition(ctx, mDpy, dpos.x, dpos.y, dpos.w, dpos.h);
-        ov.setPosition(dpos, dest);
 
+        if(mDpy) {
+            getAspectRatioPosition(ctx, mDpy, ctx->mExtOrientation, dpos.x,
+                                    dpos.y, dpos.w, dpos.h);
+            // Convert dim to hwc_rect_t
+            displayFrame.left = dpos.x;
+            displayFrame.top = dpos.y;
+            displayFrame.right = dpos.w + displayFrame.left;
+            displayFrame.bottom = dpos.h + displayFrame.top;
+        }
+        setMdpFlags(layer, mdpFlags, 0);
+        // For External use rotator if there is a rotation value set
+        if(mDpy && (ctx->mExtOrientation & HWC_TRANSFORM_ROT_90)) {
+            mRot = ctx->mRotMgr->getNext();
+            if(mRot == NULL) return -1;
+            //Configure rotator for pre-rotation
+            if(configRotator(mRot, info, sourceCrop, mdpFlags, orient, 0) < 0) {
+                ALOGE("%s: configRotator Failed!", __FUNCTION__);
+                mRot = NULL;
+                return -1;
+            }
+            info.format = (mRot)->getDstFormat();
+            updateSource(orient, info, sourceCrop);
+            rotFlags |= ovutils::ROT_PREROTATED;
+        }
+        //For the mdp, since either we are pre-rotating or MDP does flips
+        orient = ovutils::OVERLAY_TRANSFORM_0;
+        transform = 0;
+        ovutils::PipeArgs parg(mdpFlags, info, zOrder, isFg,
+                                static_cast<ovutils::eRotFlags>(rotFlags));
         ret = true;
-        if (!ov.commit(dest)) {
-            ALOGE("%s: commit fails", __FUNCTION__);
+        if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
+                    NULL, mDest) < 0) {
+            ALOGE("%s: ConfigMdp failed for low res", __FUNCTION__);
             ret = false;
         }
     }
@@ -141,7 +172,15 @@
     bool ret = true;
     overlay::Overlay& ov = *(ctx->mOverlay);
     ovutils::eDest dest = mDest;
-    if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
+    int fd = hnd->fd;
+    uint32_t offset = hnd->offset;
+    if(mRot) {
+        if(!mRot->queueBuffer(fd, offset))
+            return false;
+        fd = mRot->getDstMemId();
+        offset = mRot->getDstOffset();
+    }
+    if (!ov.queueBuffer(fd, offset, dest)) {
         ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__);
         ret = false;
     }
@@ -155,6 +194,7 @@
     IFBUpdate::reset();
     mDestLeft = ovutils::OV_INVALID;
     mDestRight = ovutils::OV_INVALID;
+    mRot = NULL;
 }
 
 bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,