/* Sets the virtual resolution to match that of the primary
   display in the event that the virtual display currently
   connected has a lower resolution. NB: we always report the
   highest available resolution to SurfaceFlinger.
*/
void VirtualDisplay::setToPrimary(uint32_t maxArea,
                                  uint32_t priW,
                                  uint32_t priH,
                                  uint32_t &extW,
                                  uint32_t &extH) {
    // for eg., primary in 1600p and WFD in 1080p
    // we wont use downscale feature because MAX MDP
    // writeback resolution supported is 1080p (tracked
    // by SUPPORTED_VIRTUAL_AREA).
    if((maxArea == (priW * priH))
        && (maxArea <= SUPPORTED_VIRTUAL_AREA)) {
        // tmpW and tmpH will hold the primary dimensions before we
        // update the aspect ratio if necessary.
        uint32_t tmpW = priW;
        uint32_t tmpH = priH;
        // If WFD is in landscape, assign the higher dimension
        // to WFD's xres.
        if(priH > priW) {
            tmpW = priH;
            tmpH = priW;
        }
        // The aspect ratios of the external and primary displays
        // can be different. As a result, directly assigning primary
        // resolution could lead to an incorrect final image.
        // We get around this by calculating a new resolution by
        // keeping aspect ratio intact.
        hwc_rect r = {0, 0, 0, 0};
        getAspectRatioPosition(tmpW, tmpH, extW, extH, r);
        extW = r.right - r.left;
        extH = r.bottom - r.top;
    }
}
// Configure
bool FBUpdateLowRes::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
                               int fbZorder) {
    bool ret = false;
    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
    if (LIKELY(ctx->mOverlay)) {
        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);
        private_handle_t *hnd = (private_handle_t *)layer->handle;
        ovutils::Whf info(getWidth(hnd), getHeight(hnd),
                          ovutils::getMdpFormat(hnd->format), hnd->size);

        //Request an RGB pipe
        ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy);
        if(dest == ovutils::OV_INVALID) { //None available
            ALOGE("%s: No pipes available to configure framebuffer",
                __FUNCTION__);
            return false;
        }

        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);

        hwc_rect_t sourceCrop = layer->sourceCrop;
        hwc_rect_t displayFrame = layer->displayFrame;
        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;
        }
        ovutils::Dim dpos(displayFrame.left,
                          displayFrame.top,
                          displayFrame.right - displayFrame.left,
                          displayFrame.bottom - displayFrame.top);

        if(mDpy) {
            // Get Aspect Ratio for external
            getAspectRatioPosition(ctx, mDpy, ctx->mExtOrientation, dpos.x,
                                    dpos.y, dpos.w, dpos.h);
            // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
            getActionSafePosition(ctx, mDpy, 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, 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;

        //XXX: FB layer plane alpha is currently sent as zero from
        //surfaceflinger
        ovutils::PipeArgs parg(mdpFlags,
                info,
                zOrder,
                isFg,
                static_cast<ovutils::eRotFlags>(rotFlags),
                ovutils::DEFAULT_PLANE_ALPHA,
                (ovutils::eBlending) getBlending(layer->blending));

        ret = true;
        if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
                    NULL, mDest) < 0) {
            ALOGE("%s: ConfigMdp failed for low res", __FUNCTION__);
            ret = false;
        }
    }
    return ret;
}