hwc: Add support for SourceSplit

Add support for SourceSplit. The mixers are abstracted from hwc.
There would be no translations to mixer understood destinations.

1) If a layer's crop and position are < 2048, only 1 pipe can be used
irrespective of position.
2) Else 2 pipes can be used with the layer equally split, without
regard to position.

Change-Id: I501a53838d147887c1e2299366663e05320d5096
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index cc9e3b9..27abf6a 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -39,6 +39,9 @@
 
 IFBUpdate* IFBUpdate::getObject(hwc_context_t *ctx, const int& dpy) {
     if(isDisplaySplit(ctx, dpy)) {
+        if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
+            return new FBSrcSplit(ctx, dpy);
+        }
         return new FBUpdateSplit(ctx, dpy);
     }
     return new FBUpdateNonSplit(ctx, dpy);
@@ -422,5 +425,102 @@
     return ret;
 }
 
+//=================FBSrcSplit====================================
+FBSrcSplit::FBSrcSplit(hwc_context_t *ctx, const int& dpy):
+        FBUpdateSplit(ctx, dpy) {}
+
+bool FBSrcSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+        hwc_rect_t fbUpdatingRect, int fbZorder) {
+    bool ret = false;
+    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
+    int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
+    // ext only layer present..
+    if(extOnlyLayerIndex != -1) {
+        layer = &list->hwLayers[extOnlyLayerIndex];
+        layer->compositionType = HWC_OVERLAY;
+    }
+    overlay::Overlay& ov = *(ctx->mOverlay);
+
+    ovutils::Whf info(mAlignedFBWidth,
+            mAlignedFBHeight,
+            ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
+                mTileEnabled));
+    //Request left pipe, VG first owing to higher prio
+    ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy,
+            Overlay::MIXER_DEFAULT);
+    if(destL == ovutils::OV_INVALID) {
+        destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
+            Overlay::MIXER_DEFAULT);
+        if(destL == ovutils::OV_INVALID) {
+            ALOGE("%s: No pipes available to configure fb for dpy %d's left"
+                    " mixer", __FUNCTION__, mDpy);
+            return false;
+        }
+    }
+    //Request right pipe
+    ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
+            Overlay::MIXER_DEFAULT);
+    if(destR == ovutils::OV_INVALID) {
+        ALOGE("%s: No pipes available to configure fb for dpy %d's right"
+                " mixer", __FUNCTION__, mDpy);
+        return false;
+    }
+
+    mDestLeft = destL;
+    mDestRight = destR;
+
+    ovutils::eMdpFlags mdpFlags = OV_MDP_BLEND_FG_PREMULT;
+    ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
+
+    ovutils::PipeArgs parg(mdpFlags,
+            info,
+            zOrder,
+            ovutils::IS_FG_OFF,
+            ovutils::ROT_FLAGS_NONE,
+            ovutils::DEFAULT_PLANE_ALPHA,
+            (ovutils::eBlending)
+            getBlending(layer->blending));
+    ov.setSource(parg, destL);
+    ov.setSource(parg, destR);
+
+    //Crop and Position are same for FB
+    ovutils::Dim cropPosL(
+            fbUpdatingRect.left,
+            fbUpdatingRect.top,
+            (fbUpdatingRect.right - fbUpdatingRect.left) / 2,
+            fbUpdatingRect.bottom - fbUpdatingRect.top);
+
+    ovutils::Dim cropPosR(
+            cropPosL.x + cropPosL.w,
+            cropPosL.y,
+            cropPosL.w,
+            cropPosL.h);
+
+    ov.setCrop(cropPosL, destL);
+    ov.setCrop(cropPosR, destR);
+    ov.setPosition(cropPosL, destL);
+    ov.setPosition(cropPosR, destR);
+
+    int transform = layer->transform;
+    ovutils::eTransform orient =
+            static_cast<ovutils::eTransform>(transform);
+    ov.setTransform(orient, destL);
+    ov.setTransform(orient, destR);
+
+    ret = true;
+    if (!ov.commit(destL)) {
+        ALOGE("%s: commit fails for left", __FUNCTION__);
+        ret = false;
+    }
+    if (!ov.commit(destR)) {
+        ALOGE("%s: commit fails for right", __FUNCTION__);
+        ret = false;
+    }
+    if(ret == false) {
+        ctx->mLayerRotMap[mDpy]->clear();
+    }
+    return ret;
+}
+
 //---------------------------------------------------------------------
 }; //namespace qhwc
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index c8347fa..545f5bd 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -88,13 +88,24 @@
             hwc_rect_t fbUpdatingRect, int fbZorder);
     bool draw(hwc_context_t *ctx, private_handle_t *hnd);
     void reset();
-private:
-    bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+
+protected:
+    virtual bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
             hwc_rect_t fbUpdatingRect, int fbZorder);
     ovutils::eDest mDestLeft; //left pipe to draw on
     ovutils::eDest mDestRight; //right pipe to draw on
 };
 
+//Source Split Handler
+class FBSrcSplit : public FBUpdateSplit {
+public:
+    explicit FBSrcSplit(hwc_context_t *ctx, const int& dpy);
+    virtual ~FBSrcSplit() {};
+private:
+    bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+            hwc_rect_t fbUpdatingRect, int fbZorder);
+};
+
 }; //namespace qhwc
 
 #endif //HWC_FBUPDATE_H
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 2356c9c..028af47 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -48,6 +48,9 @@
 
 MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
     if(isDisplaySplit(ctx, dpy)) {
+        if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
+            return new MDPCompSrcSplit(dpy);
+        }
         return new MDPCompSplit(dpy);
     }
     return new MDPCompNonSplit(dpy);
@@ -1825,5 +1828,183 @@
 
     return true;
 }
+
+//================MDPCompSrcSplit==============================================
+bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+        MdpPipeInfoSplit& pipe_info, ePipeType /*type*/) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    hwc_rect_t dst = layer->displayFrame;
+    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+    pipe_info.lIndex = ovutils::OV_INVALID;
+    pipe_info.rIndex = ovutils::OV_INVALID;
+
+    //If 2 pipes are staged on a single stage of a mixer, then the left pipe
+    //should have a higher priority than the right one. Pipe priorities are
+    //starting with VG0, VG1 ... , RGB0 ..., DMA1
+    //TODO Currently we acquire VG pipes for left side and RGB/DMA for right to
+    //make sure pipe priorities are satisfied. A better way is to have priority
+    //as part of overlay object and acquire any 2 pipes. Assign the higher
+    //priority one to left side and lower to right side.
+
+    //1 pipe by default for a layer
+    pipe_info.lIndex = getMdpPipe(ctx, MDPCOMP_OV_VG, Overlay::MIXER_DEFAULT);
+    if(pipe_info.lIndex == ovutils::OV_INVALID) {
+        if(isYuvBuffer(hnd)) {
+            return false;
+        }
+        pipe_info.lIndex = getMdpPipe(ctx, MDPCOMP_OV_ANY,
+                Overlay::MIXER_DEFAULT);
+        if(pipe_info.lIndex == ovutils::OV_INVALID) {
+            return false;
+        }
+    }
+
+    //If layer's crop width or dest width > 2048, use 2 pipes
+    if((dst.right - dst.left) > qdutils::MAX_DISPLAY_DIM or
+            (crop.right - crop.left) > qdutils::MAX_DISPLAY_DIM) {
+        ePipeType rightType = isYuvBuffer(hnd) ?
+                MDPCOMP_OV_VG : MDPCOMP_OV_ANY;
+        pipe_info.rIndex = getMdpPipe(ctx, rightType, Overlay::MIXER_DEFAULT);
+        if(pipe_info.rIndex == ovutils::OV_INVALID) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool MDPCompSrcSplit::allocLayerPipes(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
+        if(mCurrentFrame.isFBComposed[index]) continue;
+        hwc_layer_1_t* layer = &list->hwLayers[index];
+        int mdpIndex = mCurrentFrame.layerToMDP[index];
+        PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
+        info.pipeInfo = new MdpPipeInfoSplit;
+        info.rot = NULL;
+        MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
+
+        ePipeType type = MDPCOMP_OV_ANY;
+        if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
+            ALOGD_IF(isDebug(), "%s: Unable to get pipe for type = %d",
+                    __FUNCTION__, (int) type);
+            return false;
+        }
+    }
+    return true;
+}
+
+int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        PipeLayerPair& PipeLayerPair) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if(!hnd) {
+        ALOGE("%s: layer handle is NULL", __FUNCTION__);
+        return -1;
+    }
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+    MdpPipeInfoSplit& mdp_info =
+        *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
+    Rotator **rot = &PipeLayerPair.rot;
+    eZorder z = static_cast<eZorder>(mdp_info.zOrder);
+    eIsFg isFg = IS_FG_OFF;
+    eDest lDest = mdp_info.lIndex;
+    eDest rDest = mdp_info.rIndex;
+    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+    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;
+    uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
+    Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
+
+    ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
+             "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
+
+    // Handle R/B swap
+    if (layer->flags & HWC_FORMAT_RB_SWAP) {
+        if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
+            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
+        else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
+            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
+    }
+
+    eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+    setMdpFlags(layer, mdpFlagsL, 0, transform);
+    eMdpFlags mdpFlagsR = mdpFlagsL;
+
+    if(lDest != OV_INVALID && rDest != OV_INVALID) {
+        //Enable overfetch
+        setMdpFlags(mdpFlagsL, OV_MDSS_MDP_DUAL_PIPE);
+    }
+
+    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, crop, mdpFlagsL, orient, downscale) < 0) {
+            ALOGE("%s: configRotator failed!", __FUNCTION__);
+            return -1;
+        }
+        ctx->mLayerRotMap[mDpy]->add(layer, *rot);
+        whf.format = (*rot)->getDstFormat();
+        updateSource(orient, whf, crop);
+        rotFlags |= ROT_PREROTATED;
+    }
+
+    //If 2 pipes being used, divide layer into half, crop and dst
+    hwc_rect_t cropL = crop;
+    hwc_rect_t cropR = crop;
+    hwc_rect_t dstL = dst;
+    hwc_rect_t dstR = dst;
+    if(lDest != OV_INVALID && rDest != OV_INVALID) {
+        cropL.right = (crop.right + crop.left) / 2;
+        cropR.left = cropL.right;
+        sanitizeSourceCrop(cropL, cropR, hnd);
+
+        //Swap crops on H flip since 2 pipes are being used
+        if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
+            hwc_rect_t tmp = cropL;
+            cropL = cropR;
+            cropR = tmp;
+        }
+
+        dstL.right = (dst.right + dst.left) / 2;
+        dstR.left = dstL.right;
+    }
+
+    //For the mdp, since either we are pre-rotating or MDP does flips
+    orient = OVERLAY_TRANSFORM_0;
+    transform = 0;
+
+    //configure left pipe
+    if(lDest != OV_INVALID) {
+        PipeArgs pargL(mdpFlagsL, whf, z, isFg,
+                static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+                (ovutils::eBlending) getBlending(layer->blending));
+
+        if(configMdp(ctx->mOverlay, pargL, orient,
+                    cropL, dstL, metadata, lDest) < 0) {
+            ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
+            return -1;
+        }
+    }
+
+    //configure right pipe
+    if(rDest != OV_INVALID) {
+        PipeArgs pargR(mdpFlagsR, whf, z, isFg,
+                static_cast<eRotFlags>(rotFlags),
+                layer->planeAlpha,
+                (ovutils::eBlending) getBlending(layer->blending));
+        if(configMdp(ctx->mOverlay, pargR, orient,
+                    cropR, dstR, metadata, rDest) < 0) {
+            ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
 }; //namespace
 
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 4e4bea4..94199e3 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -269,14 +269,15 @@
     explicit MDPCompSplit(int dpy):MDPComp(dpy){};
     virtual ~MDPCompSplit(){};
     virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
-private:
+
+protected:
     struct MdpPipeInfoSplit : public MdpPipeInfo {
         ovutils::eDest lIndex;
         ovutils::eDest rIndex;
         virtual ~MdpPipeInfoSplit() {};
     };
 
-    bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+    virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
                          MdpPipeInfoSplit& pipe_info, ePipeType type);
 
     /* configure's overlay pipes for the frame */
@@ -287,6 +288,7 @@
     virtual bool allocLayerPipes(hwc_context_t *ctx,
                                  hwc_display_contents_1_t* list);
 
+private:
     /* Increments mdpCount if 4k2k yuv layer split is enabled.
      * updates framebuffer z order if fb lies above source-split layer */
     virtual void adjustForSourceSplit(hwc_context_t *ctx,
@@ -297,5 +299,20 @@
             PipeLayerPair& PipeLayerPair);
 };
 
+class MDPCompSrcSplit : public MDPCompSplit {
+public:
+    explicit MDPCompSrcSplit(int dpy) : MDPCompSplit(dpy){};
+    virtual ~MDPCompSrcSplit(){};
+private:
+    virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+            MdpPipeInfoSplit& pipe_info, ePipeType type);
+
+    virtual bool allocLayerPipes(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+
+    virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+            PipeLayerPair& pipeLayerPair);
+};
+
 }; //namespace
 #endif