hwc: Rotate RGB layer using MDP Rotator

1. Use MDP rotator to rotate RGB layers which are rendered by software
2. Restrict total number of rotator sessions to 4 for all displays
3. Disable RGB layer rotation for all MDP versions < MDP5

Change-Id: Ie93111082dff9a16b614e9768df5d8ce83ff9e25
This commit is contained in:
Ramkumar Radhakrishnan
2013-11-15 19:32:47 -08:00
parent 3063fca48e
commit 9d20b39e4a
9 changed files with 97 additions and 31 deletions

View File

@@ -152,6 +152,10 @@ int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
flags |= private_handle_t::PRIV_FLAGS_TILE_RENDERED;
}
if(usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED;
}
flags |= data.allocType;
uint64_t eBaseAddr = (uint64_t)(eData.base) + eData.offset;
private_handle_t *hnd = new private_handle_t(data.fd, size, flags,

View File

@@ -202,7 +202,9 @@ struct private_handle_t : public native_handle {
PRIV_FLAGS_ITU_R_709 = 0x00800000,
PRIV_FLAGS_SECURE_DISPLAY = 0x01000000,
// Buffer is rendered in Tile Format
PRIV_FLAGS_TILE_RENDERED = 0x02000000
PRIV_FLAGS_TILE_RENDERED = 0x02000000,
// Buffer rendered using CPU/SW renderer
PRIV_FLAGS_CPU_RENDERED = 0x04000000
};
// file-descriptors

View File

@@ -143,11 +143,11 @@ static void setDMAState(hwc_context_t *ctx, int numDisplays,
hwc_layer_1_t const* layer = &list->hwLayers[layerIndex];
private_handle_t *hnd = (private_handle_t *)layer->handle;
/* If a video layer requires rotation, set the DMA state
/* If a layer requires rotation, set the DMA state
* to BLOCK_MODE */
if (UNLIKELY(isYuvBuffer(hnd)) && canUseRotator(ctx, dpy) &&
(layer->transform & HWC_TRANSFORM_ROT_90)) {
if (canUseRotator(ctx, dpy) &&
has90Transform(layer) && isRotationDoable(ctx, hnd)) {
if(not ctx->mOverlay->isDMAMultiplexingSupported()) {
if(ctx->mOverlay->isPipeTypeAttached(
overlay::utils::OV_MDP_PIPE_DMA))

View File

@@ -208,7 +208,7 @@ bool FBUpdateNonSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *lis
transform, orient);
//Store the displayFrame, will be used in getDisplayViewFrame
ctx->dpyAttr[mDpy].mDstRect = displayFrame;
setMdpFlags(layer, mdpFlags, 0, transform);
setMdpFlags(ctx, layer, mdpFlags, 0, transform);
// For External use rotator if there is a rotation value set
ret = preRotateExtDisplay(ctx, layer, info,
sourceCrop, mdpFlags, rotFlags);

View File

@@ -320,7 +320,7 @@ bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
if((not isYuvBuffer(hnd) and has90Transform(layer)) or
if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
(not isValidDimension(ctx,layer))
//More conditions here, SKIP, sRGB+Blend etc
) {
@@ -615,8 +615,9 @@ void MDPCompSplit::generateROI(hwc_context_t *ctx,
for(int index = 0; index < numAppLayers; index++ ) {
hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
if ((mCachedFrame.hnd[index] != layer->handle) ||
isYuvBuffer((private_handle_t *)layer->handle)) {
isYuvBuffer(hnd)) {
hwc_rect_t dst = layer->displayFrame;
hwc_rect_t updatingRect = dst;
@@ -713,7 +714,7 @@ bool MDPComp::tryFullFrame(hwc_context_t *ctx,
hwc_layer_1_t* layer = &list->hwLayers[i];
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(isYuvBuffer(hnd) && has90Transform(layer)) {
if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
if(!canUseRotator(ctx, mDpy)) {
ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
__FUNCTION__, mDpy);
@@ -1157,7 +1158,7 @@ bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
return false;
}
if(layer->transform & HWC_TRANSFORM_ROT_90 && !canUseRotator(ctx,mDpy)) {
if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
return false;
}
@@ -1420,7 +1421,7 @@ bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
//Capability checks
if(!resourceCheck()) {
if(!resourceCheck(ctx, list)) {
ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
return false;
}
@@ -1494,12 +1495,31 @@ bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
return true;
}
bool MDPComp::resourceCheck() {
bool MDPComp::resourceCheck(hwc_context_t* ctx,
hwc_display_contents_1_t* list) {
const bool fbUsed = mCurrentFrame.fbCount;
if(mCurrentFrame.mdpCount > sMaxPipesPerMixer - fbUsed) {
ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
return false;
}
// Init rotCount to number of rotate sessions used by other displays
int rotCount = ctx->mRotMgr->getNumActiveSessions();
// Count the number of rotator sessions required for current display
for (int index = 0; index < mCurrentFrame.layerCount; index++) {
if(!mCurrentFrame.isFBComposed[index]) {
hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
rotCount++;
}
}
}
// if number of layers to rotate exceeds max rotator sessions, bail out.
if(rotCount > RotMgr::MAX_ROT_SESS) {
ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
__FUNCTION__, mDpy);
return false;
}
return true;
}
@@ -2255,14 +2275,14 @@ int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
}
eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
setMdpFlags(layer, mdpFlags, 0, transform);
setMdpFlags(ctx, layer, mdpFlags, 0, transform);
if(lDest != OV_INVALID && rDest != OV_INVALID) {
//Enable overfetch
setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
}
if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
(*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1;
ctx->mLayerRotMap[mDpy]->add(layer, *rot);

View File

@@ -228,7 +228,7 @@ protected:
hwc_display_contents_1_t* list);
void reset(hwc_context_t *ctx);
bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer);
bool resourceCheck();
bool resourceCheck(hwc_context_t* ctx, hwc_display_contents_1_t* list);
hwc_rect_t getUpdatingFBRect(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
/* checks for conditions to enable partial udpate */

View File

@@ -955,6 +955,32 @@ bool isSecureModePolicy(int mdpVersion) {
return false;
}
bool isRotatorSupportedFormat(private_handle_t *hnd) {
// Following rotator src formats are supported by mdp driver
// TODO: Add more formats in future, if mdp driver adds support
switch(hnd->format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGB_565:
case HAL_PIXEL_FORMAT_RGB_888:
case HAL_PIXEL_FORMAT_BGRA_8888:
return true;
default:
return false;
}
return false;
}
bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd) {
// Rotate layers, if it is YUV type or rendered by CPU and not
// for the MDP versions below MDP5
if((isCPURendered(hnd) && isRotatorSupportedFormat(hnd) &&
!ctx->mMDP.version < qdutils::MDSS_V5)
|| isYuvBuffer(hnd)) {
return true;
}
return false;
}
// returns true if Action safe dimensions are set and target supports Actionsafe
bool isActionSafePresent(hwc_context_t *ctx, int dpy) {
// if external supports underscan, do nothing
@@ -1422,7 +1448,7 @@ int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
return ret;
}
void setMdpFlags(hwc_layer_1_t *layer,
void setMdpFlags(hwc_context_t *ctx, hwc_layer_1_t *layer,
ovutils::eMdpFlags &mdpFlags,
int rotDownscale, int transform) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -1443,11 +1469,6 @@ void setMdpFlags(hwc_layer_1_t *layer,
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);
}
}
if(isSecureDisplayBuffer(hnd)) {
@@ -1457,6 +1478,12 @@ void setMdpFlags(hwc_layer_1_t *layer,
ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION);
}
//Pre-rotation will be used using rotator.
if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
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(!(transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
@@ -1649,14 +1676,15 @@ int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
}
}
setMdpFlags(layer, mdpFlags, downscale, transform);
setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
//if 90 component or downscale, use rot
if((has90Transform(layer) && isRotationDoable(ctx, hnd)) || downscale) {
*rot = ctx->mRotMgr->getNext();
if(*rot == NULL) return -1;
ctx->mLayerRotMap[dpy]->add(layer, *rot);
if(!dpy)
// BWC is not tested for other formats So enable it only for YUV format
if(!dpy && isYuvBuffer(hnd))
BwcPM::setBwc(crop, dst, transform, mdpFlags);
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
@@ -1746,7 +1774,7 @@ int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
ActionSafe, and extorientation features. */
calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
setMdpFlags(layer, mdpFlagsL, 0, transform);
setMdpFlags(ctx, layer, mdpFlagsL, 0, transform);
if(lDest != OV_INVALID && rDest != OV_INVALID) {
//Enable overfetch
@@ -1760,7 +1788,7 @@ int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
whf.format = wb->getOutputFormat();
}
if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
(*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1;
ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1888,14 +1916,15 @@ int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
ActionSafe, and extorientation features. */
calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
setMdpFlags(layer, mdpFlagsL, 0, transform);
setMdpFlags(ctx, layer, mdpFlagsL, 0, transform);
trimLayer(ctx, dpy, transform, crop, dst);
if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
(*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1;
ctx->mLayerRotMap[dpy]->add(layer, *rot);
if(!dpy)
// BWC is not tested for other formats So enable it only for YUV format
if(!dpy && isYuvBuffer(hnd))
BwcPM::setBwc(crop, dst, transform, mdpFlagsL);
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {

View File

@@ -235,6 +235,10 @@ void getNonWormholeRegion(hwc_display_contents_1_t* list,
hwc_rect_t& nwr);
bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer);
bool isSecureModePolicy(int mdpVersion);
// Returns true, if the input layer format is supported by rotator
bool isRotatorSupportedFormat(private_handle_t *hnd);
//Returns true, if the layer is YUV or the layer has been rendered by CPU
bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd);
bool isExternalActive(hwc_context_t* ctx);
bool isAlphaScaled(hwc_layer_1_t const* layer);
bool needsScaling(hwc_layer_1_t const* layer);
@@ -315,7 +319,7 @@ int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
int fd);
//Sets appropriate mdp flags for a layer.
void setMdpFlags(hwc_layer_1_t *layer,
void setMdpFlags(hwc_context_t *ctx, hwc_layer_1_t *layer,
ovutils::eMdpFlags &mdpFlags,
int rotDownscale, int transform);
@@ -400,6 +404,10 @@ static inline bool isTileRendered(const private_handle_t* hnd) {
return (hnd && (private_handle_t::PRIV_FLAGS_TILE_RENDERED & hnd->flags));
}
static inline bool isCPURendered(const private_handle_t* hnd) {
return (hnd && (private_handle_t::PRIV_FLAGS_CPU_RENDERED & hnd->flags));
}
//Return true if buffer is marked locked
static inline bool isBufferLocked(const private_handle_t* hnd) {
return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
@@ -577,7 +585,7 @@ static inline bool isYuvPresent (hwc_context_t *ctx, int dpy) {
return ctx->listStats[dpy].yuvCount;
}
static inline bool has90Transform(hwc_layer_1_t *layer) {
static inline bool has90Transform(hwc_layer_1_t const* layer) {
return ((layer->transform & HWC_TRANSFORM_ROT_90) &&
!(layer->flags & HWC_COLOR_FILL));
}

View File

@@ -210,6 +210,9 @@ private:
// Holder of rotator objects. Manages lifetimes
class RotMgr {
public:
//Virtually we can support as many rotator sessions as possible, However
// more number of rotator sessions leads to performance issues, so
// restricting the max rotator session to 4
enum { MAX_ROT_SESS = 4 };
~RotMgr();