libhwcomposer: Optimize layer crops when possible.
With in hwc list of layers if a layer above is opaque,
deduct the opaque layers crops from all the layers below
in z-order if deduction is possible with out creating
any hole.
Change-Id: I6391a13b0501cb972b134f72b58514cb807c7613
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 9837bd1..ec0644f 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -709,6 +709,8 @@
ctx->listStats[dpy].extOnlyLayerIndex = -1;
ctx->listStats[dpy].isDisplayAnimating = false;
+ optimizeLayerRects(ctx, list, dpy);
+
for (size_t i = 0; i < (size_t)ctx->listStats[dpy].numAppLayers; i++) {
hwc_layer_1_t const* layer = &list->hwLayers[i];
private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -915,6 +917,89 @@
crop_b -= crop_h * bottomCutRatio;
}
+bool isValidRect(hwc_rect_t& rect) {
+ return ((rect.bottom > rect.top) && (rect.right > rect.left)) ;
+}
+
+/* computes intersection of two rects into 3rd arg/rect */
+void getIntersection(hwc_rect_t& rect1,
+ hwc_rect_t& rect2, hwc_rect_t& irect) {
+ irect.left = max(rect1.left, rect2.left);
+ irect.top = max(rect1.top, rect2.top);
+ irect.right = min(rect1.right, rect2.right);
+ irect.bottom = min(rect1.bottom, rect2.bottom);
+}
+
+/* get union of two rects into 3rd rect */
+void getUnion(hwc_rect_t& rect1,
+ hwc_rect_t& rect2, hwc_rect_t& irect) {
+ irect.left = min(rect1.left, rect2.left);
+ irect.top = min(rect1.top, rect2.top);
+ irect.right = max(rect1.right, rect2.right);
+ irect.bottom = max(rect1.bottom, rect2.bottom);
+}
+
+/* deducts given rect from layers display-frame and source crop.
+ also it avoid hole creation.*/
+void deductRect(const hwc_layer_1_t* layer, hwc_rect_t& irect) {
+ hwc_rect_t& disprect = (hwc_rect_t&)layer->displayFrame;
+ hwc_rect_t& srcrect = (hwc_rect_t&)layer->sourceCrop;
+ int irect_w = irect.right - irect.left;
+ int irect_h = irect.bottom - irect.top;
+
+ if((disprect.left == irect.left) && (disprect.right == irect.right)) {
+ if((disprect.top == irect.top) && (irect.bottom <= disprect.bottom)) {
+ disprect.top = irect.bottom;
+ srcrect.top += irect_h;
+ }
+ else if((disprect.bottom == irect.bottom)
+ && (irect.top >= disprect.top)) {
+ disprect.bottom = irect.top;
+ srcrect.bottom -= irect_h;
+ }
+ }
+ else if((disprect.top == irect.top) && (disprect.bottom == irect.bottom)) {
+ if((disprect.left == irect.left) && (irect.right <= disprect.right)) {
+ disprect.left = irect.right;
+ srcrect.left += irect_w;
+ }
+ else if((disprect.right == irect.right)
+ && (irect.left >= disprect.left)) {
+ disprect.right = irect.left;
+ srcrect.right -= irect_w;
+ }
+ }
+}
+
+void optimizeLayerRects(hwc_context_t *ctx,
+ const hwc_display_contents_1_t *list, const int& dpy) {
+ int i=list->numHwLayers-2;
+ hwc_rect_t irect;
+ while(i > 0) {
+
+ //see if there is no blending required.
+ //If it is opaque see if we can substract this region from below layers.
+ if(list->hwLayers[i].blending == HWC_BLENDING_NONE) {
+ int j= i-1;
+ hwc_rect_t& topframe =
+ (hwc_rect_t&)list->hwLayers[i].displayFrame;
+ while(j >= 0) {
+ if(!needsScaling(ctx, &list->hwLayers[j], dpy)) {
+ hwc_rect_t& bottomframe =
+ (hwc_rect_t&)list->hwLayers[j].displayFrame;
+ getIntersection(bottomframe, topframe, (hwc_rect_t&)irect);
+ if(isValidRect(irect)) {
+ //if intersection is valid rect, deduct it
+ deductRect(&list->hwLayers[j], irect);
+ }
+ }
+ j--;
+ }
+ }
+ i--;
+ }
+}
+
void getNonWormholeRegion(hwc_display_contents_1_t* list,
hwc_rect_t& nwr)
{
@@ -928,18 +1013,11 @@
for (uint32_t i = 1; i < last; i++) {
hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
- nwr.left = min(nwr.left, displayFrame.left);
- nwr.top = min(nwr.top, displayFrame.top);
- nwr.right = max(nwr.right, displayFrame.right);
- nwr.bottom = max(nwr.bottom, displayFrame.bottom);
+ getUnion(nwr, displayFrame, nwr);
}
//Intersect with the framebuffer
- nwr.left = max(nwr.left, fbDisplayFrame.left);
- nwr.top = max(nwr.top, fbDisplayFrame.top);
- nwr.right = min(nwr.right, fbDisplayFrame.right);
- nwr.bottom = min(nwr.bottom, fbDisplayFrame.bottom);
-
+ getIntersection(nwr, fbDisplayFrame, nwr);
}
bool isExternalActive(hwc_context_t* ctx) {