Merge "hwc: Enable QTI_BSP if TARGET_USES_QCOM_BSP defined."
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 8fb99d1..545a6b6 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -927,7 +927,7 @@
 
         //Setup HWC methods
         dev->device.common.tag          = HARDWARE_DEVICE_TAG;
-        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_4;
+        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_5;
         dev->device.common.module       = const_cast<hw_module_t*>(module);
         dev->device.common.close        = hwc_device_close;
         dev->device.prepare             = hwc_prepare;
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 11197c4..e21ced5 100755
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -279,19 +279,11 @@
 }
 
 void MDPComp::LayerCache::reset() {
-    memset(&hnd, 0, sizeof(hnd));
     memset(&isFBComposed, true, sizeof(isFBComposed));
     memset(&drop, false, sizeof(drop));
     layerCount = 0;
 }
 
-void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
-    const int numAppLayers = list->numHwLayers - 1;
-    for(int i = 0; i < numAppLayers; i++) {
-        hnd[i] = list->hwLayers[i].handle;
-    }
-}
-
 void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
     layerCount = curFrame.layerCount;
     memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
@@ -307,8 +299,8 @@
                 (curFrame.drop[i] != drop[i])) {
             return false;
         }
-        if(curFrame.isFBComposed[i] &&
-           (hnd[i] != list->hwLayers[i].handle)){
+        hwc_layer_1_t const* layer = &list->hwLayers[i];
+        if(curFrame.isFBComposed[i] && layerUpdating(layer)) {
             return false;
         }
     }
@@ -327,7 +319,8 @@
     }
 
     for(int i = 0; i < layerCount; i++) {
-        if(hnd[i] != list->hwLayers[i].handle)
+        hwc_layer_1_t const* layer = &list->hwLayers[i];
+        if(layerUpdating(layer))
             return false;
     }
 
@@ -474,6 +467,31 @@
     return ret;
 }
 
+hwc_rect_t MDPComp::calculateDirtyRect(const hwc_layer_1_t* layer,
+                                       hwc_rect_t& scissor) {
+    hwc_region_t surfDamage = layer->surfaceDamage;
+    hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+    hwc_rect_t dst = layer->displayFrame;
+    int x_off = dst.left - src.left;
+    int y_off = dst.top - src.top;
+    hwc_rect dirtyRect = (hwc_rect){0, 0, 0, 0};
+    hwc_rect_t updatingRect = dst;
+
+    if (surfDamage.numRects == 0) {
+      // full layer updating, dirty rect is full frame
+        dirtyRect = getIntersection(layer->displayFrame, scissor);
+    } else {
+        for(uint32_t i = 0; i < surfDamage.numRects; i++) {
+            updatingRect = moveRect(surfDamage.rects[i], x_off, y_off);
+            hwc_rect_t intersect = getIntersection(updatingRect, scissor);
+            if(isValidRect(intersect)) {
+               dirtyRect = getUnion(intersect, dirtyRect);
+            }
+        }
+     }
+     return dirtyRect;
+}
+
 /*
  * 1) Identify layers that are not visible in the updating ROI and drop them
  * from composition.
@@ -546,6 +564,9 @@
     return true;
 }
 
+/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
+ * are updating. If DirtyRegion is applicable, calculate it by accounting all
+ * the changing layer's dirtyRegion. */
 void MDPComp::generateROI(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
 
@@ -553,29 +574,24 @@
         return;
 
     struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
+    hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
+        (int)ctx->dpyAttr[mDpy].yres};
+
     for(int index = 0; index < numAppLayers; index++ ) {
         hwc_layer_1_t* layer = &list->hwLayers[index];
-        if ((mCachedFrame.hnd[index] != layer->handle) ||
+        if (layerUpdating(layer) ||
                 isYuvBuffer((private_handle_t *)layer->handle)) {
-            hwc_rect_t dst = layer->displayFrame;
-            hwc_rect_t updatingRect = dst;
-
-#ifdef QCOM_BSP
-            if(!needsScaling(layer) && !layer->transform)
+            hwc_rect_t updatingRect = layer->displayFrame;
+            if(!needsScaling(layer) && !layer->transform &&
+                   (!isYuvBuffer((private_handle_t *)layer->handle)))
             {
-                hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
-                int x_off = dst.left - src.left;
-                int y_off = dst.top - src.top;
-                updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
+                updatingRect = calculateDirtyRect(layer, fullFrame);
             }
-#endif
+
             roi = getUnion(roi, updatingRect);
         }
     }
 
-    hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
-        (int)ctx->dpyAttr[mDpy].yres};
-
     // Align ROI coordinates to panel restrictions
     roi = sanitizeROI(roi, fullFrame);
 
@@ -1349,8 +1365,8 @@
     int fbCount = 0;
 
     for(int i = 0; i < numAppLayers; i++) {
-        hwc_layer_1_t* layer = &list->hwLayers[i];
-        if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
+        hwc_layer_1_t * layer = &list->hwLayers[i];
+        if (!layerUpdating(layer)) {
             if(!frame.drop[i])
                 fbCount++;
             frame.isFBComposed[i] = true;
@@ -1641,7 +1657,6 @@
     setDynRefreshRate(ctx, list);
 #endif
 
-    mCachedFrame.cacheAll(list);
     mCachedFrame.updateCounts(mCurrentFrame);
     return ret;
 }
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index ff93e9e..f07326a 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -119,7 +119,6 @@
     /* cached data */
     struct LayerCache {
         int layerCount;
-        buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
         bool isFBComposed[MAX_NUM_APP_LAYERS];
         bool drop[MAX_NUM_APP_LAYERS];
 
@@ -127,7 +126,6 @@
         LayerCache();
         /* clear caching info*/
         void reset();
-        void cacheAll(hwc_display_contents_1_t* list);
         void updateCounts(const FrameInfo&);
         bool isSameFrame(const FrameInfo& curFrame,
                          hwc_display_contents_1_t* list);
@@ -150,6 +148,9 @@
     /* configures 4kx2k yuv layer*/
     virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
             PipeLayerPair& PipeLayerPair) = 0;
+    /* Calculates the dirtyRegion for the given layer */
+    hwc_rect_t calculateDirtyRect(const hwc_layer_1_t* layer,
+            hwc_rect_t& scissor);
     /* set/reset flags for MDPComp */
     void setMDPCompLayerFlags(hwc_context_t *ctx,
                               hwc_display_contents_1_t* list);
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 0b72d67..243dc8c 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -1166,6 +1166,12 @@
    return ((rect.bottom > rect.top) && (rect.right > rect.left)) ;
 }
 
+bool layerUpdating(const hwc_layer_1_t* layer) {
+     hwc_region_t surfDamage = layer->surfaceDamage;
+     return ((surfDamage.numRects == 0) ||
+              isValidRect(layer->surfaceDamage.rects[0]));
+}
+
 hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off)
 {
     hwc_rect_t res;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 882bde7..05827e6 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -284,6 +284,7 @@
 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);
+bool layerUpdating(const hwc_layer_1_t* layer);
 
 // returns true if Action safe dimensions are set and target supports Actionsafe
 bool isActionSafePresent(hwc_context_t *ctx, int dpy);