hwc : Add support for single layer Bypass in MDP3
If the display list contains single layer and that layer
has same properties as Frame Buffer, avoid BLIT on Frame buffer
and pass it directly to display.
Change-Id: I24decaca4788432a55b550caa2a1354a670cd6fa
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index e5c7ce7..902f882 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -601,6 +601,12 @@
hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
}
+ if(isAbcInUse(ctx) == true) {
+ int index = ctx->listStats[dpy].renderBufIndexforABC;
+ hwc_layer_1_t *tempLayer = &list->hwLayers[index];
+ hnd = (private_handle_t *)tempLayer->handle;
+ }
+
if(hnd) {
if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index f379cf8..2cd2d2a 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -340,8 +340,46 @@
return ret;
}
-bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
- int dpy, int32_t *fd) {
+bool CopyBit::drawUsingAppBufferComposition(hwc_context_t *ctx,
+ hwc_display_contents_1_t *list,
+ int dpy) {
+ int layerCount = 0;
+ uint32_t last = list->numHwLayers - 1;
+ hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+ private_handle_t *fbhnd = (private_handle_t *)fbLayer->handle;
+
+ if(ctx->enableABC == false)
+ return false;
+
+ if(ctx->listStats[dpy].numAppLayers != MAX_LAYERS_FOR_ABC )
+ return false;
+
+ layerCount = ctx->listStats[dpy].numAppLayers;
+ //bottom most layer should
+ //equal to FB
+ hwc_layer_1_t *tmpLayer = &list->hwLayers[0];
+ private_handle_t *hnd = (private_handle_t *)tmpLayer->handle;
+ if(hnd && fbhnd && (hnd->size == fbhnd->size) &&
+ (hnd->width == fbhnd->width) && (hnd->height == fbhnd->height)){
+ if(tmpLayer->transform ||
+ (!(hnd->format == HAL_PIXEL_FORMAT_RGBA_8888 ||
+ hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)) ||
+ (needsScaling(tmpLayer) == true)) {
+ return false;
+ }else {
+ ctx->listStats[dpy].renderBufIndexforABC = 0;
+ }
+ }
+
+ if(ctx->listStats[dpy].renderBufIndexforABC == 0){
+ return true;
+ // Todo::same for two layers.
+ }
+ return false;
+}
+
+bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+ int dpy, int32_t *fd) {
// draw layers marked for COPYBIT
int retVal = true;
int copybitLayerCount = 0;
@@ -353,6 +391,10 @@
mFbCache.reset(); // there is no layer marked for copybit
return false ;
}
+
+ if(drawUsingAppBufferComposition(ctx, list, dpy)) {
+ return true;
+ }
//render buffer
if (ctx->mMDP.version == qdutils::MDP_V3_0_4) {
last = (uint32_t)list->numHwLayers - 1;
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index 14f8cfc..3137538 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -27,7 +27,7 @@
//twice
#define MAX_SCALE_FACTOR 16
#define MIN_SCALE_FACTOR 0.0625
-
+#define MAX_LAYERS_FOR_ABC 1
namespace qhwc {
class CopyBit {
@@ -73,6 +73,9 @@
// holds the copybit device
struct copybit_device_t *mEngine;
+ bool drawUsingAppBufferComposition(hwc_context_t *ctx,
+ hwc_display_contents_1_t *list,
+ int dpy);
// Helper functions for copybit composition
int drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
private_handle_t *renderBuffer, bool isFG);
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 972f12f..ea3aecb 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -274,6 +274,10 @@
ctx->mMDPDownscaleEnabled = true;
}
+ ctx->enableABC = false;
+ property_get("debug.sf.hwc.canUseABC", value, "0");
+ ctx->enableABC = atoi(value) ? true : false;
+
// Initialize gpu perfomance hint related parameters
property_get("sys.hwc.gpu_perf_mode", value, "0");
#ifdef QCOM_BSP
@@ -838,6 +842,7 @@
ctx->listStats[dpy].yuv4k2kCount = 0;
ctx->mViewFrame[dpy] = (hwc_rect_t){0, 0, 0, 0};
ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
+ ctx->listStats[dpy].renderBufIndexforABC = -1;
resetROI(ctx, dpy);
@@ -1323,7 +1328,8 @@
}
for(uint32_t i = 0; i < list->numHwLayers; i++) {
- if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
+ if(((isAbcInUse(ctx)== true ) ||
+ (list->hwLayers[i].compositionType == HWC_OVERLAY)) &&
list->hwLayers[i].acquireFenceFd >= 0) {
if(UNLIKELY(swapzero))
acquireFd[count++] = -1;
@@ -1379,7 +1385,9 @@
} else if(list->hwLayers[i].releaseFenceFd < 0 ) {
#ifdef QCOM_BSP
//If rotator has not already populated this field
- if(list->hwLayers[i].compositionType == HWC_BLIT) {
+ // & if it's a not VPU layer
+ if((list->hwLayers[i].compositionType == HWC_BLIT)&&
+ (isAbcInUse(ctx) == false)){
//For Blit, the app layers should be released when the Blit is
//complete. This fd was passed from copybit->draw
list->hwLayers[i].releaseFenceFd = dup(fd);
@@ -2017,6 +2025,10 @@
ctx->layerProp[dpy] = new LayerProp[numAppLayers];
}
+bool isAbcInUse(hwc_context_t *ctx){
+ return (ctx->enableABC && ctx->listStats[0].renderBufIndexforABC == 0);
+}
+
/* Since we fake non-Hybrid WFD solution as external display, this
* function helps us in determining the priority between external
* (hdmi/non-Hybrid WFD display) and virtual display devices(SSD/
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 4cfed2a..d7fa73d 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -127,6 +127,8 @@
bool isSecurePresent;
hwc_rect_t lRoi; //left ROI
hwc_rect_t rRoi; //right ROI. Unused in single DSI panels.
+ //App Buffer Composition index
+ int renderBufIndexforABC;
};
struct LayerProp {
@@ -251,6 +253,7 @@
int getBlending(int blending);
bool isGLESOnlyComp(hwc_context_t *ctx, const int& dpy);
void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers);
+bool isAbcInUse(hwc_context_t *ctx);
bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
const hwc_display_contents_1_t *list);
@@ -556,6 +559,8 @@
// persist.hwc.enable_vds
bool mVDSEnabled;
struct gpu_hint_info mGPUHintInfo;
+ //App Buffer Composition
+ bool enableABC;
};
namespace qhwc {