hwc/overlay: Video on 4k2k external, 4k2k rotation.

-Add support for Video via overlay on 4k2k external panel.
-Add support for rotating videos on 4k2k panels. We use
pre-rotation in hwc to rotate a video into a single buffer,
irrespective of panel size. Then this buffer is fed to MDP.
Rotator objects are managed by the new RotMgr.
-Cleaup mdpcomp and overlay.

Change-Id: Ifb08534747e8e18b6c58dd8a3e1a9947409100f1
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index e9446ad..74ab9e0 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -25,9 +25,11 @@
 #include <gralloc_priv.h>
 #include <fb_priv.h>
 #include <overlay.h>
+#include <overlayRotator.h>
 #include "hwc_utils.h"
 #include "hwc_mdpcomp.h"
 #include "hwc_fbupdate.h"
+#include "hwc_video.h"
 #include "mdp_version.h"
 #include "hwc_copybit.h"
 #include "external.h"
@@ -38,6 +40,9 @@
 using namespace qClient;
 using namespace qService;
 using namespace android;
+using namespace overlay;
+using namespace overlay::utils;
+namespace ovutils = overlay::utils;
 
 namespace qhwc {
 
@@ -67,6 +72,7 @@
     openFramebufferDevice(ctx);
     overlay::Overlay::initOverlay();
     ctx->mOverlay = overlay::Overlay::getInstance();
+    ctx->mRotMgr = new RotMgr();
     ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
     ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
     ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
@@ -77,6 +83,10 @@
         IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
         HWC_DISPLAY_PRIMARY);
 
+    ctx->mVidOv[HWC_DISPLAY_PRIMARY] =
+        IVideoOverlay::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
+        HWC_DISPLAY_PRIMARY);
+
     char value[PROPERTY_VALUE_MAX];
     // Check if the target supports copybit compostion (dyn/mdp/c2d) to
     // decide if we need to open the copybit module.
@@ -120,6 +130,11 @@
         ctx->mOverlay = NULL;
     }
 
+    if(ctx->mRotMgr) {
+        delete ctx->mRotMgr;
+        ctx->mRotMgr = NULL;
+    }
+
     for(int i = 0; i < MAX_DISPLAYS; i++) {
         if(ctx->mCopyBit[i]) {
             delete ctx->mCopyBit[i];
@@ -144,6 +159,10 @@
             delete ctx->mFBUpdate[i];
             ctx->mFBUpdate[i] = NULL;
         }
+        if(ctx->mVidOv[i]) {
+            delete ctx->mVidOv[i];
+            ctx->mVidOv[i] = NULL;
+        }
     }
 
     if(ctx->mMDPComp) {
@@ -492,6 +511,263 @@
     return ret;
 }
 
+void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
+        hwc_rect_t& crop, hwc_rect_t& dst) {
+    int hw_w = ctx->dpyAttr[dpy].xres;
+    int hw_h = ctx->dpyAttr[dpy].yres;
+    if(dst.left < 0 || dst.top < 0 ||
+            dst.right > hw_w || dst.bottom > hw_h) {
+        hwc_rect_t scissor = {0, 0, hw_w, hw_h };
+        qhwc::calculate_crop_rects(crop, dst, scissor, transform);
+    }
+}
+
+void setMdpFlags(hwc_layer_1_t *layer,
+        ovutils::eMdpFlags &mdpFlags,
+        int rotDownscale) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+    const int& transform = layer->transform;
+
+    if(layer->blending == HWC_BLENDING_PREMULT) {
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_BLEND_FG_PREMULT);
+    }
+
+    if(isYuvBuffer(hnd)) {
+        if(isSecureBuffer(hnd)) {
+            ovutils::setMdpFlags(mdpFlags,
+                    ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
+        }
+        if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
+                metadata->interlaced) {
+            ovutils::setMdpFlags(mdpFlags,
+                    ovutils::OV_MDP_DEINTERLACE);
+        }
+        //Pre-rotation will be used using rotator.
+        if(transform & HWC_TRANSFORM_ROT_90) {
+            ovutils::setMdpFlags(mdpFlags,
+                    ovutils::OV_MDP_SOURCE_ROTATED_90);
+        }
+    }
+
+    //No 90 component and no rot-downscale then flips done by MDP
+    //If we use rot then it might as well do flips
+    if(!(layer->transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
+        if(layer->transform & HWC_TRANSFORM_FLIP_H) {
+            ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
+        }
+
+        if(layer->transform & HWC_TRANSFORM_FLIP_V) {
+            ovutils::setMdpFlags(mdpFlags,  ovutils::OV_MDP_FLIP_V);
+        }
+    }
+}
+
+static inline int configRotator(Rotator *rot, const Whf& whf,
+        const eMdpFlags& mdpFlags, const eTransform& orient,
+        const int& downscale) {
+    rot->setSource(whf);
+    rot->setFlags(mdpFlags);
+    rot->setTransform(orient);
+    rot->setDownscale(downscale);
+    if(!rot->commit()) return -1;
+    return 0;
+}
+
+static inline int configMdp(Overlay *ov, const PipeArgs& parg,
+        const eTransform& orient, const hwc_rect_t& crop,
+        const hwc_rect_t& pos, const eDest& dest) {
+    ov->setSource(parg, dest);
+    ov->setTransform(orient, dest);
+
+    int crop_w = crop.right - crop.left;
+    int crop_h = crop.bottom - crop.top;
+    Dim dcrop(crop.left, crop.top, crop_w, crop_h);
+    ov->setCrop(dcrop, dest);
+
+    int posW = pos.right - pos.left;
+    int posH = pos.bottom - pos.top;
+    Dim position(pos.left, pos.top, posW, posH);
+    ov->setPosition(position, dest);
+
+    if (!ov->commit(dest)) {
+        return -1;
+    }
+    return 0;
+}
+
+static inline void updateSource(eTransform& orient, Whf& whf,
+        hwc_rect_t& crop) {
+    Dim srcCrop(crop.left, crop.top,
+            crop.right - crop.left,
+            crop.bottom - crop.top);
+    preRotateSource(orient, whf, srcCrop);
+    crop.left = srcCrop.x;
+    crop.top = srcCrop.y;
+    crop.right = srcCrop.x + srcCrop.w;
+    crop.bottom = srcCrop.y + srcCrop.h;
+}
+
+int configureLowRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        const int& dpy, eMdpFlags& mdpFlags, const eZorder& z,
+        const eIsFg& isFg, const eDest& dest, Rotator **rot) {
+
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if(!hnd) {
+        ALOGE("%s: layer handle is NULL", __FUNCTION__);
+        return -1;
+    }
+
+    hwc_rect_t crop = layer->sourceCrop;
+    hwc_rect_t dst = layer->displayFrame;
+    int transform = layer->transform;
+    eTransform orient = static_cast<eTransform>(transform);
+    int downscale = 0;
+    int rotFlags = ovutils::ROT_FLAGS_NONE;
+    Whf whf(hnd->width, hnd->height,
+            getMdpFormat(hnd->format), hnd->size);
+
+    if(isYuvBuffer(hnd) && ctx->mMDP.version >= qdutils::MDP_V4_2 &&
+                ctx->mMDP.version < qdutils::MDSS_V5) {
+        downscale = getDownscaleFactor(
+                crop.right - crop.left,
+                crop.bottom - crop.top,
+                dst.right - dst.left,
+                dst.bottom - dst.top);
+        if(downscale) {
+            rotFlags = ROT_DOWNSCALE_ENABLED;
+        }
+    }
+
+    setMdpFlags(layer, mdpFlags, downscale);
+    trimLayer(ctx, dpy, transform, crop, dst);
+
+    if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
+            ((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
+        *rot = ctx->mRotMgr->getNext();
+        if(*rot == NULL) return -1;
+        //Configure rotator for pre-rotation
+        if(configRotator(*rot, whf, mdpFlags, orient, downscale) < 0)
+            return -1;
+        whf.format = (*rot)->getDstFormat();
+        updateSource(orient, whf, crop);
+        //For the mdp, since we are pre-rotating
+        transform = 0;
+        rotFlags |= ovutils::ROT_PREROTATED;
+    }
+
+    PipeArgs parg(mdpFlags, whf, z, isFg, static_cast<eRotFlags>(rotFlags));
+    if(configMdp(ctx->mOverlay, parg, orient, crop, dst, dest) < 0) {
+        ALOGE("%s: commit failed for low res panel", __FUNCTION__);
+        return -1;
+    }
+    return 0;
+}
+
+int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        const int& dpy, eMdpFlags& mdpFlagsL, const eZorder& z,
+        const eIsFg& isFg, const eDest& lDest, const eDest& rDest,
+        Rotator **rot) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if(!hnd) {
+        ALOGE("%s: layer handle is NULL", __FUNCTION__);
+        return -1;
+    }
+
+    int hw_w = ctx->dpyAttr[dpy].xres;
+    int hw_h = ctx->dpyAttr[dpy].yres;
+    hwc_rect_t crop = layer->sourceCrop;
+    hwc_rect_t dst = layer->displayFrame;
+    int transform = layer->transform;
+    eTransform orient = static_cast<eTransform>(transform);
+    const int downscale = 0;
+    int rotFlags = ROT_FLAGS_NONE;
+
+    Whf whf(hnd->width, hnd->height,
+            getMdpFormat(hnd->format), hnd->size);
+
+    setMdpFlags(layer, mdpFlagsL);
+    trimLayer(ctx, dpy, transform, crop, dst);
+
+    if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
+        (*rot) = ctx->mRotMgr->getNext();
+        if((*rot) == NULL) return -1;
+        //Configure rotator for pre-rotation
+        if(configRotator(*rot, whf, mdpFlagsL, orient, downscale) < 0)
+            return -1;
+        whf.format = (*rot)->getDstFormat();
+        updateSource(orient, whf, crop);
+        //For the mdp, since we are pre-rotating
+        transform = 0;
+        rotFlags |= ROT_PREROTATED;
+    }
+
+    eMdpFlags mdpFlagsR = mdpFlagsL;
+    setMdpFlags(mdpFlagsR, OV_MDSS_MDP_RIGHT_MIXER);
+
+    hwc_rect_t tmp_cropL, tmp_dstL;
+    hwc_rect_t tmp_cropR, tmp_dstR;
+
+    if(lDest != OV_INVALID) {
+        tmp_cropL = crop;
+        tmp_dstL = dst;
+        hwc_rect_t scissor = {0, 0, hw_w/2, hw_h };
+        qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
+    }
+    if(rDest != OV_INVALID) {
+        tmp_cropR = crop;
+        tmp_dstR = dst;
+        hwc_rect_t scissor = {hw_w/2, 0, hw_w, hw_h };
+        qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
+    }
+
+    //When buffer is flipped, contents of mixer config also needs to swapped.
+    //Not needed if the layer is confined to one half of the screen.
+    //If rotator has been used then it has also done the flips, so ignore them.
+    if(layer->transform & HWC_TRANSFORM_FLIP_V && lDest != OV_INVALID
+            && rDest != OV_INVALID && rot == NULL) {
+        hwc_rect_t new_cropR;
+        new_cropR.left = tmp_cropL.left;
+        new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
+
+        hwc_rect_t new_cropL;
+        new_cropL.left  = new_cropR.right;
+        new_cropL.right = tmp_cropR.right;
+
+        tmp_cropL.left =  new_cropL.left;
+        tmp_cropL.right =  new_cropL.right;
+
+        tmp_cropR.left = new_cropR.left;
+        tmp_cropR.right =  new_cropR.right;
+
+    }
+
+    //configure left mixer
+    if(lDest != OV_INVALID) {
+        PipeArgs pargL(mdpFlagsL, whf, z, isFg,
+                static_cast<eRotFlags>(rotFlags));
+        if(configMdp(ctx->mOverlay, pargL, orient,
+                tmp_cropL, tmp_dstL, lDest) < 0) {
+            ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
+            return -1;
+        }
+    }
+
+    //configure right mixer
+    if(rDest != OV_INVALID) {
+        PipeArgs pargR(mdpFlagsR, whf, z, isFg,
+                static_cast<eRotFlags>(rotFlags));
+        if(configMdp(ctx->mOverlay, pargR, orient,
+                tmp_cropR, tmp_dstR, rDest) < 0) {
+            ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
 void LayerCache::resetLayerCache(int num) {
     for(uint32_t i = 0; i < MAX_NUM_LAYERS; i++) {
         hnd[i] = NULL;
@@ -556,7 +832,6 @@
             }
         }
     }
-
 }
 
-};//namespace
+};//namespace qhwc