overlay: Add support for rotator downscale

Add support for rotator downscale. This is enabled from 8994 onwards
Constraints:
--Downscale should be a power of 2, max upto 32
--Both directions should have equal downscale
--{src_w, src_h} mod downscale = 0
--No BWC
--No Interlaced video support

The rotator's destination rect is modified to reflect the presence of
downscale. Any downscale calcs should be done only after adjusting
crop to meet rotator's requirements.

Smaller downscale is used if we need to chop off any more than 1
line or pixel.

Change-Id: Id07d62fefa3213035f16cca49497800716484a95
This commit is contained in:
Saurabh Shah
2014-07-02 15:22:34 -07:00
parent 1c47cede92
commit c46cf9d26b
11 changed files with 235 additions and 76 deletions

View File

@@ -147,7 +147,8 @@ static void setDMAState(hwc_context_t *ctx, int numDisplays,
* to BLOCK_MODE */ * to BLOCK_MODE */
if (canUseRotator(ctx, dpy) && if (canUseRotator(ctx, dpy) &&
has90Transform(layer) && isRotationDoable(ctx, hnd)) { (has90Transform(layer) || getRotDownscale(ctx, layer))
&& isRotationDoable(ctx, hnd)) {
if(not ctx->mOverlay->isDMAMultiplexingSupported()) { if(not ctx->mOverlay->isDMAMultiplexingSupported()) {
if(ctx->mOverlay->isPipeTypeAttached( if(ctx->mOverlay->isPipeTypeAttached(
overlay::utils::OV_MDP_PIPE_DMA)) overlay::utils::OV_MDP_PIPE_DMA))

View File

@@ -156,6 +156,7 @@ bool MDPComp::init(hwc_context_t *ctx) {
} }
if(!qdutils::MDPVersion::getInstance().isSrcSplit() && if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
!qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 && property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
(!strncmp(property, "1", PROPERTY_VALUE_MAX) || (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
!strncasecmp(property,"true", PROPERTY_VALUE_MAX))) { !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
@@ -2311,6 +2312,10 @@ bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
int dstWidth = dst.right - dst.left; int dstWidth = dst.right - dst.left;
int cropWidth = crop.right - crop.left; int cropWidth = crop.right - crop.left;
//TODO Even if a 4k video is going to be rot-downscaled to dimensions under
//pipe line length, we are still using 2 pipes. This is fine just because
//this is source split where destination doesn't matter. Evaluate later to
//see if going through all the calcs to save a pipe is worth it
if(dstWidth > mdpHw.getMaxMixerWidth() or if(dstWidth > mdpHw.getMaxMixerWidth() or
cropWidth > mdpHw.getMaxMixerWidth() or cropWidth > mdpHw.getMaxMixerWidth() or
(primarySplitAlways and (cropWidth > lSplit))) { (primarySplitAlways and (cropWidth > lSplit))) {
@@ -2351,7 +2356,6 @@ int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
hwc_rect_t dst = layer->displayFrame; hwc_rect_t dst = layer->displayFrame;
int transform = layer->transform; int transform = layer->transform;
eTransform orient = static_cast<eTransform>(transform); eTransform orient = static_cast<eTransform>(transform);
const int downscale = 0;
int rotFlags = ROT_FLAGS_NONE; int rotFlags = ROT_FLAGS_NONE;
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd)); uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size); Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
@@ -2367,21 +2371,22 @@ int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888); whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
} }
int downscale = getRotDownscale(ctx, layer);
eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION; eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
setMdpFlags(ctx, layer, mdpFlags, 0, transform); setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
if(lDest != OV_INVALID && rDest != OV_INVALID) { if(lDest != OV_INVALID && rDest != OV_INVALID) {
//Enable overfetch //Enable overfetch
setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE); setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
} }
if(has90Transform(layer) && isRotationDoable(ctx, hnd)) { if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
(*rot) = ctx->mRotMgr->getNext(); (*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1; if((*rot) == NULL) return -1;
ctx->mLayerRotMap[mDpy]->add(layer, *rot); ctx->mLayerRotMap[mDpy]->add(layer, *rot);
//If the video is using a single pipe, enable BWC //If the video is using a single pipe, enable BWC
if(rDest == OV_INVALID) { if(rDest == OV_INVALID) {
BwcPM::setBwc(crop, dst, transform, mdpFlags); BwcPM::setBwc(crop, dst, transform, downscale, mdpFlags);
} }
//Configure rotator for pre-rotation //Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) { if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
@@ -2389,7 +2394,7 @@ int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
return -1; return -1;
} }
updateSource(orient, whf, crop, *rot); updateSource(orient, whf, crop, *rot);
rotFlags |= ROT_PREROTATED; rotFlags |= ovutils::ROT_PREROTATED;
} }
//If 2 pipes being used, divide layer into half, crop and dst //If 2 pipes being used, divide layer into half, crop and dst

View File

@@ -1633,6 +1633,47 @@ void updateSource(eTransform& orient, Whf& whf,
crop.bottom = transformedCrop.y + transformedCrop.h; crop.bottom = transformedCrop.y + transformedCrop.h;
} }
int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer) {
if(not qdutils::MDPVersion::getInstance().isRotDownscaleEnabled()) {
return 0;
}
int downscale = 0;
hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
hwc_rect_t dst = layer->displayFrame;
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(not hnd) {
return 0;
}
MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
bool isInterlaced = metadata && (metadata->operation & PP_PARAM_INTERLACED)
&& metadata->interlaced;
int transform = layer->transform;
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
if(isYuvBuffer(hnd)) {
if(ctx->mMDP.version >= qdutils::MDP_V4_2 &&
ctx->mMDP.version < qdutils::MDSS_V5) {
downscale = Rotator::getDownscaleFactor(crop.right - crop.left,
crop.bottom - crop.top, dst.right - dst.left,
dst.bottom - dst.top, format, isInterlaced);
} else {
Dim adjCrop(crop.left, crop.top, crop.right - crop.left,
crop.bottom - crop.top);
Dim pos(dst.left, dst.top, dst.right - dst.left,
dst.bottom - dst.top);
if(transform & HAL_TRANSFORM_ROT_90) {
swap(adjCrop.w, adjCrop.h);
}
downscale = Rotator::getDownscaleFactor(adjCrop.w, adjCrop.h, pos.w,
pos.h, format, isInterlaced);
}
}
return downscale;
}
int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer, int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
const int& dpy, eMdpFlags& mdpFlags, eZorder& z, const int& dpy, eMdpFlags& mdpFlags, eZorder& z,
eIsFg& isFg, const eDest& dest, Rotator **rot) { eIsFg& isFg, const eDest& dest, Rotator **rot) {
@@ -1654,7 +1695,6 @@ int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
hwc_rect_t dst = layer->displayFrame; hwc_rect_t dst = layer->displayFrame;
int transform = layer->transform; int transform = layer->transform;
eTransform orient = static_cast<eTransform>(transform); eTransform orient = static_cast<eTransform>(transform);
int downscale = 0;
int rotFlags = ovutils::ROT_FLAGS_NONE; int rotFlags = ovutils::ROT_FLAGS_NONE;
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd)); uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size); Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
@@ -1668,36 +1708,24 @@ int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
} }
calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient); calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
int downscale = getRotDownscale(ctx, layer);
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(ctx, layer, mdpFlags, downscale, transform); setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
//if 90 component or downscale, use rot //if 90 component or downscale, use rot
if((has90Transform(layer) && isRotationDoable(ctx, hnd)) || downscale) { if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
*rot = ctx->mRotMgr->getNext(); *rot = ctx->mRotMgr->getNext();
if(*rot == NULL) return -1; if(*rot == NULL) return -1;
ctx->mLayerRotMap[dpy]->add(layer, *rot); ctx->mLayerRotMap[dpy]->add(layer, *rot);
// BWC is not tested for other formats So enable it only for YUV format // BWC is not tested for other formats So enable it only for YUV format
if(!dpy && isYuvBuffer(hnd)) if(!dpy && isYuvBuffer(hnd))
BwcPM::setBwc(crop, dst, transform, mdpFlags); BwcPM::setBwc(crop, dst, transform, downscale, mdpFlags);
//Configure rotator for pre-rotation //Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) { if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__); ALOGE("%s: configRotator failed!", __FUNCTION__);
return -1; return -1;
} }
updateSource(orient, whf, crop, *rot); updateSource(orient, whf, crop, *rot);
rotFlags |= ovutils::ROT_PREROTATED; rotFlags |= ROT_PREROTATED;
} }
//For the mdp, since either we are pre-rotating or MDP does flips //For the mdp, since either we are pre-rotating or MDP does flips
@@ -1761,7 +1789,6 @@ int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
hwc_rect_t dst = layer->displayFrame; hwc_rect_t dst = layer->displayFrame;
int transform = layer->transform; int transform = layer->transform;
eTransform orient = static_cast<eTransform>(transform); eTransform orient = static_cast<eTransform>(transform);
const int downscale = 0;
int rotFlags = ROT_FLAGS_NONE; int rotFlags = ROT_FLAGS_NONE;
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd)); uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size); Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
@@ -1777,8 +1804,8 @@ int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
/* Calculate the external display position based on MDP downscale, /* Calculate the external display position based on MDP downscale,
ActionSafe, and extorientation features. */ ActionSafe, and extorientation features. */
calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient); calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
int downscale = getRotDownscale(ctx, layer);
setMdpFlags(ctx, layer, mdpFlagsL, 0, transform); setMdpFlags(ctx, layer, mdpFlagsL, downscale, transform);
if(lDest != OV_INVALID && rDest != OV_INVALID) { if(lDest != OV_INVALID && rDest != OV_INVALID) {
//Enable overfetch //Enable overfetch
@@ -1792,7 +1819,7 @@ int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
whf.format = wb->getOutputFormat(); whf.format = wb->getOutputFormat();
} }
if(has90Transform(layer) && isRotationDoable(ctx, hnd)) { if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
(*rot) = ctx->mRotMgr->getNext(); (*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1; if((*rot) == NULL) return -1;
ctx->mLayerRotMap[dpy]->add(layer, *rot); ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1928,7 +1955,7 @@ int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
ctx->mLayerRotMap[dpy]->add(layer, *rot); ctx->mLayerRotMap[dpy]->add(layer, *rot);
// BWC is not tested for other formats So enable it only for YUV format // BWC is not tested for other formats So enable it only for YUV format
if(!dpy && isYuvBuffer(hnd)) if(!dpy && isYuvBuffer(hnd))
BwcPM::setBwc(crop, dst, transform, mdpFlagsL); BwcPM::setBwc(crop, dst, transform, downscale, mdpFlagsL);
//Configure rotator for pre-rotation //Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) { if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__); ALOGE("%s: configRotator failed!", __FUNCTION__);
@@ -2175,9 +2202,12 @@ bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
return (eqBounds == 3); return (eqBounds == 3);
} }
void BwcPM::setBwc(const hwc_rect_t& crop, void BwcPM::setBwc(const hwc_rect_t& crop, const hwc_rect_t& dst,
const hwc_rect_t& dst, const int& transform, const int& transform,const int& downscale,
ovutils::eMdpFlags& mdpFlags) { ovutils::eMdpFlags& mdpFlags) {
//BWC not supported with rot-downscale
if(downscale) return;
//Target doesnt support Bwc //Target doesnt support Bwc
qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance(); qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
if(!mdpHw.supportsBWC()) { if(!mdpHw.supportsBWC()) {

View File

@@ -161,8 +161,8 @@ struct VsyncState {
}; };
struct BwcPM { struct BwcPM {
static void setBwc(const hwc_rect_t& crop, static void setBwc(const hwc_rect_t& crop, const hwc_rect_t& dst,
const hwc_rect_t& dst, const int& transform, const int& transform, const int& downscale,
ovutils::eMdpFlags& mdpFlags); ovutils::eMdpFlags& mdpFlags);
}; };
@@ -387,6 +387,8 @@ int getLeftSplit(hwc_context_t *ctx, const int& dpy);
bool isDisplaySplit(hwc_context_t* ctx, int dpy); bool isDisplaySplit(hwc_context_t* ctx, int dpy);
int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer);
// Set the GPU hint flag to high for MIXED/GPU composition only for // Set the GPU hint flag to high for MIXED/GPU composition only for
// first frame after MDP to GPU/MIXED mode transition. // first frame after MDP to GPU/MIXED mode transition.
// Set the GPU hint to default if the current composition type is GPU // Set the GPU hint to default if the current composition type is GPU

View File

@@ -17,6 +17,7 @@
* limitations under the License. * limitations under the License.
*/ */
#include <math.h>
#include "overlayUtils.h" #include "overlayUtils.h"
#include "overlayRotator.h" #include "overlayRotator.h"
#include "gr.h" #include "gr.h"
@@ -274,4 +275,35 @@ void MdpRot::getDump(char *buf, size_t len) const {
ovutils::getDump(buf, len, "MdpRotData", mRotDataInfo); ovutils::getDump(buf, len, "MdpRotData", mRotDataInfo);
} }
int MdpRot::getDownscaleFactor(const int& src_w, const int& src_h,
const int& dst_w, const int& dst_h, const uint32_t& /*mdpFormat*/,
const bool& /*isInterlaced*/) {
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)
{
float fDscale = (float)(src_w * src_h) / (float)(dst_w * dst_h);
uint32_t dscale = (int)sqrtf(fDscale);
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;
}
} // namespace overlay } // namespace overlay

View File

@@ -17,6 +17,7 @@
* limitations under the License. * limitations under the License.
*/ */
#include <math.h>
#include "overlayUtils.h" #include "overlayUtils.h"
#include "overlayRotator.h" #include "overlayRotator.h"
@@ -103,7 +104,8 @@ void MdssRot::setCrop(const utils::Dim& crop) {
mRotInfo.src_rect.h = crop.h; mRotInfo.src_rect.h = crop.h;
} }
void MdssRot::setDownscale(int /*ds*/) { void MdssRot::setDownscale(int downscale) {
mDownscale = downscale;
} }
void MdssRot::setFlags(const utils::eMdpFlags& flags) { void MdssRot::setFlags(const utils::eMdpFlags& flags) {
@@ -128,19 +130,25 @@ void MdssRot::doTransform() {
} }
bool MdssRot::commit() { bool MdssRot::commit() {
if (utils::isYuv(mRotInfo.src.format)) { Dim adjCrop(mRotInfo.src_rect.x,mRotInfo.src_rect.y,
utils::normalizeCrop(mRotInfo.src_rect.x, mRotInfo.src_rect.w); mRotInfo.src_rect.w,mRotInfo.src_rect.h);
utils::normalizeCrop(mRotInfo.src_rect.y, mRotInfo.src_rect.h); adjCrop = getFormatAdjustedCrop(adjCrop, mRotInfo.src.format,
// For interlaced, crop.h should be 4-aligned mRotInfo.flags & utils::OV_MDP_DEINTERLACE);
if ((mRotInfo.flags & utils::OV_MDP_DEINTERLACE) and adjCrop = getDownscaleAdjustedCrop(adjCrop, mDownscale);
(mRotInfo.src_rect.h % 4))
mRotInfo.src_rect.h = utils::aligndown(mRotInfo.src_rect.h, 4); mRotInfo.src_rect.x = adjCrop.x;
} mRotInfo.src_rect.y = adjCrop.y;
mRotInfo.src_rect.w = adjCrop.w;
mRotInfo.src_rect.h = adjCrop.h;
mRotInfo.dst_rect.x = 0; mRotInfo.dst_rect.x = 0;
mRotInfo.dst_rect.y = 0; mRotInfo.dst_rect.y = 0;
mRotInfo.dst_rect.w = mRotInfo.src_rect.w; mRotInfo.dst_rect.w = mDownscale ?
mRotInfo.dst_rect.h = mRotInfo.src_rect.h; mRotInfo.src_rect.w / mDownscale : mRotInfo.src_rect.w;
mRotInfo.dst_rect.h = mDownscale ?
mRotInfo.src_rect.h / mDownscale : mRotInfo.src_rect.h;
//Clear for next round
mDownscale = 0;
doTransform(); doTransform();
@@ -258,6 +266,7 @@ void MdssRot::reset() {
ovutils::memset0(mMem.mRotOffset); ovutils::memset0(mMem.mRotOffset);
mMem.mCurrIndex = 0; mMem.mCurrIndex = 0;
mOrientation = utils::OVERLAY_TRANSFORM_0; mOrientation = utils::OVERLAY_TRANSFORM_0;
mDownscale = 0;
} }
void MdssRot::dump() const { void MdssRot::dump() const {
@@ -340,4 +349,54 @@ uint32_t MdssRot::calcCompressedBufSize(const ovutils::Whf& destWhf) {
return bufSize; return bufSize;
} }
int MdssRot::getDownscaleFactor(const int& srcW, const int& srcH,
const int& dstW, const int& dstH, const uint32_t& mdpFormat,
const bool& isInterlaced) {
if(not srcW or not srcH or not dstW or not dstH or isInterlaced) return 0;
Dim crop(0, 0, srcW, srcH);
Dim adjCrop = getFormatAdjustedCrop(crop, mdpFormat,
false /*isInterlaced */);
uint32_t downscale = min((adjCrop.w / dstW), (adjCrop.h / dstH));
//Reduced to a power of 2
downscale = (uint32_t) powf(2.0f, floorf(log2f((float)downscale)));
if(downscale < 2 or downscale > 32) return 0;
//Allow only 1 line or pixel to be chopped off since the source needs to
//be aligned to downscale. Progressively try with smaller downscale to see
//if we can satisfy the threshold
//For YUV the loop shouldnt be needed, unless in exceptional cases
Dim dsAdjCrop = getDownscaleAdjustedCrop(adjCrop, downscale);
while(downscale > 2 and (adjCrop.w > dsAdjCrop.w or
adjCrop.h > dsAdjCrop.h)) {
downscale /= 2;
dsAdjCrop = getDownscaleAdjustedCrop(adjCrop, downscale);
}
if(not dsAdjCrop.w or not dsAdjCrop.h) return 0;
return downscale;
}
Dim MdssRot::getFormatAdjustedCrop(const Dim& crop,
const uint32_t& mdpFormat, const bool& isInterlaced) {
Dim adjCrop = crop;
if (isYuv(mdpFormat)) {
normalizeCrop(adjCrop.x, adjCrop.w);
normalizeCrop(adjCrop.y, adjCrop.h);
// For interlaced, crop.h should be 4-aligned
if (isInterlaced and (adjCrop.h % 4))
adjCrop.h = aligndown(adjCrop.h, 4);
}
return adjCrop;
}
Dim MdssRot::getDownscaleAdjustedCrop(const Dim& crop,
const uint32_t& downscale) {
uint32_t alignedSrcW = aligndown(crop.w, downscale * 2);
uint32_t alignedSrcH = aligndown(crop.h, downscale * 2);
return Dim(crop.x, crop.y, alignedSrcW, alignedSrcH);
}
} // namespace overlay } // namespace overlay

View File

@@ -42,6 +42,17 @@ Rotator* Rotator::getRotator() {
} }
} }
int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
const int& dstW, const int& dstH, const uint32_t& mdpFormat,
const bool& isInterlaced) {
if(getRotatorHwType() == TYPE_MDSS) {
return MdssRot::getDownscaleFactor(srcW, srcH, dstW, dstH,
mdpFormat, isInterlaced);
}
return MdpRot::getDownscaleFactor(srcW, srcH, dstW, dstH,
mdpFormat, isInterlaced);
}
uint32_t Rotator::calcOutputBufSize(const utils::Whf& destWhf) { uint32_t Rotator::calcOutputBufSize(const utils::Whf& destWhf) {
//dummy aligned w & h. //dummy aligned w & h.
int alW = 0, alH = 0; int alW = 0, alH = 0;

View File

@@ -88,6 +88,13 @@ public:
virtual void getDump(char *buf, size_t len) const = 0; virtual void getDump(char *buf, size_t len) const = 0;
void setReleaseFd(const int& fence) { mMem.setReleaseFd(fence); } void setReleaseFd(const int& fence) { mMem.setReleaseFd(fence); }
static Rotator *getRotator(); static Rotator *getRotator();
/* Returns downscale by successfully applying constraints
* Returns 0 if target doesnt support rotator downscaling
* or if any of the constraints are not met
*/
static int getDownscaleFactor(const int& srcW, const int& srcH,
const int& dstW, const int& dstH, const uint32_t& mdpFormat,
const bool& isInterlaced);
protected: protected:
/* Rotator memory manager */ /* Rotator memory manager */
@@ -146,6 +153,16 @@ private:
* knowing the o/p format depending on whether fastYuv is enabled or not */ * knowing the o/p format depending on whether fastYuv is enabled or not */
uint32_t calcOutputBufSize(); uint32_t calcOutputBufSize();
/* Applies downscale by taking areas
* Returns a log(downscale)
* Constraints applied:
* - downscale should be a power of 2
* - Max downscale is 1/8
*/
static int getDownscaleFactor(const int& srcW, const int& srcH,
const int& dstW, const int& dstH, const uint32_t& mdpFormat,
const bool& isInterlaced);
/* rot info*/ /* rot info*/
msm_rotator_img_info mRotImgInfo; msm_rotator_img_info mRotImgInfo;
/* Last saved rot info*/ /* Last saved rot info*/
@@ -158,6 +175,9 @@ private:
OvFD mFd; OvFD mFd;
friend Rotator* Rotator::getRotator(); friend Rotator* Rotator::getRotator();
friend int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
const int& dstW, const int& dstH, const uint32_t& mdpFormat,
const bool& isInterlaced);
}; };
/* /*
@@ -202,6 +222,25 @@ private:
// Calculate the compressed o/p buffer size for BWC // Calculate the compressed o/p buffer size for BWC
uint32_t calcCompressedBufSize(const utils::Whf& destWhf); uint32_t calcCompressedBufSize(const utils::Whf& destWhf);
/* Caller's responsibility to swap srcW, srcH if there is a 90 transform
* Returns actual downscale (not a log value)
* Constraints applied:
* - downscale should be a power of 2
* - Max downscale is 1/32
* - Equal downscale is applied in both directions
* - {srcW, srcH} mod downscale = 0
* - Interlaced content is not supported
*/
static int getDownscaleFactor(const int& srcW, const int& srcH,
const int& dstW, const int& dstH, const uint32_t& mdpFormat,
const bool& isInterlaced);
static utils::Dim getFormatAdjustedCrop(const utils::Dim& crop,
const uint32_t& mdpFormat, const bool& isInterlaced);
static utils::Dim getDownscaleAdjustedCrop(const utils::Dim& crop,
const uint32_t& downscale);
/* MdssRot info structure */ /* MdssRot info structure */
mdp_overlay mRotInfo; mdp_overlay mRotInfo;
/* MdssRot data structure */ /* MdssRot data structure */
@@ -212,8 +251,12 @@ private:
OvFD mFd; OvFD mFd;
/* Enable/Disable Mdss Rot*/ /* Enable/Disable Mdss Rot*/
bool mEnabled; bool mEnabled;
int mDownscale;
friend Rotator* Rotator::getRotator(); friend Rotator* Rotator::getRotator();
friend int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
const int& dstW, const int& dstH, const uint32_t& mdpFormat,
const bool& isInterlaced);
}; };
// Holder of rotator objects. Manages lifetimes // Holder of rotator objects. Manages lifetimes

View File

@@ -248,36 +248,6 @@ int getMdpOrient(eTransform rotation) {
return retTrans; return retTrans;
} }
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)
{
float fDscale = (float)(src_w * src_h) / (float)(dst_w * dst_h);
uint32_t dscale = (int)sqrtf(fDscale);
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 getDecimationFactor(const int& src_w, const int& src_h, void getDecimationFactor(const int& src_w, const int& src_h,
const int& dst_w, const int& dst_h, uint8_t& horzDeci, const int& dst_w, const int& dst_h, uint8_t& horzDeci,
uint8_t& vertDeci) { uint8_t& vertDeci) {

View File

@@ -379,8 +379,6 @@ struct ScreenInfo {
int getMdpFormat(int format); int getMdpFormat(int format);
int getMdpFormat(int format, bool tileEnabled); int getMdpFormat(int format, bool tileEnabled);
int getHALFormat(int mdpFormat); int getHALFormat(int mdpFormat);
int getDownscaleFactor(const int& src_w, const int& src_h,
const int& dst_w, const int& dst_h);
void getDecimationFactor(const int& src_w, const int& src_h, void getDecimationFactor(const int& src_w, const int& src_h,
const int& dst_w, const int& dst_h, uint8_t& horzDeci, const int& dst_w, const int& dst_h, uint8_t& horzDeci,
uint8_t& vertDeci); uint8_t& vertDeci);
@@ -399,6 +397,10 @@ template <class T> inline void swap ( T& a, T& b )
T c(a); a=b; b=c; T c(a); a=b; b=c;
} }
template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
inline int alignup(int value, int a) { inline int alignup(int value, int a) {
//if align = 0, return the value. Else, do alignment. //if align = 0, return the value. Else, do alignment.
return a ? ((((value - 1) / a) + 1) * a) : value; return a ? ((((value - 1) / a) + 1) * a) : value;

View File

@@ -321,6 +321,10 @@ bool MDPVersion::updateSysFsInfo() {
fclose(sysfsFd); fclose(sysfsFd);
} }
if(mMDPVersion >= qdutils::MDP_V4_2 and mMDPVersion < qdutils::MDSS_V5) {
mRotDownscale = true;
}
if(mSourceSplit) { if(mSourceSplit) {
memset(sysfsPath, 0, sizeof(sysfsPath)); memset(sysfsPath, 0, sizeof(sysfsPath));
snprintf(sysfsPath , sizeof(sysfsPath), snprintf(sysfsPath , sizeof(sysfsPath),