h/q/d: Optimize framebuffer layer update
While doing mixed mode composition, update only the region of the
framebuffer where layer contents are cached or updated. Avoids
MDP fetch for non-visible contents of FB.
Change-Id: I20997d79e02a6bac60d7333c28c6dde134263197
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 78a05e9..cc9e3b9 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -62,7 +62,8 @@
bool IFBUpdate::prepareAndValidate(hwc_context_t *ctx,
hwc_display_contents_1 *list, int fbZorder) {
- return prepare(ctx, list, fbZorder) &&
+ hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
+ return prepare(ctx, list, layer->displayFrame, fbZorder) &&
ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd);
}
@@ -106,19 +107,19 @@
}
bool FBUpdateNonSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder) {
+ hwc_rect_t fbUpdatingRect, int fbZorder) {
if(!ctx->mMDP.hasOverlay) {
ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
__FUNCTION__);
return false;
}
- mModeOn = configure(ctx, list, fbZorder);
+ mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
return mModeOn;
}
// Configure
bool FBUpdateNonSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder) {
+ hwc_rect_t fbUpdatingRect, int fbZorder) {
bool ret = false;
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
if (LIKELY(ctx->mOverlay)) {
@@ -159,6 +160,15 @@
hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
hwc_rect_t displayFrame = layer->displayFrame;
+
+ // No FB update optimization on (1) Custom FB resolution,
+ // (2) External Mirror mode, (3) External orientation
+ if(!ctx->dpyAttr[mDpy].customFBSize && !ctx->mBufferMirrorMode
+ && !ctx->mExtOrientation) {
+ sourceCrop = fbUpdatingRect;
+ displayFrame = fbUpdatingRect;
+ }
+
int transform = layer->transform;
int rotFlags = ovutils::ROT_FLAGS_NONE;
@@ -251,20 +261,20 @@
}
bool FBUpdateSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder) {
+ hwc_rect_t fbUpdatingRect, int fbZorder) {
if(!ctx->mMDP.hasOverlay) {
ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
__FUNCTION__);
return false;
}
ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
- mModeOn = configure(ctx, list, fbZorder);
+ mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
return mModeOn;
}
// Configure
bool FBUpdateSplit::configure(hwc_context_t *ctx,
- hwc_display_contents_1 *list, int fbZorder) {
+ hwc_display_contents_1 *list, hwc_rect_t fbUpdatingRect, int fbZorder) {
bool ret = false;
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
if (LIKELY(ctx->mOverlay)) {
@@ -328,8 +338,8 @@
getBlending(layer->blending));
ov.setSource(pargR, destR);
- hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
- hwc_rect_t displayFrame = layer->displayFrame;
+ hwc_rect_t sourceCrop = fbUpdatingRect;
+ hwc_rect_t displayFrame = fbUpdatingRect;
const float xres = ctx->dpyAttr[mDpy].xres;
const int lSplit = getLeftSplit(ctx, mDpy);
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index da4cdfc..c8347fa 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -39,7 +39,7 @@
virtual ~IFBUpdate() {};
// Sets up members and prepares overlay if conditions are met
virtual bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder) = 0;
+ hwc_rect_t fbUpdatingRect, int fbZorder) = 0;
virtual bool prepareAndValidate(hwc_context_t *ctx,
hwc_display_contents_1 *list, int fbZorder);
// Draws layer
@@ -64,12 +64,12 @@
explicit FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy);
virtual ~FBUpdateNonSplit() {};
bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder);
+ hwc_rect_t fbUpdatingRect, int fbZorder);
bool draw(hwc_context_t *ctx, private_handle_t *hnd);
void reset();
private:
bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder);
+ hwc_rect_t fbUpdatingRect, int fbZorder);
bool preRotateExtDisplay(hwc_context_t *ctx,
hwc_layer_1_t *layer,
ovutils::Whf &info,
@@ -85,12 +85,12 @@
explicit FBUpdateSplit(hwc_context_t *ctx, const int& dpy);
virtual ~FBUpdateSplit() {};
bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder);
+ hwc_rect_t fbUpdatingRect, int fbZorder);
bool draw(hwc_context_t *ctx, private_handle_t *hnd);
void reset();
private:
bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
- int fbZorder);
+ hwc_rect_t fbUpdatingRect, int fbZorder);
ovutils::eDest mDestLeft; //left pipe to draw on
ovutils::eDest mDestRight; //right pipe to draw on
};
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 6ff1aa3..440cbd5 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -1212,6 +1212,22 @@
mCurrentFrame.fbCount);
}
+hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list){
+ hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
+ hwc_layer_1_t *fbLayer = &list->hwLayers[mCurrentFrame.layerCount];
+
+ /* Update only the region of FB needed for composition */
+ for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
+ if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ hwc_rect_t dst = layer->displayFrame;
+ fbRect = getUnion(fbRect, dst);
+ }
+ }
+ return fbRect;
+}
+
bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
@@ -1229,7 +1245,9 @@
//Configure framebuffer first if applicable
if(mCurrentFrame.fbZ >= 0) {
- if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
+ hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
+ if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
+ {
ALOGD_IF(isDebug(), "%s configure framebuffer failed",
__FUNCTION__);
return false;
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index f2a8eda..c5f46e3 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -223,6 +223,8 @@
void reset(hwc_context_t *ctx);
bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer);
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);
int mDpy;
static bool sEnabled;