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; 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; flags |= data.allocType;
uint64_t eBaseAddr = (uint64_t)(eData.base) + eData.offset; uint64_t eBaseAddr = (uint64_t)(eData.base) + eData.offset;
private_handle_t *hnd = new private_handle_t(data.fd, size, flags, 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_ITU_R_709 = 0x00800000,
PRIV_FLAGS_SECURE_DISPLAY = 0x01000000, PRIV_FLAGS_SECURE_DISPLAY = 0x01000000,
// Buffer is rendered in Tile Format // 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 // 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]; hwc_layer_1_t const* layer = &list->hwLayers[layerIndex];
private_handle_t *hnd = (private_handle_t *)layer->handle; 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 */ * to BLOCK_MODE */
if (UNLIKELY(isYuvBuffer(hnd)) && canUseRotator(ctx, dpy) && if (canUseRotator(ctx, dpy) &&
(layer->transform & HWC_TRANSFORM_ROT_90)) { has90Transform(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

@@ -208,7 +208,7 @@ bool FBUpdateNonSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *lis
transform, orient); transform, orient);
//Store the displayFrame, will be used in getDisplayViewFrame //Store the displayFrame, will be used in getDisplayViewFrame
ctx->dpyAttr[mDpy].mDstRect = displayFrame; 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 // For External use rotator if there is a rotation value set
ret = preRotateExtDisplay(ctx, layer, info, ret = preRotateExtDisplay(ctx, layer, info,
sourceCrop, mdpFlags, rotFlags); 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) { bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
private_handle_t *hnd = (private_handle_t *)layer->handle; 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)) (not isValidDimension(ctx,layer))
//More conditions here, SKIP, sRGB+Blend etc //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++ ) { for(int index = 0; index < numAppLayers; index++ ) {
hwc_layer_1_t* layer = &list->hwLayers[index]; hwc_layer_1_t* layer = &list->hwLayers[index];
private_handle_t *hnd = (private_handle_t *)layer->handle;
if ((mCachedFrame.hnd[index] != 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 dst = layer->displayFrame;
hwc_rect_t updatingRect = dst; hwc_rect_t updatingRect = dst;
@@ -713,7 +714,7 @@ bool MDPComp::tryFullFrame(hwc_context_t *ctx,
hwc_layer_1_t* layer = &list->hwLayers[i]; hwc_layer_1_t* layer = &list->hwLayers[i];
private_handle_t *hnd = (private_handle_t *)layer->handle; private_handle_t *hnd = (private_handle_t *)layer->handle;
if(isYuvBuffer(hnd) && has90Transform(layer)) { if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
if(!canUseRotator(ctx, mDpy)) { if(!canUseRotator(ctx, mDpy)) {
ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d", ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
__FUNCTION__, mDpy); __FUNCTION__, mDpy);
@@ -1157,7 +1158,7 @@ bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
return false; 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__); ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
return false; return false;
} }
@@ -1420,7 +1421,7 @@ bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
hwc_display_contents_1_t* list) { hwc_display_contents_1_t* list) {
//Capability checks //Capability checks
if(!resourceCheck()) { if(!resourceCheck(ctx, list)) {
ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__); ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
return false; return false;
} }
@@ -1494,12 +1495,31 @@ bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
return true; return true;
} }
bool MDPComp::resourceCheck() { bool MDPComp::resourceCheck(hwc_context_t* ctx,
hwc_display_contents_1_t* list) {
const bool fbUsed = mCurrentFrame.fbCount; const bool fbUsed = mCurrentFrame.fbCount;
if(mCurrentFrame.mdpCount > sMaxPipesPerMixer - fbUsed) { if(mCurrentFrame.mdpCount > sMaxPipesPerMixer - fbUsed) {
ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__); ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
return false; 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; return true;
} }
@@ -2255,14 +2275,14 @@ int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
} }
eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION; eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
setMdpFlags(layer, mdpFlags, 0, transform); setMdpFlags(ctx, layer, mdpFlags, 0, 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(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) { if(has90Transform(layer) && 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);

View File

@@ -228,7 +228,7 @@ protected:
hwc_display_contents_1_t* list); hwc_display_contents_1_t* list);
void reset(hwc_context_t *ctx); void reset(hwc_context_t *ctx);
bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer); 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_rect_t getUpdatingFBRect(hwc_context_t *ctx,
hwc_display_contents_1_t* list); hwc_display_contents_1_t* list);
/* checks for conditions to enable partial udpate */ /* checks for conditions to enable partial udpate */

View File

@@ -955,6 +955,32 @@ bool isSecureModePolicy(int mdpVersion) {
return false; 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 // returns true if Action safe dimensions are set and target supports Actionsafe
bool isActionSafePresent(hwc_context_t *ctx, int dpy) { bool isActionSafePresent(hwc_context_t *ctx, int dpy) {
// if external supports underscan, do nothing // 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; return ret;
} }
void setMdpFlags(hwc_layer_1_t *layer, void setMdpFlags(hwc_context_t *ctx, hwc_layer_1_t *layer,
ovutils::eMdpFlags &mdpFlags, ovutils::eMdpFlags &mdpFlags,
int rotDownscale, int transform) { int rotDownscale, int transform) {
private_handle_t *hnd = (private_handle_t *)layer->handle; private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -1443,11 +1469,6 @@ void setMdpFlags(hwc_layer_1_t *layer,
ovutils::setMdpFlags(mdpFlags, ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_DEINTERLACE); 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)) { if(isSecureDisplayBuffer(hnd)) {
@@ -1457,6 +1478,12 @@ void setMdpFlags(hwc_layer_1_t *layer,
ovutils::setMdpFlags(mdpFlags, ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION); 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 //No 90 component and no rot-downscale then flips done by MDP
//If we use rot then it might as well do flips //If we use rot then it might as well do flips
if(!(transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) { 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 //if 90 component or downscale, use rot
((transform & HWC_TRANSFORM_ROT_90) || downscale)) { if((has90Transform(layer) && isRotationDoable(ctx, hnd)) || downscale) {
*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);
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); BwcPM::setBwc(crop, dst, transform, 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) {
@@ -1746,7 +1774,7 @@ int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
ActionSafe, and extorientation features. */ ActionSafe, and extorientation features. */
calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient); 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) { if(lDest != OV_INVALID && rDest != OV_INVALID) {
//Enable overfetch //Enable overfetch
@@ -1760,7 +1788,7 @@ int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
whf.format = wb->getOutputFormat(); whf.format = wb->getOutputFormat();
} }
if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) { if(has90Transform(layer) && 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);
@@ -1888,14 +1916,15 @@ int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
ActionSafe, and extorientation features. */ ActionSafe, and extorientation features. */
calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient); 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); trimLayer(ctx, dpy, transform, crop, dst);
if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) { if(has90Transform(layer) && 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);
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); BwcPM::setBwc(crop, dst, transform, 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) {

View File

@@ -235,6 +235,10 @@ void getNonWormholeRegion(hwc_display_contents_1_t* list,
hwc_rect_t& nwr); hwc_rect_t& nwr);
bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer); bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer);
bool isSecureModePolicy(int mdpVersion); 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 isExternalActive(hwc_context_t* ctx);
bool isAlphaScaled(hwc_layer_1_t const* layer); bool isAlphaScaled(hwc_layer_1_t const* layer);
bool needsScaling(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); int fd);
//Sets appropriate mdp flags for a layer. //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, ovutils::eMdpFlags &mdpFlags,
int rotDownscale, int transform); 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)); 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 //Return true if buffer is marked locked
static inline bool isBufferLocked(const private_handle_t* hnd) { static inline bool isBufferLocked(const private_handle_t* hnd) {
return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags)); 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; 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) && return ((layer->transform & HWC_TRANSFORM_ROT_90) &&
!(layer->flags & HWC_COLOR_FILL)); !(layer->flags & HWC_COLOR_FILL));
} }

View File

@@ -210,6 +210,9 @@ private:
// Holder of rotator objects. Manages lifetimes // Holder of rotator objects. Manages lifetimes
class RotMgr { class RotMgr {
public: 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 }; enum { MAX_ROT_SESS = 4 };
~RotMgr(); ~RotMgr();