HWC/Copybit :: Add swap rect feature in HAL for MDP3

We brings all swap rect level checks in HAL from surfaceflinger
for MDP3.
swap rect kicks in case of
1 Only one layer is updating.
2 No overlaypping layers.
3.Both src and dst has same value.(no scaling)
4.No video layer

Change-Id: I881958994e80b53d4969beaaf51518b727a8de78
This commit is contained in:
Ramakant Singh
2014-03-07 19:11:45 +05:30
parent 20091d8895
commit 21cec725af
4 changed files with 177 additions and 11 deletions

View File

@@ -131,6 +131,80 @@ unsigned int CopyBit::getRGBRenderingArea
return renderArea;
}
int CopyBit::getLayersChanging(hwc_context_t *ctx,
hwc_display_contents_1_t *list,
int dpy){
int changingLayerIndex = -1;
if(mLayerCache.layerCount != ctx->listStats[dpy].numAppLayers) {
mLayerCache.reset();
mFbCache.reset();
mLayerCache.updateCounts(ctx,list,dpy);
return -1;
}
int updatingLayerCount = 0;
for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
//swap rect will kick in only for single updating layer
if(mLayerCache.hnd[k] != list->hwLayers[k].handle){
updatingLayerCount ++;
if(updatingLayerCount == 1)
changingLayerIndex = k;
}
}
//since we are using more than one framebuffers,we have to
//kick in swap rect only if we are getting continuous same
//dirty rect for same layer at least equal of number of
//framebuffers
if ( updatingLayerCount == 1 ) {
hwc_rect_t dirtyRect =list->hwLayers[changingLayerIndex].dirtyRect;
for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
//disable swap rect for overlapping visible layer(s)
hwc_rect_t displayFrame = list->hwLayers[k].displayFrame;
hwc_rect_t result = getIntersection(displayFrame,dirtyRect);
if((k != changingLayerIndex) && isValidRect(result)){
return -1;
}
}
mFbCache.insertAndUpdateFbCache(dirtyRect);
if(mFbCache.getUnchangedFbDRCount(dirtyRect) <
NUM_RENDER_BUFFERS)
changingLayerIndex = -1;
}else {
mFbCache.reset();
changingLayerIndex = -1;
}
mLayerCache.updateCounts(ctx,list,dpy);
return changingLayerIndex;
}
int CopyBit::checkDirtyRect(hwc_context_t *ctx,
hwc_display_contents_1_t *list,
int dpy) {
//dirty rect will enable only if
//1.Only single layer is updating.
//2.No overlapping
//3.No scaling
//4.No video layer
if(mSwapRectEnable == false)
return -1;
int changingLayerIndex = getLayersChanging(ctx, list, dpy);
//swap rect will kick in only for single updating layer
if(changingLayerIndex == -1){
return -1;
}
if(!needsScaling(&list->hwLayers[changingLayerIndex])){
private_handle_t *hnd =
(private_handle_t *)list->hwLayers[changingLayerIndex].handle;
if( hnd && !isYuvBuffer(hnd))
return changingLayerIndex;
}
return -1;
}
bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy) {
@@ -272,9 +346,10 @@ bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
LayerProp *layerProp = ctx->layerProp[dpy];
private_handle_t *renderBuffer;
if(mCopyBitDraw == false) // there is no layer marked for copybit
if(mCopyBitDraw == false){
mFbCache.reset(); // there is no layer marked for copybit
return false ;
}
//render buffer
if (ctx->mMDP.version == qdutils::MDP_V3_0_4) {
last = (uint32_t)list->numHwLayers - 1;
@@ -301,10 +376,15 @@ bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
}
}
//Clear the transparent or left out region on the render buffer
mDirtyLayerIndex = checkDirtyRect(ctx, list, dpy);
if( mDirtyLayerIndex != -1){
hwc_layer_1_t *layer = &list->hwLayers[mDirtyLayerIndex];
clear(renderBuffer,layer->dirtyRect);
} else {
hwc_rect_t clearRegion = {0,0,0,0};
if(CBUtils::getuiClearRegion(list, clearRegion, layerProp))
clear(renderBuffer, clearRegion);
}
// numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
@@ -313,9 +393,9 @@ bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
ALOGD_IF(DEBUG_COPYBIT, "%s: Not Marked for copybit", __FUNCTION__);
continue;
}
if(layer->flags & HWC_SKIP_HWC_COMPOSITION){
//skip non updating layers
if((mDirtyLayerIndex != -1) && (mDirtyLayerIndex != i) )
continue;
}
int ret = -1;
if (list->hwLayers[i].acquireFenceFd != -1
&& ctx->mMDP.version >= qdutils::MDP_V4_0) {
@@ -429,7 +509,14 @@ int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
displayFrame.right,
displayFrame.bottom};
//change src and dst with dirtyRect
if(mDirtyLayerIndex != -1) {
srcRect.l = layer->dirtyRect.left;
srcRect.t = layer->dirtyRect.top;
srcRect.r = layer->dirtyRect.right;
srcRect.b = layer->dirtyRect.bottom;
dstRect = srcRect;
}
// Copybit dst
copybit_image_t dst;
dst.w = ALIGN(fbHandle->width,32);
@@ -733,6 +820,9 @@ CopyBit::CopyBit(hwc_context_t *ctx, const int& dpy) : mIsModeOn(false),
property_get("debug.hwc.dynThreshold", value, "2");
mDynThreshold = atof(value);
property_get("debug.sf.swaprect", value, "0");
mSwapRectEnable = atoi(value) ? true:false ;
mDirtyLayerIndex = -1;
if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
if(copybit_open(module, &mEngine) < 0) {
ALOGE("FATAL ERROR: copybit open failed.");
@@ -751,4 +841,43 @@ CopyBit::~CopyBit()
mEngine = NULL;
}
}
CopyBit::LayerCache::LayerCache() {
reset();
}
void CopyBit::LayerCache::reset() {
memset(&hnd, 0, sizeof(hnd));
layerCount = 0;
}
void CopyBit::LayerCache::updateCounts(hwc_context_t *ctx,
hwc_display_contents_1_t *list, int dpy)
{
layerCount = ctx->listStats[dpy].numAppLayers;
for (int i=0; i<ctx->listStats[dpy].numAppLayers; i++){
hnd[i] = list->hwLayers[i].handle;
}
}
CopyBit::FbCache::FbCache() {
reset();
}
void CopyBit::FbCache::reset() {
memset(&FbdirtyRect, 0, sizeof(FbdirtyRect));
FbIndex =0;
}
void CopyBit::FbCache::insertAndUpdateFbCache(hwc_rect_t dirtyRect) {
FbIndex = FbIndex % NUM_RENDER_BUFFERS;
FbdirtyRect[FbIndex] = dirtyRect;
FbIndex++;
}
int CopyBit::FbCache::getUnchangedFbDRCount(hwc_rect_t dirtyRect){
int sameDirtyCount = 0;
for (int i = 0 ; i < NUM_RENDER_BUFFERS ; i++ ){
if( FbdirtyRect[i] == dirtyRect)
sameDirtyCount++;
}
return sameDirtyCount;
}
}; //namespace qhwc

View File

@@ -50,6 +50,27 @@ public:
void setReleaseFd(int fd);
private:
/* cached data */
struct LayerCache {
int layerCount;
buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
/* c'tor */
LayerCache();
/* clear caching info*/
void reset();
void updateCounts(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy);
};
/* framebuffer cache*/
struct FbCache {
hwc_rect_t FbdirtyRect[NUM_RENDER_BUFFERS];
int FbIndex;
FbCache();
void reset();
void insertAndUpdateFbCache(hwc_rect_t dirtyRect);
int getUnchangedFbDRCount(hwc_rect_t dirtyRect);
};
// holds the copybit device
struct copybit_device_t *mEngine;
// Helper functions for copybit composition
@@ -89,8 +110,16 @@ private:
//Dynamic composition threshold for deciding copybit usage.
double mDynThreshold;
bool mSwapRectEnable;
int mAlignedFBWidth;
int mAlignedFBHeight;
int mDirtyLayerIndex;
LayerCache mLayerCache;
FbCache mFbCache;
int getLayersChanging(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy);
int checkDirtyRect(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy);
};
}; //namespace qhwc

View File

@@ -1080,6 +1080,13 @@ bool isValidRect(const hwc_rect& rect)
return ((rect.bottom > rect.top) && (rect.right > rect.left)) ;
}
bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs) {
if(lhs.left == rhs.left && lhs.top == rhs.top &&
lhs.right == rhs.right && lhs.bottom == rhs.bottom )
return true ;
return false;
}
/* computes the intersection of two rects */
hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2)
{

View File

@@ -254,6 +254,7 @@ hwc_rect_t getUnion(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
void optimizeLayerRects(const hwc_display_contents_1_t *list);
bool areLayersIntersecting(const hwc_layer_1_t* layer1,
const hwc_layer_1_t* layer2);
bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs);
// returns true if Action safe dimensions are set and target supports Actionsafe
bool isActionSafePresent(hwc_context_t *ctx, int dpy);