diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index ae7bb954..30555fa6 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include "hwc_utils.h" @@ -100,11 +101,11 @@ static void reset(hwc_context_t *ctx, int numDisplays, if(ctx->mFBUpdate[i]) ctx->mFBUpdate[i]->reset(); - + if(ctx->mVidOv[i]) + ctx->mVidOv[i]->reset(); if(ctx->mCopyBit[i]) ctx->mCopyBit[i]->reset(); } - VideoOverlay::reset(); } //clear prev layer prop flags and realloc for current frame @@ -135,7 +136,7 @@ static int hwc_prepare_primary(hwc_composer_device_1 *dev, int ret = ctx->mMDPComp->prepare(ctx, list); if(!ret) { // IF MDPcomp fails use this route - VideoOverlay::prepare(ctx, list, dpy); + ctx->mVidOv[dpy]->prepare(ctx, list); ctx->mFBUpdate[dpy]->prepare(ctx, list); } ctx->mLayerCache[dpy]->updateLayerCache(list); @@ -161,7 +162,7 @@ static int hwc_prepare_external(hwc_composer_device_1 *dev, if(fbLayer->handle) { setListStats(ctx, list, dpy); reset_layer_prop(ctx, dpy); - VideoOverlay::prepare(ctx, list, dpy); + ctx->mVidOv[dpy]->prepare(ctx, list); ctx->mFBUpdate[dpy]->prepare(ctx, list); ctx->mLayerCache[dpy]->updateLayerCache(list); if(ctx->mCopyBit[dpy]) @@ -188,6 +189,7 @@ static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays, reset(ctx, numDisplays, displays); ctx->mOverlay->configBegin(); + ctx->mRotMgr->configBegin(); for (int32_t i = numDisplays; i >= 0; i--) { hwc_display_contents_1_t *list = displays[i]; @@ -205,6 +207,8 @@ static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays, } ctx->mOverlay->configDone(); + ctx->mRotMgr->configDone(); + return ret; } @@ -250,6 +254,7 @@ static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank) if(blank) { ctx->mOverlay->configBegin(); ctx->mOverlay->configDone(); + ctx->mRotMgr->clear(); ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN); if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected == true) { @@ -344,12 +349,12 @@ static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); if(list->numHwLayers > 1) hwc_sync(ctx, list, dpy, fd); - if (!VideoOverlay::draw(ctx, list, dpy)) { - ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__); + if (!ctx->mVidOv[dpy]->draw(ctx, list)) { + ALOGE("%s: VideoOverlay draw failed", __FUNCTION__); ret = -1; } if (!ctx->mMDPComp->draw(ctx, list)) { - ALOGE("%s: MDPComp::draw fail!", __FUNCTION__); + ALOGE("%s: MDPComp draw failed", __FUNCTION__); ret = -1; } @@ -365,7 +370,7 @@ static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { if(!(fbLayer->flags & HWC_SKIP_LAYER) && (list->numHwLayers > 1)) { if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) { - ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); + ALOGE("%s: FBUpdate draw failed", __FUNCTION__); ret = -1; } } @@ -400,7 +405,7 @@ static int hwc_set_external(hwc_context_t *ctx, if(list->numHwLayers > 1) hwc_sync(ctx, list, dpy, fd); - if (!VideoOverlay::draw(ctx, list, dpy)) { + if (!ctx->mVidOv[dpy]->draw(ctx, list)) { ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__); ret = -1; } @@ -549,6 +554,9 @@ void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len) char ovDump[2048] = {'\0'}; ctx->mOverlay->getDump(ovDump, 2048); dumpsys_log(aBuf, ovDump); + ovDump[0] = '\0'; + ctx->mRotMgr->getDump(ovDump, 2048); + dumpsys_log(aBuf, ovDump); strlcpy(buff, aBuf.string(), buff_len); } diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp index f9161a30..e79523d0 100644 --- a/libhwcomposer/hwc_fbupdate.cpp +++ b/libhwcomposer/hwc_fbupdate.cpp @@ -71,7 +71,8 @@ bool FBUpdateLowRes::configure(hwc_context_t *ctx, ALOGE("%s:NULL private handle for layer!", __FUNCTION__); return false; } - ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); + ovutils::Whf info(hnd->width, hnd->height, + ovutils::getMdpFormat(hnd->format), hnd->size); //Request an RGB pipe ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy); @@ -171,7 +172,8 @@ bool FBUpdateHighRes::configure(hwc_context_t *ctx, ALOGE("%s:NULL private handle for layer!", __FUNCTION__); return false; } - ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); + ovutils::Whf info(hnd->width, hnd->height, + ovutils::getMdpFormat(hnd->format), hnd->size); //Request left RGB pipe ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy); diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp index 4bdc3e9e..f141af80 100644 --- a/libhwcomposer/hwc_mdpcomp.cpp +++ b/libhwcomposer/hwc_mdpcomp.cpp @@ -21,11 +21,14 @@ #include "external.h" #include "qdMetaData.h" #include "mdp_version.h" +#include + +using overlay::Rotator; +using namespace overlay::utils; +namespace ovutils = overlay::utils; namespace qhwc { -namespace ovutils = overlay::utils; - //==============MDPComp======================================================== IdleInvalidator *MDPComp::idleInvalidator = NULL; @@ -188,6 +191,8 @@ void MDPComp::reset(hwc_context_t *ctx, if(mCurrentFrame.pipeLayer[i].pipeInfo) { delete mCurrentFrame.pipeLayer[i].pipeInfo; mCurrentFrame.pipeLayer[i].pipeInfo = NULL; + //We dont own the rotator + mCurrentFrame.pipeLayer[i].rot = NULL; } } free(mCurrentFrame.pipeLayer); @@ -196,20 +201,6 @@ void MDPComp::reset(hwc_context_t *ctx, mCurrentFrame.count = 0; } -void MDPComp::setVidInfo(hwc_layer_1_t *layer, - ovutils::eMdpFlags &mdpFlags) { - private_handle_t *hnd = (private_handle_t *)layer->handle; - MetaData_t *metadata = (MetaData_t *)hnd->base_metadata; - - 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); - } -} - bool MDPComp::isWidthValid(hwc_context_t *ctx, hwc_layer_1_t *layer) { const int dpy = HWC_DISPLAY_PRIMARY; @@ -363,9 +354,7 @@ bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) { for (int index = 0 ; index < mCurrentFrame.count; index++) { hwc_layer_1_t* layer = &list->hwLayers[index]; - MdpPipeInfo* cur_pipe = mCurrentFrame.pipeLayer[index].pipeInfo; - - if(configure(ctx, layer, cur_pipe) != 0 ) { + if(configure(ctx, layer, mCurrentFrame.pipeLayer[index]) != 0 ) { ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \ layer %d",__FUNCTION__, index); return false; @@ -417,134 +406,17 @@ bool MDPComp::prepare(hwc_context_t *ctx, * Configures pipe(s) for MDP composition */ int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer, - MdpPipeInfo* mdpInfo) { + PipeLayerPair& pipeLayerPair) { const int dpy = HWC_DISPLAY_PRIMARY; - private_handle_t *hnd = (private_handle_t *)layer->handle; - overlay::Overlay& ov = *ctx->mOverlay; + MdpPipeInfoLowRes& mdp_info = + *(static_cast(pipeLayerPair.pipeInfo)); + eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION; + eZorder zOrder = static_cast(mdp_info.zOrder); + eIsFg isFg = IS_FG_OFF; + eDest dest = mdp_info.index; - if(!hnd) { - ALOGE("%s: layer handle is NULL", __FUNCTION__); - return -1; - } - - MdpPipeInfoLowRes& mdp_info = *(MdpPipeInfoLowRes*)mdpInfo; - - 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 crop_w = crop.right - crop.left; - int crop_h = crop.bottom - crop.top; - - int dst_w = dst.right - dst.left; - int dst_h = dst.bottom - dst.top; - - if(dst.left < 0 || dst.top < 0 || - dst.right > hw_w || dst.bottom > hw_h) { - ALOGD_IF(isDebug(),"%s: Destination has negative coordinates", - __FUNCTION__); - hwc_rect_t scissor = {0, 0, hw_w, hw_h }; - qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform); - - //Update calulated width and height - crop_w = crop.right - crop.left; - crop_h = crop.bottom - crop.top; - - dst_w = dst.right - dst.left; - dst_h = dst.bottom - dst.top; - } - - if( (dst_w > hw_w)|| (dst_h > hw_h)) { - ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__); - dst_w = hw_w; - dst_h = hw_h; - } - - // Determine pipe to set based on pipe index - ovutils::eDest dest = mdp_info.index; - - ovutils::eZorder zOrder = ovutils::ZORDER_0; - - if(mdp_info.zOrder == 0 ) { - zOrder = ovutils::ZORDER_0; - } else if(mdp_info.zOrder == 1 ) { - zOrder = ovutils::ZORDER_1; - } else if(mdp_info.zOrder == 2 ) { - zOrder = ovutils::ZORDER_2; - } else if(mdp_info.zOrder == 3) { - zOrder = ovutils::ZORDER_3; - } - - // Order order order - // setSource - just setting source - // setParameter - changes src w/h/f accordingly - // setCrop - ROI - src_rect - // setPosition - dst_rect - // commit - commit changes to mdp driver - // queueBuffer - not here, happens when draw is called - - ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); - - ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; - - if(isYuvBuffer(hnd)) - setVidInfo(layer, mdpFlags); - - ovutils::setMdpFlags(mdpFlags,ovutils::OV_MDP_BACKEND_COMPOSITION); - - if(layer->blending == HWC_BLENDING_PREMULT) { - ovutils::setMdpFlags(mdpFlags, - ovutils::OV_MDP_BLEND_FG_PREMULT); - } - - ovutils::eTransform orient = overlay::utils::OVERLAY_TRANSFORM_0 ; - - if(!(layer->transform & HWC_TRANSFORM_ROT_90)) { - 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); - } - } else { - orient = static_cast(layer->transform); - } - - ovutils::eRotFlags rotFlags = ovutils::ROT_FLAGS_NONE; - if(isYuvBuffer(hnd) && (ctx->mMDP.version >= qdutils::MDP_V4_2 && - ctx->mMDP.version < qdutils::MDSS_V5)) { - rotFlags = ovutils::ROT_DOWNSCALE_ENABLED; - } - - ovutils::PipeArgs parg(mdpFlags, - info, - zOrder, - ovutils::IS_FG_OFF, - rotFlags); - - ov.setSource(parg, dest); - - ov.setTransform(orient, dest); - - ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h); - ov.setCrop(dcrop, dest); - - ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h); - ov.setPosition(dim, dest); - - ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \ - nPipe: %d zorder: %d",__FUNCTION__, dcrop.x, - dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h, - mdp_info.index, mdp_info.zOrder); - - if (!ov.commit(dest)) { - ALOGE("%s: commit failed", __FUNCTION__); - return -1; - } - return 0; + return configureLowRes(ctx, layer, dpy, mdpFlags, zOrder, isFg, dest, + &pipeLayerPair.rot); } int MDPCompLowRes::pipesNeeded(hwc_context_t *ctx, @@ -572,6 +444,7 @@ bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx, hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex]; PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex]; info.pipeInfo = new MdpPipeInfoLowRes; + info.rot = NULL; MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo; pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG); if(pipe_info.index == ovutils::OV_INVALID) { @@ -592,6 +465,7 @@ bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx, PipeLayerPair& info = currentFrame.pipeLayer[index]; info.pipeInfo = new MdpPipeInfoLowRes; + info.rot = NULL; MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)info.pipeInfo; pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_ANY); @@ -628,35 +502,41 @@ bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) { for(int i = 0; i < numHwLayers; i++ ) { hwc_layer_1_t *layer = &list->hwLayers[i]; - - if(!(layerProp[i].mFlags & HWC_MDPCOMP)) { - continue; + private_handle_t *hnd = (private_handle_t *)layer->handle; + if(!hnd) { + ALOGE("%s handle null", __FUNCTION__); + return false; } MdpPipeInfoLowRes& pipe_info = *(MdpPipeInfoLowRes*)mCurrentFrame.pipeLayer[i].pipeInfo; ovutils::eDest dest = pipe_info.index; - if(dest == ovutils::OV_INVALID) { ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest); return false; } - if (ctx ) { - private_handle_t *hnd = (private_handle_t *)layer->handle; - if(!hnd) { - ALOGE("%s handle null", __FUNCTION__); - return false; - } + if(!(layerProp[i].mFlags & HWC_MDPCOMP)) { + continue; + } - ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ - using pipe: %d", __FUNCTION__, layer, - hnd, dest ); + ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ + using pipe: %d", __FUNCTION__, layer, + hnd, dest ); - if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) { - ALOGE("%s: queueBuffer failed for external", __FUNCTION__); + int fd = hnd->fd; + uint32_t offset = hnd->offset; + Rotator *rot = mCurrentFrame.pipeLayer[i].rot; + if(rot) { + if(!rot->queueBuffer(fd, offset)) return false; - } + fd = rot->getDstMemId(); + offset = rot->getDstOffset(); + } + + if (!ov.queueBuffer(fd, offset, dest)) { + ALOGE("%s: queueBuffer failed for external", __FUNCTION__); + return false; } layerProp[i].mFlags &= ~HWC_MDPCOMP; @@ -774,212 +654,17 @@ bool MDPCompHighRes::allocLayerPipes(hwc_context_t *ctx, * Configures pipe(s) for MDP composition */ int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer, - MdpPipeInfo* mdpInfo) { + PipeLayerPair& pipeLayerPair) { const int dpy = HWC_DISPLAY_PRIMARY; - private_handle_t *hnd = (private_handle_t *)layer->handle; - overlay::Overlay& ov = *ctx->mOverlay; - - if(!hnd) { - ALOGE("%s: layer handle is NULL", __FUNCTION__); - return -1; - } - - MdpPipeInfoHighRes& mdp_info = *(MdpPipeInfoHighRes*)mdpInfo; - - 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 crop_w = crop.right - crop.left; - int crop_h = crop.bottom - crop.top; - - int dst_w = dst.right - dst.left; - int dst_h = dst.bottom - dst.top; - - if(dst.left < 0 || dst.top < 0 || - dst.right > hw_w || dst.bottom > hw_h) { - ALOGD_IF(isDebug(),"%s: Destination has negative coordinates", - __FUNCTION__); - hwc_rect_t scissor = {0, 0, hw_w, hw_h }; - qhwc::calculate_crop_rects(crop, dst, scissor, 0); - - //Update calulated width and height - crop_w = crop.right - crop.left; - crop_h = crop.bottom - crop.top; - - dst_w = dst.right - dst.left; - dst_h = dst.bottom - dst.top; - } - - if( (dst_w > hw_w)|| (dst_h > hw_h)) { - ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__); - dst_w = hw_w; - dst_h = hw_h; - } - - // Determine pipe to set based on pipe index - ovutils::eDest l_dest = mdp_info.lIndex; - ovutils::eDest r_dest = mdp_info.rIndex; - - ovutils::eZorder zOrder = ovutils::ZORDER_0; - - if(mdp_info.zOrder == 0 ) { - zOrder = ovutils::ZORDER_0; - } else if(mdp_info.zOrder == 1 ) { - zOrder = ovutils::ZORDER_1; - } else if(mdp_info.zOrder == 2 ) { - zOrder = ovutils::ZORDER_2; - } else if(mdp_info.zOrder == 3) { - zOrder = ovutils::ZORDER_3; - } - - // Order order order - // setSource - just setting source - // setParameter - changes src w/h/f accordingly - // setCrop - ROI - src_rect - // setPosition - dst_rect - // commit - commit changes to mdp driver - // queueBuffer - not here, happens when draw is called - - ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); - - ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE; - - if(isYuvBuffer(hnd)) - setVidInfo(layer, mdpFlagsL); - - ovutils::setMdpFlags(mdpFlagsL,ovutils::OV_MDP_BACKEND_COMPOSITION); - - if(layer->blending == HWC_BLENDING_PREMULT) { - ovutils::setMdpFlags(mdpFlagsL, - ovutils::OV_MDP_BLEND_FG_PREMULT); - } - - ovutils::eTransform orient = overlay::utils::OVERLAY_TRANSFORM_0 ; - - if(!(layer->transform & HWC_TRANSFORM_ROT_90)) { - if(layer->transform & HWC_TRANSFORM_FLIP_H) { - ovutils::setMdpFlags(mdpFlagsL, ovutils::OV_MDP_FLIP_H); - } - - if(layer->transform & HWC_TRANSFORM_FLIP_V) { - ovutils::setMdpFlags(mdpFlagsL, ovutils::OV_MDP_FLIP_V); - } - } else { - orient = static_cast(layer->transform); - } - - ovutils::eMdpFlags mdpFlagsR = mdpFlagsL; - ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER); - - hwc_rect_t tmp_cropL, tmp_dstL; - hwc_rect_t tmp_cropR, tmp_dstR; - - if(l_dest != ovutils::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(r_dest != ovutils::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(layer->transform & HWC_TRANSFORM_FLIP_V && - l_dest != ovutils::OV_INVALID && r_dest != ovutils::OV_INVALID ) { - 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; - - ALOGD_IF(isDebug(),"rects on V flip: \ - cropL(%d,%d,%d,%d) dstL(%d,%d,%d,%d) \ - cropR(%d,%d,%d,%d) dstR(%d,%d,%d,%d)", - tmp_cropL.left, tmp_cropL.top, tmp_cropL.right, tmp_cropL.bottom, - tmp_dstL.left, tmp_dstL.top, tmp_dstL.right, tmp_dstL.bottom, - tmp_cropR.left, tmp_cropR.top, tmp_cropR.right, tmp_cropR.bottom, - tmp_dstR.left, tmp_dstR.top, tmp_dstR.right, tmp_dstR.bottom); - } - - //**** configure left mixer **** - if(l_dest != ovutils::OV_INVALID) { - ovutils::PipeArgs pargL(mdpFlagsL, - info, - zOrder, - ovutils::IS_FG_OFF, - ovutils::ROT_FLAGS_NONE); - - ov.setSource(pargL, l_dest); - ov.setTransform(orient, l_dest); - ovutils::Dim dcropL(tmp_cropL.left, tmp_cropL.top, - tmp_cropL.right - tmp_cropL.left, - tmp_cropL.bottom - tmp_cropL.top); - ov.setCrop(dcropL, l_dest); - ovutils::Dim dimL(tmp_dstL.left , tmp_dstL.top, - tmp_dstL.right - tmp_dstL.left, - tmp_dstL.bottom - tmp_dstL.top); - ov.setPosition(dimL, l_dest); - - ALOGD_IF(isDebug(),"%s: MDP set: LEFT: \ - crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] pipeIndexL: %d zorder: %d", - __FUNCTION__, dcropL.x, dcropL.y,dcropL.w, dcropL.h, - dimL.x, dimL.y, dimL.w, dimL.h, - mdp_info.lIndex, mdp_info.zOrder); - - if (!ov.commit(l_dest)) { - ALOGE("%s: commit failed for left mixer config", __FUNCTION__); - return -1; - } - } - - //**** configure right mixer **** - if(r_dest != ovutils::OV_INVALID) { - ovutils::PipeArgs pargR(mdpFlagsR, - info, - zOrder, - ovutils::IS_FG_OFF, - ovutils::ROT_FLAGS_NONE); - - ov.setSource(pargR, r_dest); - ov.setTransform(orient, r_dest); - ovutils::Dim dcropR(tmp_cropR.left, tmp_cropR.top, - tmp_cropR.right - tmp_cropR.left, - tmp_cropR.bottom - tmp_cropR.top); - ov.setCrop(dcropR, r_dest); - ovutils::Dim dimR(tmp_dstR.left - hw_w/2, tmp_dstR.top, - tmp_dstR.right - tmp_dstR.left, - tmp_dstR.bottom - tmp_dstR.top); - ov.setPosition(dimR, r_dest); - - ALOGD_IF(isDebug(),"%s: MDP set: RIGHT: \ - crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] pipeIndexR: %d zorder: %d", - __FUNCTION__, dcropR.x, dcropR.y,dcropR.w, dcropR.h, - dimR.x, dimR.y, dimR.w, dimR.h, - mdp_info.rIndex, mdp_info.zOrder); - - if (!ov.commit(r_dest)) { - ALOGE("%s: commit failed for right mixer config", __FUNCTION__); - return -1; - } - } - - return 0; + MdpPipeInfoHighRes& mdp_info = + *(static_cast(pipeLayerPair.pipeInfo)); + eZorder zOrder = static_cast(mdp_info.zOrder); + eIsFg isFg = IS_FG_OFF; + eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION; + eDest lDest = mdp_info.lIndex; + eDest rDest = mdp_info.rIndex; + return configureHighRes(ctx, layer, dpy, mdpFlagsL, zOrder, isFg, lDest, + rDest, &pipeLayerPair.rot); } bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) { @@ -1006,6 +691,11 @@ bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) { for(int i = 0; i < numHwLayers; i++ ) { hwc_layer_1_t *layer = &list->hwLayers[i]; + private_handle_t *hnd = (private_handle_t *)layer->handle; + if(!hnd) { + ALOGE("%s handle null", __FUNCTION__); + return false; + } if(!(layerProp[i].mFlags & HWC_MDPCOMP)) { continue; @@ -1013,50 +703,44 @@ bool MDPCompHighRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) { MdpPipeInfoHighRes& pipe_info = *(MdpPipeInfoHighRes*)mCurrentFrame.pipeLayer[i].pipeInfo; + Rotator *rot = mCurrentFrame.pipeLayer[i].rot; + ovutils::eDest indexL = pipe_info.lIndex; ovutils::eDest indexR = pipe_info.rIndex; + int fd = hnd->fd; + int offset = hnd->offset; + + if(rot) { + rot->queueBuffer(fd, offset); + fd = rot->getDstMemId(); + offset = rot->getDstOffset(); + } //************* play left mixer ********** if(indexL != ovutils::OV_INVALID) { ovutils::eDest destL = (ovutils::eDest)indexL; - if (ctx ) { - private_handle_t *hnd = (private_handle_t *)layer->handle; - if(!hnd) { - ALOGE("%s handle null", __FUNCTION__); - return false; - } - - ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ - using pipe: %d", __FUNCTION__, layer, hnd, indexL ); - - if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) { - ALOGE("%s: queueBuffer failed for external", __FUNCTION__); - return false; - } + ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ + using pipe: %d", __FUNCTION__, layer, hnd, indexL ); + if (!ov.queueBuffer(fd, offset, destL)) { + ALOGE("%s: queueBuffer failed for left mixer", __FUNCTION__); + return false; } } //************* play right mixer ********** if(indexR != ovutils::OV_INVALID) { ovutils::eDest destR = (ovutils::eDest)indexR; - if (ctx ) { - private_handle_t *hnd = (private_handle_t *)layer->handle; - if(!hnd) { - ALOGE("%s handle null", __FUNCTION__); - return false; - } - - ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ - using pipe: %d", __FUNCTION__, layer, hnd, indexR ); - - if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) { - ALOGE("%s: queueBuffer failed for external", __FUNCTION__); - return false; - } + ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ + using pipe: %d", __FUNCTION__, layer, hnd, indexR ); + if (!ov.queueBuffer(fd, offset, destR)) { + ALOGE("%s: queueBuffer failed for right mixer", __FUNCTION__); + return false; } } + layerProp[i].mFlags &= ~HWC_MDPCOMP; } + return true; } }; //namespace diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h index fae460c2..926f6374 100644 --- a/libhwcomposer/hwc_mdpcomp.h +++ b/libhwcomposer/hwc_mdpcomp.h @@ -28,10 +28,13 @@ #define DEFAULT_IDLE_TIME 2000 #define MAX_PIPES_PER_MIXER 4 +namespace overlay { + class Rotator; +}; + namespace qhwc { namespace ovutils = overlay::utils; - class MDPComp { public: virtual ~MDPComp(){}; @@ -67,6 +70,7 @@ protected: struct PipeLayerPair { MdpPipeInfo *pipeInfo; native_handle_t* handle; + overlay::Rotator* rot; }; /* introduced for mixed mode implementation */ @@ -83,7 +87,7 @@ protected: hwc_display_contents_1_t* list,FrameInfo& current_frame) = 0; /* configures MPD pipes */ virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer, - MdpPipeInfo* mdp_info) = 0; + PipeLayerPair& pipeLayerPair) = 0; /* Is rotation supported */ virtual bool canRotate(){ return true; }; @@ -97,8 +101,6 @@ protected: eState getState() { return mState; }; /* reset state */ void reset( hwc_context_t *ctx, hwc_display_contents_1_t* list ); - /* configure MDP flags for video buffers */ - void setVidInfo(hwc_layer_1_t *layer, ovutils::eMdpFlags &mdpFlags); /* allocate MDP pipes from overlay */ ovutils::eDest getMdpPipe(hwc_context_t *ctx, ePipeType type); /* checks for conditions where mdpcomp is not possible */ @@ -136,7 +138,7 @@ private: /* configure's overlay pipes for the frame */ virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer, - MdpPipeInfo* mdp_info); + PipeLayerPair& pipeLayerPair); /* allocates pipes to selected candidates */ virtual bool allocLayerPipes(hwc_context_t *ctx, @@ -144,7 +146,7 @@ private: FrameInfo& current_frame); virtual int pipesNeeded(hwc_context_t *ctx, - hwc_display_contents_1_t* list); + hwc_display_contents_1_t* list); }; class MDPCompHighRes : public MDPComp { @@ -163,7 +165,7 @@ private: /* configure's overlay pipes for the frame */ virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer, - MdpPipeInfo* mdp_info); + PipeLayerPair& pipeLayerPair); /* allocates pipes to selected candidates */ virtual bool allocLayerPipes(hwc_context_t *ctx, diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp index 752aaa2d..d27128eb 100644 --- a/libhwcomposer/hwc_uevents.cpp +++ b/libhwcomposer/hwc_uevents.cpp @@ -27,6 +27,7 @@ #include #include "hwc_utils.h" #include "hwc_fbupdate.h" +#include "hwc_video.h" #include "hwc_copybit.h" #include "comptype.h" #include "external.h" @@ -115,6 +116,11 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) delete ctx->mFBUpdate[dpy]; ctx->mFBUpdate[dpy] = NULL; } + if(ctx->mVidOv[dpy]) { + Locker::Autolock _l(ctx->mExtSetLock); + delete ctx->mVidOv[dpy]; + ctx->mVidOv[dpy] = NULL; + } if(ctx->mCopyBit[dpy]){ Locker::Autolock _l(ctx->mExtSetLock); delete ctx->mCopyBit[dpy]; @@ -134,6 +140,8 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) ctx->mExtDisplay->processUEventOnline(udata); ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx->dpyAttr[dpy].xres, dpy); + ctx->mVidOv[dpy] = + IVideoOverlay::getObject(ctx->dpyAttr[dpy].xres, dpy); ctx->dpyAttr[dpy].isPause = false; if(usecopybit) ctx->mCopyBit[dpy] = new CopyBit(); diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp index e9446adb..74ab9e04 100644 --- a/libhwcomposer/hwc_utils.cpp +++ b/libhwcomposer/hwc_utils.cpp @@ -25,9 +25,11 @@ #include #include #include +#include #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 @@ void initContext(hwc_context_t *ctx) 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 @@ void initContext(hwc_context_t *ctx) 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 @@ void closeContext(hwc_context_t *ctx) 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 @@ void closeContext(hwc_context_t *ctx) 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 @@ int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy, 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(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(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(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(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(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 @@ void LayerCache::markCachedLayersAsOverlay(hwc_display_contents_1_t* list) { } } } - } -};//namespace +};//namespace qhwc diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h index de62b05d..67745f45 100644 --- a/libhwcomposer/hwc_utils.h +++ b/libhwcomposer/hwc_utils.h @@ -27,6 +27,8 @@ #include #include #include +#include "qdMetaData.h" +#include #define ALIGN_TO(x, align) (((x) + ((align)-1)) & ~((align)-1)) #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) @@ -44,8 +46,12 @@ struct hwc_context_t; struct framebuffer_device_t; +namespace ovutils = overlay::utils; + namespace overlay { class Overlay; +class Rotator; +class RotMgr; } namespace qhwc { @@ -53,6 +59,7 @@ namespace qhwc { class QueuedBufferStore; class ExternalDisplay; class IFBUpdate; +class IVideoOverlay; class MDPComp; class CopyBit; @@ -121,9 +128,6 @@ class LayerCache { }; - - - // ----------------------------------------------------------------------------- // Utility functions - implemented in hwc_utils.cpp void dumpLayer(hwc_layer_1_t const* l); @@ -154,7 +158,28 @@ void closeAcquireFds(hwc_display_contents_1_t* list); //Sync point impl. int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy, - int fd); + int fd); + +//Trims a layer's source crop which is outside of screen boundary. +void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform, + hwc_rect_t& crop, hwc_rect_t& dst); + +//Sets appropriate mdp flags for a layer. +void setMdpFlags(hwc_layer_1_t *layer, + ovutils::eMdpFlags &mdpFlags, + int rotDownscale = 0); + +//Routine to configure low resolution panels (<= 2048 width) +int configureLowRes(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy, + ovutils::eMdpFlags& mdpFlags, const ovutils::eZorder& z, + const ovutils::eIsFg& isFg, const ovutils::eDest& dest, + overlay::Rotator **rot); + +//Routine to configure high resolution panels (> 2048 width) +int configureHighRes(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy, + ovutils::eMdpFlags& mdpFlags, const ovutils::eZorder& z, + const ovutils::eIsFg& isFg, const ovutils::eDest& lDest, + const ovutils::eDest& rDest, overlay::Rotator **rot); // Inline utility functions static inline bool isSkipLayer(const hwc_layer_1_t* l) { @@ -245,9 +270,12 @@ struct hwc_context_t { //Overlay object - NULL for non overlay devices overlay::Overlay *mOverlay; + //Holds a few rot objects + overlay::RotMgr *mRotMgr; //Primary and external FB updater qhwc::IFBUpdate *mFBUpdate[MAX_DISPLAYS]; + qhwc::IVideoOverlay *mVidOv[MAX_DISPLAYS]; // External display related information qhwc::ExternalDisplay *mExtDisplay; qhwc::MDPInfo mMDP; @@ -273,6 +301,7 @@ struct hwc_context_t { bool mDMAInUse; }; +namespace qhwc { static inline bool isSkipPresent (hwc_context_t *ctx, int dpy) { return ctx->listStats[dpy].skipCount; } @@ -280,5 +309,6 @@ static inline bool isSkipPresent (hwc_context_t *ctx, int dpy) { static inline bool isYuvPresent (hwc_context_t *ctx, int dpy) { return ctx->listStats[dpy].yuvCount; } +}; #endif //HWC_UTILS_H diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp index edd0ba88..2166a5b3 100644 --- a/libhwcomposer/hwc_video.cpp +++ b/libhwcomposer/hwc_video.cpp @@ -24,26 +24,36 @@ #include "hwc_utils.h" #include "qdMetaData.h" #include "mdp_version.h" +#include + +using overlay::Rotator; namespace qhwc { namespace ovutils = overlay::utils; -//Static Members -bool VideoOverlay::sIsModeOn[] = {false}; -ovutils::eDest VideoOverlay::sDest[] = {ovutils::OV_INVALID}; +//===========IVideoOverlay========================= +IVideoOverlay* IVideoOverlay::getObject(const int& width, const int& dpy) { + if(width > MAX_DISPLAY_DIM) { + return new VideoOverlayHighRes(dpy); + } + return new VideoOverlayLowRes(dpy); +} + +//===========VideoOverlayLowRes========================= + +VideoOverlayLowRes::VideoOverlayLowRes(const int& dpy): IVideoOverlay(dpy) {} //Cache stats, figure out the state, config overlay -bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list, - int dpy) { +bool VideoOverlayLowRes::prepare(hwc_context_t *ctx, + hwc_display_contents_1_t *list) { - if(ctx->listStats[dpy].yuvCount > 1) + if(ctx->listStats[mDpy].yuvCount > 1) return false; - int yuvIndex = ctx->listStats[dpy].yuvIndices[0]; - sIsModeOn[dpy] = false; - - int hw_w = ctx->dpyAttr[dpy].xres; + int yuvIndex = ctx->listStats[mDpy].yuvIndices[0]; + int hw_w = ctx->dpyAttr[mDpy].xres; + mModeOn = false; if(hw_w > MAX_DISPLAY_DIM) { ALOGD_IF(VIDEO_DEBUG,"%s, \ @@ -61,7 +71,7 @@ bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list, return false; } - if(yuvIndex == -1 || ctx->listStats[dpy].yuvCount != 1) { + if(yuvIndex == -1 || ctx->listStats[mDpy].yuvCount != 1) { return false; } @@ -83,126 +93,55 @@ bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list, } } } - if(configure(ctx, dpy, layer)) { + + if(configure(ctx, layer)) { markFlags(layer); - sIsModeOn[dpy] = true; + mModeOn = true; } - return sIsModeOn[dpy]; + return mModeOn; } -void VideoOverlay::markFlags(hwc_layer_1_t *layer) { +void VideoOverlayLowRes::markFlags(hwc_layer_1_t *layer) { if(layer) { layer->compositionType = HWC_OVERLAY; layer->hints |= HWC_HINT_CLEAR_FB; } } -bool VideoOverlay::configure(hwc_context_t *ctx, int dpy, +bool VideoOverlayLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer) { + overlay::Overlay& ov = *(ctx->mOverlay); private_handle_t *hnd = (private_handle_t *)layer->handle; - ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); + ovutils::Whf info(hnd->width, hnd->height, + ovutils::getMdpFormat(hnd->format), hnd->size); //Request a VG pipe - ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy); + ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy); if(dest == ovutils::OV_INVALID) { //None available return false; } - sDest[dpy] = dest; - + mDest = dest; ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; - if (isSecureBuffer(hnd)) { - ovutils::setMdpFlags(mdpFlags, - ovutils::OV_MDP_SECURE_OVERLAY_SESSION); + ovutils::eZorder zOrder = ovutils::ZORDER_1; + ovutils::eIsFg isFg = ovutils::IS_FG_OFF; + if (ctx->listStats[mDpy].numAppLayers == 1) { + isFg = ovutils::IS_FG_SET; } - if(layer->blending == HWC_BLENDING_PREMULT) { - ovutils::setMdpFlags(mdpFlags, - ovutils::OV_MDP_BLEND_FG_PREMULT); - } - - MetaData_t *metadata = (MetaData_t *)hnd->base_metadata; - if (metadata && (metadata->operation & PP_PARAM_INTERLACED) && - metadata->interlaced) { - ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_DEINTERLACE); - } - - ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF; - if (ctx->listStats[dpy].numAppLayers == 1) { - isFgFlag = ovutils::IS_FG_SET; - } - - ovutils::eRotFlags rotFlags = ovutils::ROT_FLAGS_NONE; - if(ctx->mMDP.version >= qdutils::MDP_V4_2 && - ctx->mMDP.version < qdutils::MDSS_V5) { - rotFlags = ovutils::ROT_DOWNSCALE_ENABLED; - } - - ovutils::PipeArgs parg(mdpFlags, - info, - ovutils::ZORDER_1, - isFgFlag, - rotFlags); - - ov.setSource(parg, dest); - - int transform = layer->transform; - ovutils::eTransform orient = - static_cast(transform); - - hwc_rect_t sourceCrop = layer->sourceCrop; - hwc_rect_t displayFrame = layer->displayFrame; - - //Calculate the rect for primary based on whether the supplied position - //is within or outside bounds. - const int fbWidth = ctx->dpyAttr[dpy].xres; - const int fbHeight = ctx->dpyAttr[dpy].yres; - - if( displayFrame.left < 0 || - displayFrame.top < 0 || - displayFrame.right > fbWidth || - displayFrame.bottom > fbHeight) { - hwc_rect_t scissor = {0, 0, fbWidth, fbHeight}; - calculate_crop_rects(sourceCrop, displayFrame, scissor, transform); - } - - // source crop x,y,w,h - ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top, - sourceCrop.right - sourceCrop.left, - sourceCrop.bottom - sourceCrop.top); - //Only for Primary - ov.setCrop(dcrop, dest); - - ov.setTransform(orient, dest); - - // position x,y,w,h - 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(dpy) - getActionSafePosition(ctx, dpy, dpos.x, dpos.y, dpos.w, dpos.h); - - ov.setPosition(dpos, dest); - - if (!ov.commit(dest)) { - ALOGE("%s: commit fails", __FUNCTION__); - return false; - } - return true; + return (configureLowRes(ctx, layer, mDpy, mdpFlags, zOrder, isFg, dest, + &mRot) == 0 ); } -bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list, - int dpy) -{ - if(!sIsModeOn[dpy]) { +bool VideoOverlayLowRes::draw(hwc_context_t *ctx, + hwc_display_contents_1_t *list) { + if(!mModeOn) { return true; } - int yuvIndex = ctx->listStats[dpy].yuvIndices[0]; + int yuvIndex = ctx->listStats[mDpy].yuvIndices[0]; if(yuvIndex == -1) { return true; } @@ -210,16 +149,148 @@ bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list, private_handle_t *hnd = (private_handle_t *) list->hwLayers[yuvIndex].handle; - bool ret = true; overlay::Overlay& ov = *(ctx->mOverlay); + int fd = hnd->fd; + uint32_t offset = hnd->offset; + Rotator *rot = mRot; - if (!ov.queueBuffer(hnd->fd, hnd->offset, - sDest[dpy])) { - ALOGE("%s: queueBuffer failed for dpy=%d", __FUNCTION__, dpy); - ret = false; + if(rot) { + if(!rot->queueBuffer(fd, offset)) + return false; + fd = rot->getDstMemId(); + offset = rot->getDstOffset(); } - return ret; + if (!ov.queueBuffer(fd, offset, mDest)) { + ALOGE("%s: queueBuffer failed for dpy=%d", __FUNCTION__, mDpy); + return false; + } + + return true; } +//===========VideoOverlayHighRes========================= + +VideoOverlayHighRes::VideoOverlayHighRes(const int& dpy): IVideoOverlay(dpy) {} + +//Cache stats, figure out the state, config overlay +bool VideoOverlayHighRes::prepare(hwc_context_t *ctx, + hwc_display_contents_1_t *list) { + + int yuvIndex = ctx->listStats[mDpy].yuvIndices[0]; + int hw_w = ctx->dpyAttr[mDpy].xres; + mModeOn = false; + + if(!ctx->mMDP.hasOverlay) { + ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__); + return false; + } + + if(yuvIndex == -1 || ctx->listStats[mDpy].yuvCount != 1) { + return false; + } + + //index guaranteed to be not -1 at this point + hwc_layer_1_t *layer = &list->hwLayers[yuvIndex]; + if(configure(ctx, layer)) { + markFlags(layer); + mModeOn = true; + } + + return mModeOn; +} + +void VideoOverlayHighRes::markFlags(hwc_layer_1_t *layer) { + if(layer) { + layer->compositionType = HWC_OVERLAY; + layer->hints |= HWC_HINT_CLEAR_FB; + } +} + +bool VideoOverlayHighRes::configure(hwc_context_t *ctx, + hwc_layer_1_t *layer) { + + int hw_w = ctx->dpyAttr[mDpy].xres; + overlay::Overlay& ov = *(ctx->mOverlay); + private_handle_t *hnd = (private_handle_t *)layer->handle; + ovutils::Whf info(hnd->width, hnd->height, + ovutils::getMdpFormat(hnd->format), hnd->size); + + //Request a VG pipe + mDestL = ovutils::OV_INVALID; + mDestR = ovutils::OV_INVALID; + hwc_rect_t dst = layer->displayFrame; + if(dst.left > hw_w/2) { + mDestR = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy); + if(mDestR == ovutils::OV_INVALID) + return false; + } else if (dst.right <= hw_w/2) { + mDestL = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy); + if(mDestL == ovutils::OV_INVALID) + return false; + } else { + mDestL = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy); + mDestR = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy); + if(mDestL == ovutils::OV_INVALID || + mDestR == ovutils::OV_INVALID) + return false; + } + + ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; + ovutils::eZorder zOrder = ovutils::ZORDER_1; + ovutils::eIsFg isFg = ovutils::IS_FG_OFF; + if (ctx->listStats[mDpy].numAppLayers == 1) { + isFg = ovutils::IS_FG_SET; + } + + return (configureHighRes(ctx, layer, mDpy, mdpFlags, zOrder, isFg, mDestL, + mDestR, &mRot) == 0 ); +} + +bool VideoOverlayHighRes::draw(hwc_context_t *ctx, + hwc_display_contents_1_t *list) { + if(!mModeOn) { + return true; + } + + int yuvIndex = ctx->listStats[mDpy].yuvIndices[0]; + if(yuvIndex == -1) { + return true; + } + + private_handle_t *hnd = (private_handle_t *) + list->hwLayers[yuvIndex].handle; + + overlay::Overlay& ov = *(ctx->mOverlay); + int fd = hnd->fd; + uint32_t offset = hnd->offset; + Rotator *rot = mRot; + + if(rot) { + if(!rot->queueBuffer(fd, offset)) + return false; + fd = rot->getDstMemId(); + offset = rot->getDstOffset(); + } + + if(mDestL != ovutils::OV_INVALID) { + if (!ov.queueBuffer(fd, offset, mDestL)) { + ALOGE("%s: queueBuffer failed for dpy=%d's left mixer", + __FUNCTION__, mDpy); + return false; + } + } + + if(mDestR != ovutils::OV_INVALID) { + if (!ov.queueBuffer(fd, offset, mDestR)) { + ALOGE("%s: queueBuffer failed for dpy=%d's right mixer" + , __FUNCTION__, mDpy); + return false; + } + } + + return true; +} + + }; //namespace qhwc diff --git a/libhwcomposer/hwc_video.h b/libhwcomposer/hwc_video.h index 93cdaa5c..4acde9d8 100644 --- a/libhwcomposer/hwc_video.h +++ b/libhwcomposer/hwc_video.h @@ -23,38 +23,80 @@ #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) +namespace overlay { + class Rotator; +} + namespace qhwc { namespace ovutils = overlay::utils; -//Feature for using overlay to display videos. -class VideoOverlay { +class IVideoOverlay { public: - //Sets up members and prepares overlay if conditions are met - static bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list, - int dpy); - //Draws layer if this feature is on - static bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list, - int dpy); - //resets values - static void reset(); -private: - //Configures overlay for video prim and ext - static bool configure(hwc_context_t *ctx, int dpy, - hwc_layer_1_t *yuvlayer); - - //Marks layer flags if this feature is used - static void markFlags(hwc_layer_1_t *yuvLayer); - //Flags if this feature is on. - static bool sIsModeOn[MAX_DISPLAYS]; - static ovutils::eDest sDest[MAX_DISPLAYS]; + explicit IVideoOverlay(const int& dpy) : mDpy(dpy), mModeOn(false), + mRot(NULL) {} + virtual ~IVideoOverlay() {}; + virtual bool prepare(hwc_context_t *ctx, + hwc_display_contents_1_t *list) = 0; + virtual bool draw(hwc_context_t *ctx, + hwc_display_contents_1_t *list) = 0; + virtual void reset() = 0; + //Factory method that returns a low-res or high-res version + static IVideoOverlay *getObject(const int& width, const int& dpy); +protected: + const int mDpy; // display to update + bool mModeOn; // if prepare happened + overlay::Rotator *mRot; }; -inline void VideoOverlay::reset() { - for(uint32_t i = 0; i < MAX_DISPLAYS; i++) { - sIsModeOn[i] = false; - sDest[i] = ovutils::OV_INVALID; - } +class VideoOverlayLowRes : public IVideoOverlay { +public: + explicit VideoOverlayLowRes(const int& dpy); + virtual ~VideoOverlayLowRes() {}; + bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list); + bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list); + void reset(); +private: + //Configures overlay for video prim and ext + bool configure(hwc_context_t *ctx, hwc_layer_1_t *yuvlayer); + //Marks layer flags if this feature is used + void markFlags(hwc_layer_1_t *yuvLayer); + //Flags if this feature is on. + bool mModeOn; + ovutils::eDest mDest; +}; + +class VideoOverlayHighRes : public IVideoOverlay { +public: + explicit VideoOverlayHighRes(const int& dpy); + virtual ~VideoOverlayHighRes() {}; + bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list); + bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list); + void reset(); +private: + //Configures overlay for video prim and ext + bool configure(hwc_context_t *ctx, hwc_layer_1_t *yuvlayer); + //Marks layer flags if this feature is used + void markFlags(hwc_layer_1_t *yuvLayer); + //Flags if this feature is on. + bool mModeOn; + ovutils::eDest mDestL; + ovutils::eDest mDestR; +}; + +//=================Inlines====================== +inline void VideoOverlayLowRes::reset() { + mModeOn = false; + mDest = ovutils::OV_INVALID; + mRot = NULL; } + +inline void VideoOverlayHighRes::reset() { + mModeOn = false; + mDestL = ovutils::OV_INVALID; + mDestR = ovutils::OV_INVALID; + mRot = NULL; +} + }; //namespace qhwc #endif //HWC_VIDEO_H diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk index 82c6610c..ed2f5037 100644 --- a/liboverlay/Android.mk +++ b/liboverlay/Android.mk @@ -11,7 +11,6 @@ LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdoverlay\" LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) LOCAL_SRC_FILES := \ overlay.cpp \ - overlayCtrl.cpp \ overlayUtils.cpp \ overlayMdp.cpp \ overlayRotator.cpp \ diff --git a/liboverlay/overlayCtrl.cpp b/liboverlay/overlayCtrl.cpp deleted file mode 100644 index 2cbf1c57..00000000 --- a/liboverlay/overlayCtrl.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* -* Copyright (C) 2008 The Android Open Source Project -* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include -#include "overlayCtrlData.h" -#include "fb_priv.h" -#include "gralloc_priv.h" //for interlace - -namespace overlay{ - -bool Ctrl::init(uint32_t fbnum) { - // MDP/FD init - if(!mMdp.init(fbnum)) { - ALOGE("Ctrl failed to init fbnum=%d", fbnum); - return false; - } - - if(!getScreenInfo(mInfo)) { - ALOGE("Ctrl failed to getScreenInfo"); - return false; - } - - return true; -} - -bool Ctrl::setSource(const utils::PipeArgs& args) -{ - return mMdp.setSource(args); -} - -bool Ctrl::setPosition(const utils::Dim& dim) -{ - if(!dim.check(mInfo.mFBWidth, mInfo.mFBHeight)) { - ALOGE("Ctrl setPosition error in dim"); - dim.dump(); - return false; - } - - if(!mMdp.setPosition(dim, mInfo.mFBWidth, mInfo.mFBHeight)) { - ALOGE("Ctrl failed MDP setPosition"); - return false; - } - return true; -} - -bool Ctrl::setTransform(const utils::eTransform& orient) -{ - if(!mMdp.setTransform(orient)) { - ALOGE("Ctrl setTransform failed for Mdp"); - return false; - } - return true; -} - -void Ctrl::setRotatorUsed(const bool& rotUsed) { - mMdp.setRotatorUsed(rotUsed); -} - -bool Ctrl::setCrop(const utils::Dim& d) -{ - if(!mMdp.setCrop(d)) { - ALOGE("Data setCrop failed in MDP setCrop"); - return false; - } - return true; -} - -utils::FrameBufferInfo* utils::FrameBufferInfo::sFBInfoInstance = 0; - -void Ctrl::dump() const { - ALOGE("== Dump Ctrl start =="); - mInfo.dump("mInfo"); - mMdp.dump(); - ALOGE("== Dump Ctrl end =="); -} - -} // overlay diff --git a/liboverlay/overlayCtrlData.h b/liboverlay/overlayCtrlData.h index c9a4949e..53958344 100644 --- a/liboverlay/overlayCtrlData.h +++ b/liboverlay/overlayCtrlData.h @@ -58,15 +58,13 @@ public: bool close(); /* set source using whf, orient and wait flag */ - bool setSource(const utils::PipeArgs& args); + void setSource(const utils::PipeArgs& args); /* set crop info and pass it down to mdp */ - bool setCrop(const utils::Dim& d); + void setCrop(const utils::Dim& d); /* set orientation */ - bool setTransform(const utils::eTransform& p); - /* set whether rotator can be used */ - void setRotatorUsed(const bool& rotUsed); + void setTransform(const utils::eTransform& p); /* set mdp position using dim */ - bool setPosition(const utils::Dim& dim); + void setPosition(const utils::Dim& dim); /* mdp set overlay/commit changes */ bool commit(); @@ -74,40 +72,21 @@ public: int getPipeId() const; /* ctrl fd */ int getFd() const; - - /* access for screen info */ - utils::ScreenInfo getScreenInfo() const; - - /* retrieve cached crop data */ + /* retrieve crop data */ utils::Dim getCrop() const; - - /* Perform transformation calculations */ - void doTransform(); - - /* Performs downscale calculations */ - void doDownscale(int dscale_factor); - - /* Get downscale factor */ - int getDownscalefactor(); - - /* Update the src format */ - void updateSrcformat(const uint32_t& inputsrcFormat); - + utils::Dim getPosition() const; + /* Set downscale */ + void setDownscale(int dscale_factor); + /* Update the src format based on rotator's dest */ + void updateSrcFormat(const uint32_t& rotDstFormat); /* dump the state of the object */ void dump() const; - /* Return the dump in the specified buffer */ void getDump(char *buf, size_t len); private: - /* Retrieve screen info from underlying mdp */ - bool getScreenInfo(utils::ScreenInfo& info); - // mdp ctrl struct(info e.g.) MdpCtrl mMdp; - - /* Screen info */ - utils::ScreenInfo mInfo; }; @@ -115,28 +94,20 @@ class Data : utils::NoCopy { public: /* init, reset */ explicit Data(); - /* calls close */ ~Data(); - /* init fd etc */ bool init(uint32_t fbnum); - /* calls underlying mdp close */ bool close(); - /* set overlay pipe id in the mdp struct */ void setPipeId(int id); - /* get overlay id in the mdp struct */ int getPipeId() const; - /* queue buffer to the overlay */ bool queueBuffer(int fd, uint32_t offset); - /* sump the state of the obj */ void dump() const; - /* Return the dump in the specified buffer */ void getDump(char *buf, size_t len); @@ -171,17 +142,44 @@ inline bool Ctrl::close() { return true; } -inline bool Ctrl::commit() { - if(!mMdp.set()) { - ALOGE("Ctrl commit failed set overlay"); +inline bool Ctrl::init(uint32_t fbnum) { + // MDP/FD init + if(!mMdp.init(fbnum)) { + ALOGE("Ctrl failed to init fbnum=%d", fbnum); return false; } return true; } -inline bool Ctrl::getScreenInfo(utils::ScreenInfo& info) { - if(!mMdp.getScreenInfo(info)){ - ALOGE("Ctrl failed to get screen info"); +inline void Ctrl::setSource(const utils::PipeArgs& args) +{ + mMdp.setSource(args); +} + +inline void Ctrl::setPosition(const utils::Dim& dim) +{ + mMdp.setPosition(dim); +} + +inline void Ctrl::setTransform(const utils::eTransform& orient) +{ + mMdp.setTransform(orient); +} + +inline void Ctrl::setCrop(const utils::Dim& d) +{ + mMdp.setCrop(d); +} + +inline void Ctrl::dump() const { + ALOGE("== Dump Ctrl start =="); + mMdp.dump(); + ALOGE("== Dump Ctrl end =="); +} + +inline bool Ctrl::commit() { + if(!mMdp.set()) { + ALOGE("Ctrl commit failed set overlay"); return false; } return true; @@ -195,28 +193,20 @@ inline int Ctrl::getFd() const { return mMdp.getFd(); } -inline void Ctrl::updateSrcformat(const uint32_t& inputsrcFormat) { - mMdp.updateSrcformat(inputsrcFormat); -} - -inline utils::ScreenInfo Ctrl::getScreenInfo() const { - return mInfo; +inline void Ctrl::updateSrcFormat(const uint32_t& rotDstFmt) { + mMdp.updateSrcFormat(rotDstFmt); } inline utils::Dim Ctrl::getCrop() const { return mMdp.getSrcRectDim(); } -inline void Ctrl::doTransform() { - return mMdp.doTransform(); +inline utils::Dim Ctrl::getPosition() const { + return mMdp.getDstRectDim(); } -inline void Ctrl::doDownscale(int dscale_factor) { - mMdp.doDownscale(dscale_factor); -} - -inline int Ctrl::getDownscalefactor() { - return mMdp.getDownscalefactor(); +inline void Ctrl::setDownscale(int dscale_factor) { + mMdp.setDownscale(dscale_factor); } inline void Ctrl::getDump(char *buf, size_t len) { diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp index 8f2e2b6d..d96066bd 100644 --- a/liboverlay/overlayMdp.cpp +++ b/liboverlay/overlayMdp.cpp @@ -52,12 +52,11 @@ void MdpCtrl::reset() { mOVInfo.id = MSMFB_NEW_REQUEST; mLkgo.id = MSMFB_NEW_REQUEST; mOrientation = utils::OVERLAY_TRANSFORM_0; - mRotUsed = false; + mDownscale = 0; } bool MdpCtrl::close() { bool result = true; - if(MSMFB_NEW_REQUEST != static_cast(mOVInfo.id)) { if(!mdp_wrapper::unsetOverlay(mFd.getFD(), mOVInfo.id)) { ALOGE("MdpCtrl close error in unset"); @@ -66,6 +65,7 @@ bool MdpCtrl::close() { } reset(); + if(!mFd.close()) { result = false; } @@ -73,8 +73,7 @@ bool MdpCtrl::close() { return result; } -bool MdpCtrl::setSource(const utils::PipeArgs& args) { - +void MdpCtrl::setSource(const utils::PipeArgs& args) { setSrcWhf(args.whf); //TODO These are hardcoded. Can be moved out of setSource. @@ -85,111 +84,44 @@ bool MdpCtrl::setSource(const utils::PipeArgs& args) { setFlags(args.mdpFlags); setZ(args.zorder); setIsFg(args.isFg); - return true; } -bool MdpCtrl::setCrop(const utils::Dim& d) { +void MdpCtrl::setCrop(const utils::Dim& d) { setSrcRectDim(d); - return true; } -bool MdpCtrl::setPosition(const overlay::utils::Dim& d, - int fbw, int fbh) -{ - ovutils::Dim dim(d); - ovutils::Dim ovsrcdim = getSrcRectDim(); - // Scaling of upto a max of 20 times supported - if(dim.w >(ovsrcdim.w * ovutils::HW_OV_MAGNIFICATION_LIMIT)){ - dim.w = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.w; - dim.x = (fbw - dim.w) / 2; - } - if(dim.h >(ovsrcdim.h * ovutils::HW_OV_MAGNIFICATION_LIMIT)) { - dim.h = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.h; - dim.y = (fbh - dim.h) / 2; - } - - setDstRectDim(dim); - return true; +void MdpCtrl::setPosition(const overlay::utils::Dim& d) { + setDstRectDim(d); } -bool MdpCtrl::setTransform(const utils::eTransform& orient) { +void MdpCtrl::setTransform(const utils::eTransform& orient) { int rot = utils::getMdpOrient(orient); setUserData(rot); //getMdpOrient will switch the flips if the source is 90 rotated. //Clients in Android dont factor in 90 rotation while deciding the flip. mOrientation = static_cast(rot); - - return true; -} - -void MdpCtrl::setRotatorUsed(const bool& rotUsed) { - //rotUsed dictates whether rotator hardware can be used. - //It is set if transformation or downscaling is required. - mRotUsed = rotUsed; } void MdpCtrl::doTransform() { - adjustSrcWhf(mRotUsed); setRotationFlags(); - //180 will be H + V - //270 will be H + V + 90 - if(mOrientation & utils::OVERLAY_TRANSFORM_FLIP_H) { - overlayTransFlipH(); - } - if(mOrientation & utils::OVERLAY_TRANSFORM_FLIP_V) { - overlayTransFlipV(); - } - if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) { - overlayTransRot90(); - } + utils::Whf whf = getSrcWhf(); + utils::Dim dim = getSrcRectDim(); + utils::preRotateSource(mOrientation, whf, dim); + setSrcWhf(whf); + setSrcRectDim(dim); } -int MdpCtrl::getDownscalefactor() { - int dscale_factor = utils::ROT_DS_NONE; - int src_w = mOVInfo.src_rect.w; - int src_h = mOVInfo.src_rect.h; - int dst_w = mOVInfo.dst_rect.w; - int dst_h = mOVInfo.dst_rect.h; - // We need this check to engage the rotator whenever possible to assist MDP - // in performing video downscale. - // This saves bandwidth and avoids causing the driver to make too many panel - // -mode switches between BLT (writeback) and non-BLT (Direct) modes. - // Use-case: Video playback [with downscaling and rotation]. - - if (dst_w && dst_h) - { - uint32_t dscale = (src_w * src_h) / (dst_w * dst_h); - - if(dscale < 2) { - // Down-scale to > 50% of orig. - dscale_factor = utils::ROT_DS_NONE; - } else if(dscale < 4) { - // Down-scale to between > 25% to <= 50% of orig. - dscale_factor = utils::ROT_DS_HALF; - } else if(dscale < 8) { - // Down-scale to between > 12.5% to <= 25% of orig. - dscale_factor = utils::ROT_DS_FOURTH; - } else { - // Down-scale to <= 12.5% of orig. - dscale_factor = utils::ROT_DS_EIGHTH; - } - } - - return dscale_factor; -} - -void MdpCtrl::doDownscale(int dscale_factor) { - - if( dscale_factor ) { - mOVInfo.src_rect.x >>= dscale_factor; - mOVInfo.src_rect.y >>= dscale_factor; - mOVInfo.src_rect.w >>= dscale_factor; - mOVInfo.src_rect.h >>= dscale_factor; - } +void MdpCtrl::doDownscale() { + mOVInfo.src_rect.x >>= mDownscale; + mOVInfo.src_rect.y >>= mDownscale; + mOVInfo.src_rect.w >>= mDownscale; + mOVInfo.src_rect.h >>= mDownscale; } bool MdpCtrl::set() { //deferred calcs, so APIs could be called in any order. + doTransform(); + doDownscale(); utils::Whf whf = getSrcWhf(); if(utils::isYuv(whf.format)) { normalizeCrop(mOVInfo.src_rect.x, mOVInfo.src_rect.w); @@ -213,23 +145,6 @@ bool MdpCtrl::set() { return true; } -bool MdpCtrl::getScreenInfo(overlay::utils::ScreenInfo& info) { - fb_fix_screeninfo finfo; - if (!mdp_wrapper::getFScreenInfo(mFd.getFD(), finfo)) { - return false; - } - - fb_var_screeninfo vinfo; - if (!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) { - return false; - } - info.mFBWidth = vinfo.xres; - info.mFBHeight = vinfo.yres; - info.mFBbpp = vinfo.bits_per_pixel; - info.mFBystride = finfo.line_length; - return true; -} - bool MdpCtrl::get() { mdp_overlay ov; ov.id = mOVInfo.id; @@ -241,24 +156,10 @@ bool MdpCtrl::get() { return true; } -//Adjust width, height if rotator is used post transform calcs. -//At this point the format is already updated by updateSrcFormat -void MdpCtrl::adjustSrcWhf(const bool& rotUsed) { - if(rotUsed) { - utils::Whf whf = getSrcWhf(); - if(whf.format == MDP_Y_CRCB_H2V2_TILE || - whf.format == MDP_Y_CBCR_H2V2_TILE) { - whf.w = utils::alignup(whf.w, 64); - whf.h = utils::alignup(whf.h, 32); - } - setSrcWhf(whf); - } -} - -//Update src format if rotator used based on rotator's destination format. -void MdpCtrl::updateSrcformat(const uint32_t& inputformat) { +//Update src format based on rotator's destination format. +void MdpCtrl::updateSrcFormat(const uint32_t& rotDestFmt) { utils::Whf whf = getSrcWhf(); - whf.format = inputformat; + whf.format = rotDestFmt; setSrcWhf(whf); } diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h index 55e27876..7d3bbee8 100644 --- a/liboverlay/overlayMdp.h +++ b/liboverlay/overlayMdp.h @@ -33,151 +33,92 @@ class MdpCtrl { public: /* ctor reset */ explicit MdpCtrl(); - /* dtor close */ ~MdpCtrl(); - /* init underlying device using fbnum */ bool init(uint32_t fbnum); - /* unset overlay, reset and close fd */ bool close(); - /* reset and set ov id to -1 / MSMFB_NEW_REQUEST */ void reset(); - - /* get orient / user_data[0] */ - int getOrient() const; - - /* returns session id */ - int getPipeId() const; - - /* returns the fd associated to ctrl*/ - int getFd() const; - - /* Get screen info. out: info*/ - bool getScreenInfo(utils::ScreenInfo& info); - - /* overlay get */ - bool get(); - - /* returns flags from mdp structure */ - int getFlags() const; - - /* set flags to mdp structure */ - void setFlags(int f); - - /* set z order */ - void setZ(utils::eZorder z); - - /* set isFg flag */ - void setIsFg(utils::eIsFg isFg); - /* calls overlay set * Set would always consult last good known ov instance. * Only if it is different, set would actually exectue ioctl. * On a sucess ioctl. last good known ov instance is updated */ bool set(); - - /* return a copy of src whf*/ - utils::Whf getSrcWhf() const; - - /* set src whf */ - void setSrcWhf(const utils::Whf& whf); - - /* adjust source width height format based on rot info */ - void adjustSrcWhf(const bool& rotUsed); - - /* swap src w/h*/ - void swapSrcWH(); - - /* swap src rect w/h */ - void swapSrcRectWH(); - - /* returns a copy to src rect dim */ - utils::Dim getSrcRectDim() const; - - /* set src/dst rect dim */ - void setSrcRectDim(const utils::Dim d); - void setDstRectDim(const utils::Dim d); - - /* returns a copy ro dst rect dim */ - utils::Dim getDstRectDim() const; - - /* returns user_data[0]*/ - int getUserData() const; - - /* sets user_data[0] */ - void setUserData(int v); - - /* return true if current overlay is different - * than last known good overlay */ - bool ovChanged() const; - - /* save mOVInfo to be last known good ov*/ - void save(); - - /* restore last known good ov to be the current */ - void restore(); - /* Sets the source total width, height, format */ - bool setSource(const utils::PipeArgs& pargs); - + void setSource(const utils::PipeArgs& pargs); /* * Sets ROI, the unpadded region, for source buffer. - * Should be called before a setPosition, for small clips. * Dim - ROI dimensions. */ - bool setCrop(const utils::Dim& d); - - bool setTransform(const utils::eTransform& orient); - - /* set whether rotator can be used */ - void setRotatorUsed(const bool& rotUsed); - + void setCrop(const utils::Dim& d); + void setTransform(const utils::eTransform& orient); /* given a dim and w/h, set overlay dim */ - bool setPosition(const utils::Dim& dim, int w, int h); - + void setPosition(const utils::Dim& dim); /* using user_data, sets/unsets roationvalue in mdp flags */ void setRotationFlags(); - - /* Perform transformation calculations */ - void doTransform(); - /* Performs downscale calculations */ - void doDownscale(int dscale_factor); - - /* Get downscale factor */ - int getDownscalefactor(); - - /* Update the src format */ - void updateSrcformat(const uint32_t& inputsrcFormat); - + void setDownscale(int dscale_factor); + /* Update the src format with rotator's dest*/ + void updateSrcFormat(const uint32_t& rotDstFormat); /* dump state of the object */ void dump() const; - /* Return the dump in the specified buffer */ void getDump(char *buf, size_t len); -private: + /* returns session id */ + int getPipeId() const; + /* returns the fd associated to ctrl*/ + int getFd() const; + /* returns a copy ro dst rect dim */ + utils::Dim getDstRectDim() const; + /* returns a copy to src rect dim */ + utils::Dim getSrcRectDim() const; - /* helper functions for overlayTransform */ - void overlayTransFlipH(); - void overlayTransFlipV(); - void overlayTransRot90(); +private: + /* Perform transformation calculations */ + void doTransform(); + void doDownscale(); + /* get orient / user_data[0] */ + int getOrient() const; + /* overlay get */ + bool get(); + /* returns flags from mdp structure */ + int getFlags() const; + /* set flags to mdp structure */ + void setFlags(int f); + /* set z order */ + void setZ(utils::eZorder z); + /* set isFg flag */ + void setIsFg(utils::eIsFg isFg); + /* return a copy of src whf*/ + utils::Whf getSrcWhf() const; + /* set src whf */ + void setSrcWhf(const utils::Whf& whf); + /* set src/dst rect dim */ + void setSrcRectDim(const utils::Dim d); + void setDstRectDim(const utils::Dim d); + /* returns user_data[0]*/ + int getUserData() const; + /* sets user_data[0] */ + void setUserData(int v); + /* return true if current overlay is different + * than last known good overlay */ + bool ovChanged() const; + /* save mOVInfo to be last known good ov*/ + void save(); + /* restore last known good ov to be the current */ + void restore(); utils::eTransform mOrientation; //Holds requested orientation - bool mRotUsed; //whether rotator should be used even if requested - //orientation is 0. - /* last good known ov info */ mdp_overlay mLkgo; - /* Actual overlay mdp structure */ mdp_overlay mOVInfo; - /* FD for the mdp fbnum */ OvFD mFd; + int mDownscale; }; @@ -210,37 +151,26 @@ class MdpData { public: /* ctor reset data */ explicit MdpData(); - /* dtor close*/ ~MdpData(); - /* init FD */ bool init(uint32_t fbnum); - /* memset0 the underlying mdp object */ void reset(); - /* close fd, and reset */ bool close(); - /* set id of mdp data */ void setPipeId(int id); - /* return ses id of data */ int getPipeId() const; - /* get underlying fd*/ int getFd() const; - /* get memory_id */ int getSrcMemoryId() const; - /* calls wrapper play */ bool play(int fd, uint32_t offset); - /* dump state of the object */ void dump() const; - /* Return the dump in the specified buffer */ void getDump(char *buf, size_t len); @@ -248,18 +178,11 @@ private: /* actual overlay mdp data */ msmfb_overlay_data mOvData; - /* fd to mdp fbnum */ OvFD mFd; }; //--------------Inlines--------------------------------- -namespace { -// just a helper func for common operations x-(y+z) -int compute(uint32_t x, uint32_t y, uint32_t z) { - return x-(y+z); -} -} ///// MdpCtrl ////// @@ -299,6 +222,10 @@ inline void MdpCtrl::setIsFg(overlay::utils::eIsFg isFg) { mOVInfo.is_fg = isFg; } +inline void MdpCtrl::setDownscale(int dscale) { + mDownscale = dscale; +} + inline bool MdpCtrl::ovChanged() const { // 0 means same if(0 == ::memcmp(&mOVInfo, &mLkgo, sizeof (mdp_overlay))) { @@ -375,47 +302,6 @@ inline void MdpCtrl::setRotationFlags() { mOVInfo.flags &= ~MDP_SOURCE_ROTATED_90; } -inline void MdpCtrl::swapSrcWH() { - utils::swap(mOVInfo.src.width, - mOVInfo.src.height); -} - -inline void MdpCtrl::swapSrcRectWH() { - utils::swap(mOVInfo.src_rect.w, - mOVInfo.src_rect.h); -} - -inline void MdpCtrl::overlayTransFlipH() -{ - utils::Dim d = getSrcRectDim(); - utils::Whf whf = getSrcWhf(); - d.x = compute(whf.w, d.x, d.w); - setSrcRectDim(d); -} - -inline void MdpCtrl::overlayTransFlipV() -{ - utils::Dim d = getSrcRectDim(); - utils::Whf whf = getSrcWhf(); - d.y = compute(whf.h, d.y, d.h); - setSrcRectDim(d); -} - -inline void MdpCtrl::overlayTransRot90() -{ - utils::Dim d = getSrcRectDim(); - utils::Whf whf = getSrcWhf(); - int tmp = d.x; - d.x = compute(whf.h, - d.y, - d.h); - d.y = tmp; - setSrcRectDim(d); - swapSrcWH(); - swapSrcRectWH(); -} - - /////// MdpCtrl3D ////// inline MdpCtrl3D::MdpCtrl3D() { reset(); } diff --git a/liboverlay/overlayMdpRot.cpp b/liboverlay/overlayMdpRot.cpp index c9843f22..d1e036c5 100755 --- a/liboverlay/overlayMdpRot.cpp +++ b/liboverlay/overlayMdpRot.cpp @@ -31,48 +31,38 @@ MdpRot::MdpRot() { MdpRot::~MdpRot() { close(); } -inline void MdpRot::setEnable() { mRotImgInfo.enable = 1; } +bool MdpRot::enabled() const { return mRotImgInfo.enable; } -inline void MdpRot::setDisable() { mRotImgInfo.enable = 0; } +void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = r; } -inline bool MdpRot::enabled() const { return mRotImgInfo.enable; } - -inline void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = r; } - -inline int MdpRot::getDstMemId() const { +int MdpRot::getDstMemId() const { return mRotDataInfo.dst.memory_id; } -inline uint32_t MdpRot::getDstOffset() const { +uint32_t MdpRot::getDstOffset() const { return mRotDataInfo.dst.offset; } -inline uint32_t MdpRot::getDstFormat() const { +uint32_t MdpRot::getDstFormat() const { return mRotImgInfo.dst.format; } -inline uint32_t MdpRot::getSessId() const { return mRotImgInfo.session_id; } - -inline void MdpRot::setSrcFB() { - mRotDataInfo.src.flags |= MDP_MEMORY_ID_TYPE_FB; -} +uint32_t MdpRot::getSessId() const { return mRotImgInfo.session_id; } void MdpRot::setDownscale(int ds) { if ((utils::ROT_DS_EIGHTH == ds) && (mRotImgInfo.src_rect.h & 0xF)) { // Ensure src_rect.h is a multiple of 16 for 1/8 downscaling. // This is an undocumented MDP Rotator constraint. - // Note that src_rect.h is already ensured to be 32 pixel height aligned - // for MDP_Y_CRCB_H2V2_TILE and MDP_Y_CBCR_H2V2_TILE formats. mRotImgInfo.src_rect.h = utils::aligndown(mRotImgInfo.src_rect.h, 16); } mRotImgInfo.downscale_ratio = ds; } -inline void MdpRot::save() { +void MdpRot::save() { mLSRotImgInfo = mRotImgInfo; } -inline bool MdpRot::rotConfChanged() const { +bool MdpRot::rotConfChanged() const { // 0 means same if(0 == ::memcmp(&mRotImgInfo, &mLSRotImgInfo, sizeof (msm_rotator_img_info))) { @@ -92,13 +82,7 @@ bool MdpRot::init() void MdpRot::setSource(const overlay::utils::Whf& awhf) { utils::Whf whf(awhf); - mRotImgInfo.src.format = whf.format; - if(whf.format == MDP_Y_CRCB_H2V2_TILE || - whf.format == MDP_Y_CBCR_H2V2_TILE) { - whf.w = utils::alignup(awhf.w, 64); - whf.h = utils::alignup(awhf.h, 32); - } mRotImgInfo.src.width = whf.w; mRotImgInfo.src.height = whf.h; @@ -110,13 +94,13 @@ void MdpRot::setSource(const overlay::utils::Whf& awhf) { mRotImgInfo.dst.height = whf.h; } -inline void MdpRot::setFlags(const utils::eMdpFlags& flags) { +void MdpRot::setFlags(const utils::eMdpFlags& flags) { mRotImgInfo.secure = 0; if(flags & utils::OV_MDP_SECURE_OVERLAY_SESSION) mRotImgInfo.secure = 1; } -inline void MdpRot::setTransform(const utils::eTransform& rot) +void MdpRot::setTransform(const utils::eTransform& rot) { int r = utils::getMdpOrient(rot); setRotations(r); @@ -126,14 +110,7 @@ inline void MdpRot::setTransform(const utils::eTransform& rot) ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r); } -inline void MdpRot::setRotatorUsed(const bool& rotUsed) { - setDisable(); - if(rotUsed) { - setEnable(); - } -} - -inline void MdpRot::doTransform() { +void MdpRot::doTransform() { if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) utils::swap(mRotImgInfo.dst.width, mRotImgInfo.dst.height); } @@ -141,9 +118,11 @@ inline void MdpRot::doTransform() { bool MdpRot::commit() { doTransform(); if(rotConfChanged()) { + mRotImgInfo.enable = 1; if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) { ALOGE("MdpRot commit failed"); dump(); + mRotImgInfo.enable = 0; return false; } save(); diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp index fd747ddb..70bf52bc 100644 --- a/liboverlay/overlayMdssRot.cpp +++ b/liboverlay/overlayMdssRot.cpp @@ -43,34 +43,26 @@ MdssRot::MdssRot() { MdssRot::~MdssRot() { close(); } -inline void MdssRot::setEnable() { mEnabled = true; } +bool MdssRot::enabled() const { return mEnabled; } -inline void MdssRot::setDisable() { mEnabled = false; } +void MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; } -inline bool MdssRot::enabled() const { return mEnabled; } - -inline void MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; } - -inline int MdssRot::getDstMemId() const { +int MdssRot::getDstMemId() const { return mRotData.dst_data.memory_id; } -inline uint32_t MdssRot::getDstOffset() const { +uint32_t MdssRot::getDstOffset() const { return mRotData.dst_data.offset; } -inline uint32_t MdssRot::getDstFormat() const { +uint32_t MdssRot::getDstFormat() const { //For mdss src and dst formats are same return mRotInfo.src.format; } -inline uint32_t MdssRot::getSessId() const { return mRotInfo.id; } +uint32_t MdssRot::getSessId() const { return mRotInfo.id; } -inline void MdssRot::setSrcFB() { - mRotData.data.flags |= MDP_MEMORY_ID_TYPE_FB; -} - -inline bool MdssRot::init() { +bool MdssRot::init() { if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) { ALOGE("MdssRot failed to init fb0"); return false; @@ -82,11 +74,6 @@ void MdssRot::setSource(const overlay::utils::Whf& awhf) { utils::Whf whf(awhf); mRotInfo.src.format = whf.format; - if(whf.format == MDP_Y_CRCB_H2V2_TILE || - whf.format == MDP_Y_CBCR_H2V2_TILE) { - whf.w = utils::alignup(awhf.w, 64); - whf.h = utils::alignup(awhf.h, 32); - } mRotInfo.src.width = whf.w; mRotInfo.src.height = whf.h; @@ -98,13 +85,13 @@ void MdssRot::setSource(const overlay::utils::Whf& awhf) { mRotInfo.dst_rect.h = whf.h; } -inline void MdssRot::setDownscale(int ds) {} +void MdssRot::setDownscale(int ds) {} -inline void MdssRot::setFlags(const utils::eMdpFlags& flags) { +void MdssRot::setFlags(const utils::eMdpFlags& flags) { mRotInfo.flags |= flags; } -inline void MdssRot::setTransform(const utils::eTransform& rot) +void MdssRot::setTransform(const utils::eTransform& rot) { int flags = utils::getMdpOrient(rot); if (flags != -1) @@ -115,14 +102,7 @@ inline void MdssRot::setTransform(const utils::eTransform& rot) ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, flags); } -inline void MdssRot::setRotatorUsed(const bool& rotUsed) { - setDisable(); - if(rotUsed) { - setEnable(); - } -} - -inline void MdssRot::doTransform() { +void MdssRot::doTransform() { if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) utils::swap(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h); } @@ -130,10 +110,11 @@ inline void MdssRot::doTransform() { bool MdssRot::commit() { doTransform(); mRotInfo.flags |= MDSS_MDP_ROT_ONLY; + mEnabled = true; if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) { ALOGE("MdssRot commit failed!"); dump(); - return false; + return (mEnabled = false); } mRotData.id = mRotInfo.id; // reset rotation flags to avoid stale orientation values diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp index 90a1e7a5..3861297e 100644 --- a/liboverlay/overlayRotator.cpp +++ b/liboverlay/overlayRotator.cpp @@ -70,4 +70,65 @@ bool RotMem::close() { return ret; } +RotMgr::RotMgr() { + for(int i = 0; i < MAX_ROT_SESS; i++) { + mRot[i] = 0; + } + mUseCount = 0; +} + +RotMgr::~RotMgr() { + clear(); +} + +void RotMgr::configBegin() { + //Reset the number of objects used + mUseCount = 0; +} + +void RotMgr::configDone() { + //Remove the top most unused objects. Videos come and go. + for(int i = mUseCount; i < MAX_ROT_SESS; i++) { + if(mRot[i]) { + delete mRot[i]; + mRot[i] = 0; + } + } +} + +Rotator* RotMgr::getNext() { + //Return a rot object, creating one if necessary + overlay::Rotator *rot = NULL; + if(mUseCount >= MAX_ROT_SESS) { + ALOGE("%s, MAX rotator sessions reached", __func__); + } else { + if(mRot[mUseCount] == NULL) + mRot[mUseCount] = overlay::Rotator::getRotator(); + rot = mRot[mUseCount++]; + } + return rot; +} + +void RotMgr::clear() { + //Brute force obj destruction, helpful in suspend. + for(int i = 0; i < MAX_ROT_SESS; i++) { + if(mRot[i]) { + delete mRot[i]; + mRot[i] = 0; + } + } + mUseCount = 0; +} + +void RotMgr::getDump(char *buf, size_t len) { + for(int i = 0; i < MAX_ROT_SESS; i++) { + if(mRot[i]) { + mRot[i]->getDump(buf, len); + } + } + char str[32] = {'\0'}; + snprintf(str, 32, "\n================\n"); + strncat(buf, str, strlen(str)); +} + } diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h index bd2fd7eb..36fe581f 100644 --- a/liboverlay/overlayRotator.h +++ b/liboverlay/overlayRotator.h @@ -43,22 +43,14 @@ class Rotator public: enum { TYPE_MDP, TYPE_MDSS }; virtual ~Rotator(); - virtual bool init() = 0; - virtual bool close() = 0; virtual void setSource(const utils::Whf& wfh) = 0; virtual void setFlags(const utils::eMdpFlags& flags) = 0; virtual void setTransform(const utils::eTransform& rot) = 0; - virtual void setRotatorUsed(const bool& rotUsed) = 0; virtual bool commit() = 0; - virtual void setRotations(uint32_t r) = 0; - virtual void setSrcFB() = 0; virtual void setDownscale(int ds) = 0; virtual int getDstMemId() const = 0; virtual uint32_t getDstOffset() const = 0; virtual uint32_t getDstFormat() const = 0; - virtual void setEnable() = 0; - virtual void setDisable() = 0; - virtual bool enabled () const = 0; virtual uint32_t getSessId() const = 0; virtual bool queueBuffer(int fd, uint32_t offset) = 0; virtual void dump() const = 0; @@ -116,22 +108,14 @@ struct RotMem { class MdpRot : public Rotator { public: virtual ~MdpRot(); - virtual bool init(); - virtual bool close(); virtual void setSource(const utils::Whf& wfh); virtual void setFlags(const utils::eMdpFlags& flags); virtual void setTransform(const utils::eTransform& rot); - virtual void setRotatorUsed(const bool& rotUsed); virtual bool commit(); - virtual void setRotations(uint32_t r); - virtual void setSrcFB(); virtual void setDownscale(int ds); virtual int getDstMemId() const; virtual uint32_t getDstOffset() const; virtual uint32_t getDstFormat() const; - virtual void setEnable(); - virtual void setDisable(); - virtual bool enabled () const; virtual uint32_t getSessId() const; virtual bool queueBuffer(int fd, uint32_t offset); virtual void dump() const; @@ -139,6 +123,10 @@ public: private: explicit MdpRot(); + bool init(); + bool close(); + void setRotations(uint32_t r); + bool enabled () const; /* remap rot buffers */ bool remap(uint32_t numbufs); bool open_i(uint32_t numbufs, uint32_t bufsz); @@ -178,22 +166,14 @@ private: class MdssRot : public Rotator { public: virtual ~MdssRot(); - virtual bool init(); - virtual bool close(); virtual void setSource(const utils::Whf& wfh); virtual void setFlags(const utils::eMdpFlags& flags); virtual void setTransform(const utils::eTransform& rot); - virtual void setRotatorUsed(const bool& rotUsed); virtual bool commit(); - virtual void setRotations(uint32_t r); - virtual void setSrcFB(); virtual void setDownscale(int ds); virtual int getDstMemId() const; virtual uint32_t getDstOffset() const; virtual uint32_t getDstFormat() const; - virtual void setEnable(); - virtual void setDisable(); - virtual bool enabled () const; virtual uint32_t getSessId() const; virtual bool queueBuffer(int fd, uint32_t offset); virtual void dump() const; @@ -201,6 +181,10 @@ public: private: explicit MdssRot(); + bool init(); + bool close(); + void setRotations(uint32_t r); + bool enabled () const; /* remap rot buffers */ bool remap(uint32_t numbufs); bool open_i(uint32_t numbufs, uint32_t bufsz); @@ -228,6 +212,28 @@ private: friend Rotator* Rotator::getRotator(); }; +// Holder of rotator objects. Manages lifetimes +class RotMgr { +public: + //Maximum sessions based on VG pipes, since rotator is used only for videos. + //Even though we can have 4 mixer stages, that much may be unnecessary. + enum { MAX_ROT_SESS = 3 }; + RotMgr(); + ~RotMgr(); + void configBegin(); + void configDone(); + overlay::Rotator *getNext(); + void clear(); //Removes all instances + /* Returns rot dump. + * Expects a NULL terminated buffer of big enough size. + */ + void getDump(char *buf, size_t len); +private: + overlay::Rotator *mRot[MAX_ROT_SESS]; + int mUseCount; +}; + + } // overlay #endif // OVERlAY_ROTATOR_H diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp index de10c9ff..907597e8 100644 --- a/liboverlay/overlayUtils.cpp +++ b/liboverlay/overlayUtils.cpp @@ -89,67 +89,6 @@ namespace utils { #define NUM_FB_DEVICES 3 //-------------------------------------------------------- -FrameBufferInfo::FrameBufferInfo() { - mFBWidth = 0; - mFBHeight = 0; - mBorderFillSupported = false; - - OvFD mFd; - - // Use open defined in overlayFD file to open fd for fb0 - if(!overlay::open(mFd, 0, Res::fbPath)) { - ALOGE("FrameBufferInfo: failed to open fd"); - return; - } - - if (!mFd.valid()) { - ALOGE("FrameBufferInfo: FD not valid"); - return; - } - - fb_var_screeninfo vinfo; - if (!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) { - ALOGE("FrameBufferInfo: failed getVScreenInfo on fb0"); - mFd.close(); - return; - } - - int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion(); - if (mdpVersion < qdutils::MDSS_V5) { - mdp_overlay ov; - memset(&ov, 0, sizeof(ov)); - ov.id = 1; - if (!mdp_wrapper::getOverlay(mFd.getFD(), ov)) { - ALOGE("FrameBufferInfo: failed getOverlay on fb0"); - mFd.close(); - return; - } - mBorderFillSupported = (ov.flags & MDP_BORDERFILL_SUPPORTED) ? - true : false; - } else { - // badger always support border fill - mBorderFillSupported = true; - } - - mFd.close(); - mFBWidth = vinfo.xres; - mFBHeight = vinfo.yres; -} - -FrameBufferInfo* FrameBufferInfo::getInstance() { - if (!sFBInfoInstance) { - sFBInfoInstance = new FrameBufferInfo; - } - return sFBInfoInstance; -} - -int FrameBufferInfo::getWidth() const { - return mFBWidth; -} - -int FrameBufferInfo::getHeight() const { - return mFBHeight; -} /* clears any VG pipes allocated to the fb devices */ int initOverlay() { @@ -293,6 +232,58 @@ int getHALFormat(int mdpFormat) { return -1; } +int getDownscaleFactor(const int& src_w, const int& src_h, + const int& dst_w, const int& dst_h) { + int dscale_factor = utils::ROT_DS_NONE; + // We need this check to engage the rotator whenever possible to assist MDP + // in performing video downscale. + // This saves bandwidth and avoids causing the driver to make too many panel + // -mode switches between BLT (writeback) and non-BLT (Direct) modes. + // Use-case: Video playback [with downscaling and rotation]. + if (dst_w && dst_h) + { + uint32_t dscale = (src_w * src_h) / (dst_w * dst_h); + if(dscale < 2) { + // Down-scale to > 50% of orig. + dscale_factor = utils::ROT_DS_NONE; + } else if(dscale < 4) { + // Down-scale to between > 25% to <= 50% of orig. + dscale_factor = utils::ROT_DS_HALF; + } else if(dscale < 8) { + // Down-scale to between > 12.5% to <= 25% of orig. + dscale_factor = utils::ROT_DS_FOURTH; + } else { + // Down-scale to <= 12.5% of orig. + dscale_factor = utils::ROT_DS_EIGHTH; + } + } + return dscale_factor; +} + +static inline int compute(const uint32_t& x, const uint32_t& y, + const uint32_t& z) { + return x - ( y + z ); +} + +void preRotateSource(eTransform& tr, Whf& whf, Dim& srcCrop) { + if(tr & OVERLAY_TRANSFORM_FLIP_H) { + srcCrop.x = compute(whf.w, srcCrop.x, srcCrop.w); + } + if(tr & OVERLAY_TRANSFORM_FLIP_V) { + srcCrop.y = compute(whf.h, srcCrop.y, srcCrop.h); + } + if(tr & OVERLAY_TRANSFORM_ROT_90) { + int tmp = srcCrop.x; + srcCrop.x = compute(whf.h, + srcCrop.y, + srcCrop.h); + srcCrop.y = tmp; + swap(whf.w, whf.h); + swap(srcCrop.w, srcCrop.h); + } + tr = OVERLAY_TRANSFORM_0; +} + bool is3DTV() { char is3DTV = '0'; IOFile fp(Res::edid3dInfoFile, "r"); diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h index 0459ea4d..555232a5 100644 --- a/liboverlay/overlayUtils.h +++ b/liboverlay/overlayUtils.h @@ -114,36 +114,6 @@ private: const NoCopy& operator=(const NoCopy&); }; -/* -* Utility class to query the framebuffer info for primary display -* -* Usage: -* Outside of functions: -* utils::FrameBufferInfo* utils::FrameBufferInfo::sFBInfoInstance = 0; -* Inside functions: -* utils::FrameBufferInfo::getInstance()->supportTrueMirroring() -*/ -class FrameBufferInfo { - -public: - /* ctor init */ - explicit FrameBufferInfo(); - - /* Gets an instance if one does not already exist */ - static FrameBufferInfo* getInstance(); - - /* Gets width of primary framebuffer */ - int getWidth() const; - - /* Gets height of primary framebuffer */ - int getHeight() const; - -private: - int mFBWidth; - int mFBHeight; - bool mBorderFillSupported; - static FrameBufferInfo *sFBInfoInstance; -}; /* 3D related utils, defines etc... * The compound format passed to the overlay is @@ -163,18 +133,9 @@ enum { BARRIER_LAND = 1, int initOverlay(void); inline uint32_t format3D(uint32_t x) { return x & 0xFF000; } -inline uint32_t colorFormat(uint32_t fmt) { - /*TODO enable this block only if format has interlace / 3D info in top bits. - if(fmt & INTERLACE_MASK) { - fmt = fmt ^ HAL_PIXEL_FORMAT_INTERLACE; - } - fmt = fmt & 0xFFF;*/ - return fmt; -} inline uint32_t format3DOutput(uint32_t x) { return (x & 0xF000) >> SHIFT_OUT_3D; } inline uint32_t format3DInput(uint32_t x) { return x & 0xF0000; } -uint32_t getColorFormat(uint32_t format); bool isHDMIConnected (); bool is3DTV(); @@ -255,10 +216,8 @@ enum { MAX_PATH_LEN = 256 }; /** * Rotator flags: not to be confused with orientation flags. - * Ususally, you want to open the rotator to make sure it is + * Usually, you want to open the rotator to make sure it is * ready for business. - * ROT_FLAG_DISABLED: Rotator not used unless required. - * ROT_FLAG_ENABLED: Rotator used even if not required. * */ enum eRotFlags { ROT_FLAGS_NONE = 0, @@ -268,6 +227,7 @@ enum { MAX_PATH_LEN = 256 }; //driver. If downscale optimizatation is required, //then rotator will be used even if its 0 rotation case. ROT_DOWNSCALE_ENABLED = 1 << 1, + ROT_PREROTATED = 1 << 2, }; enum eRotDownscale { @@ -298,7 +258,6 @@ enum eMdpFlags { OV_MDP_DEINTERLACE = MDP_DEINTERLACE, OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION, OV_MDP_SOURCE_ROTATED_90 = MDP_SOURCE_ROTATED_90, - OV_MDP_MEMORY_ID_TYPE_FB = MDP_MEMORY_ID_TYPE_FB, OV_MDP_BACKEND_COMPOSITION = MDP_BACKEND_COMPOSITION, OV_MDP_BLEND_FG_PREMULT = MDP_BLEND_FG_PREMULT, OV_MDP_FLIP_H = MDP_FLIP_LR, @@ -307,7 +266,7 @@ enum eMdpFlags { }; enum eZorder { - ZORDER_0, + ZORDER_0 = 0, ZORDER_1, ZORDER_2, ZORDER_3, @@ -422,6 +381,8 @@ struct ScreenInfo { int getMdpFormat(int format); int getHALFormat(int mdpFormat); +int getDownscaleFactor(const int& src_w, const int& src_h, + const int& dst_w, const int& dst_h); /* flip is upside down and such. V, H flip * rotation is 90, 180 etc @@ -597,12 +558,6 @@ inline int getMdpOrient(eTransform rotation) { return -1; } -inline uint32_t getColorFormat(uint32_t format) -{ - return (format == HAL_PIXEL_FORMAT_YV12) ? - format : colorFormat(format); -} - // FB0 template inline Dim getPositionS3DImpl(const Whf& whf) @@ -766,6 +721,7 @@ inline eMdpPipeType getPipeType(eDest dest) { return OV_MDP_PIPE_ANY; } +void preRotateSource(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); void getDump(char *buf, size_t len, const char *prefix, const mdp_rect& ov); diff --git a/liboverlay/pipes/overlayGenPipe.cpp b/liboverlay/pipes/overlayGenPipe.cpp index 486cfda4..9108acdd 100644 --- a/liboverlay/pipes/overlayGenPipe.cpp +++ b/liboverlay/pipes/overlayGenPipe.cpp @@ -34,7 +34,7 @@ namespace overlay { GenericPipe::GenericPipe(int dpy) : mFbNum(dpy), mRot(0), mRotUsed(false), - mRotDownscaleOpt(false), pipeState(CLOSED) { + mRotDownscaleOpt(false), mPreRotated(false), pipeState(CLOSED) { init(); } @@ -47,6 +47,7 @@ bool GenericPipe::init() ALOGE_IF(DEBUG_OVERLAY, "GenericPipe init"); mRotUsed = false; mRotDownscaleOpt = false; + mPreRotated = false; if(mFbNum) mFbNum = Overlay::getInstance()->getExtFbNum(); @@ -87,54 +88,31 @@ bool GenericPipe::close() { return ret; } -bool GenericPipe::setSource( - const utils::PipeArgs& args) -{ - utils::PipeArgs newargs(args); - //Interlace video handling. - if(newargs.whf.format & INTERLACE_MASK) { - setMdpFlags(newargs.mdpFlags, utils::OV_MDP_DEINTERLACE); - } - utils::Whf whf(newargs.whf); - //Extract HAL format from lower bytes. Deinterlace if interlaced. - whf.format = utils::getColorFormat(whf.format); - //Get MDP equivalent of HAL format. - whf.format = utils::getMdpFormat(whf.format); - newargs.whf = whf; - +void GenericPipe::setSource(const utils::PipeArgs& args) { //Cache if user wants 0-rotation - mRotUsed = newargs.rotFlags & utils::ROT_0_ENABLED; - mRotDownscaleOpt = newargs.rotFlags & utils::ROT_DOWNSCALE_ENABLED; - - mRot->setSource(newargs.whf); - mRot->setFlags(newargs.mdpFlags); - return mCtrlData.ctrl.setSource(newargs); + mRotUsed = args.rotFlags & utils::ROT_0_ENABLED; + mRotDownscaleOpt = args.rotFlags & utils::ROT_DOWNSCALE_ENABLED; + mPreRotated = args.rotFlags & utils::ROT_PREROTATED; + if(mPreRotated) mRotUsed = false; + mRot->setSource(args.whf); + mRot->setFlags(args.mdpFlags); + mCtrlData.ctrl.setSource(args); } -bool GenericPipe::setCrop( - const overlay::utils::Dim& d) { - return mCtrlData.ctrl.setCrop(d); +void GenericPipe::setCrop(const overlay::utils::Dim& d) { + mCtrlData.ctrl.setCrop(d); } -bool GenericPipe::setTransform( - const utils::eTransform& orient) -{ +void GenericPipe::setTransform(const utils::eTransform& orient) { //Rotation could be enabled by user for zero-rot or the layer could have //some transform. Mark rotation enabled in either case. - mRotUsed |= (orient != utils::OVERLAY_TRANSFORM_0); + mRotUsed |= ((orient & utils::OVERLAY_TRANSFORM_ROT_90) && !mPreRotated); mRot->setTransform(orient); - - return mCtrlData.ctrl.setTransform(orient); + mCtrlData.ctrl.setTransform(orient); } -bool GenericPipe::setPosition(const utils::Dim& d) -{ - return mCtrlData.ctrl.setPosition(d); -} - -void GenericPipe::setRotatorUsed(const bool& rotUsed) { - mRot->setRotatorUsed(rotUsed); - mCtrlData.ctrl.setRotatorUsed(rotUsed); +void GenericPipe::setPosition(const utils::Dim& d) { + mCtrlData.ctrl.setPosition(d); } bool GenericPipe::commit() { @@ -142,20 +120,16 @@ bool GenericPipe::commit() { int downscale_factor = utils::ROT_DS_NONE; if(mRotDownscaleOpt) { - /* Can go ahead with calculation of downscale_factor since - * we consider area when calculating it */ - downscale_factor = mCtrlData.ctrl.getDownscalefactor(); - if(downscale_factor) - mRotUsed = true; + ovutils::Dim src(mCtrlData.ctrl.getCrop()); + ovutils::Dim dst(mCtrlData.ctrl.getPosition()); + downscale_factor = ovutils::getDownscaleFactor( + src.w, src.h, dst.w, dst.h); + mRotUsed |= (downscale_factor && !mPreRotated); } - setRotatorUsed(mRotUsed); - mCtrlData.ctrl.doTransform(); - - mCtrlData.ctrl.doDownscale(downscale_factor); - mRot->setDownscale(downscale_factor); if(mRotUsed) { + mRot->setDownscale(downscale_factor); //If wanting to use rotator, start it. if(!mRot->commit()) { ALOGE("GenPipe Rotator commit failed"); @@ -170,9 +144,10 @@ bool GenericPipe::commit() { * The output format of the rotator might be different depending on * whether fastyuv mode is enabled in the rotator. */ - mCtrlData.ctrl.updateSrcformat(mRot->getDstFormat()); + mCtrlData.ctrl.updateSrcFormat(mRot->getDstFormat()); } + mCtrlData.ctrl.setDownscale(downscale_factor); ret = mCtrlData.ctrl.commit(); //If mdp commit fails, flush rotator session, memory, fd and create a hollow @@ -220,11 +195,6 @@ int GenericPipe::getCtrlFd() const { return mCtrlData.ctrl.getFd(); } -utils::ScreenInfo GenericPipe::getScreenInfo() const -{ - return mCtrlData.ctrl.getScreenInfo(); -} - utils::Dim GenericPipe::getCrop() const { return mCtrlData.ctrl.getCrop(); diff --git a/liboverlay/pipes/overlayGenPipe.h b/liboverlay/pipes/overlayGenPipe.h index 1d1be25d..c71f8d27 100644 --- a/liboverlay/pipes/overlayGenPipe.h +++ b/liboverlay/pipes/overlayGenPipe.h @@ -43,48 +43,34 @@ public: explicit GenericPipe(int dpy); /* dtor */ ~GenericPipe(); - /* CTRL/DATA init. Not owning rotator, will not init it */ bool init(); - /* CTRL/DATA close. Not owning rotator, will not close it */ bool close(); - /* Control APIs */ /* set source using whf, orient and wait flag */ - bool setSource(const utils::PipeArgs& args); + void setSource(const utils::PipeArgs& args); /* set crop a.k.a the region of interest */ - bool setCrop(const utils::Dim& d); + void setCrop(const utils::Dim& d); /* set orientation*/ - bool setTransform(const utils::eTransform& param); + void setTransform(const utils::eTransform& param); /* set mdp posision using dim */ - bool setPosition(const utils::Dim& dim); + void setPosition(const utils::Dim& dim); /* commit changes to the overlay "set"*/ bool commit(); - /* Data APIs */ /* queue buffer to the overlay */ bool queueBuffer(int fd, uint32_t offset); - /* return cached startup args */ const utils::PipeArgs& getArgs() const; - - /* retrieve screen info */ - utils::ScreenInfo getScreenInfo() const; - /* retrieve cached crop data */ utils::Dim getCrop() const; - /* is closed */ bool isClosed() const; - /* is open */ bool isOpen() const; - /* return Ctrl fd. Used for S3D */ int getCtrlFd() const; - /* dump the state of the object */ void dump() const; - /* Return the dump in the specified buffer */ void getDump(char *buf, size_t len); @@ -92,23 +78,17 @@ private: /* set Closed pipe */ bool setClosed(); - /* Set whether rotator can be used */ - void setRotatorUsed(const bool& rotUsed); - int mFbNum; - /* Ctrl/Data aggregator */ CtrlData mCtrlData; - Rotator* mRot; - //Whether rotator is used for 0-rot or otherwise bool mRotUsed; - //Whether we will do downscale opt. This is just a request. If the frame is //not a candidate, we might not do it. bool mRotDownscaleOpt; - + //Whether the source is prerotated. + bool mPreRotated; /* Pipe open or closed */ enum ePipeState { CLOSED,