Merge "display: libqdutils: add the MDP h/w version for msmferrum"
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index d12d9f0..0a1335a 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -589,9 +589,11 @@
             // if primary resolution is more than the hdmi resolution
             // configure dpy attr to primary resolution and set
             // downscale mode
-            // Restrict this upto 1080p resolution max
-            if(((priW * priH) > (width * height)) &&
-               ((priW * priH) <= SUPPORTED_DOWNSCALE_AREA)) {
+            // Restrict this upto 1080p resolution max, if target does not
+            // support source split feature.
+            if((priW * priH) > (width * height) &&
+                (((priW * priH) <= SUPPORTED_DOWNSCALE_AREA) ||
+                qdutils::MDPVersion::getInstance().isSrcSplit())) {
                 // tmpW and tmpH will hold the primary dimensions before we
                 // update the aspect ratio if necessary.
                 int tmpW = priW;
@@ -609,14 +611,39 @@
                 // keeping aspect ratio intact.
                 hwc_rect r = {0, 0, 0, 0};
                 qdutils::getAspectRatioPosition(tmpW, tmpH, width, height, r);
-                mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres =
-                                                              r.right - r.left;
-                mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres =
-                                                              r.bottom - r.top;
+                int newExtW = r.right - r.left;
+                int newExtH = r.bottom - r.top;
+                int alignedExtW;
+                int alignedExtH;
+                // On 8994 and below targets MDP supports only 4X downscaling,
+                // Restricting selected external resolution to be exactly 4X
+                // greater resolution than actual external resolution
+                int maxMDPDownScale =
+                        qdutils::MDPVersion::getInstance().getMaxMDPDownscale();
+                if((width * height * maxMDPDownScale) < (newExtW * newExtH)) {
+                    float upScaleFactor = (float)maxMDPDownScale / 2.0f;
+                    newExtW = (int)((float)width * upScaleFactor);
+                    newExtH = (int)((float)height * upScaleFactor);
+                }
+                // Align it down so that the new aligned resolution does not
+                // exceed the maxMDPDownscale factor
+                alignedExtW = overlay::utils::aligndown(newExtW, 4);
+                alignedExtH = overlay::utils::aligndown(newExtH, 4);
+                mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = alignedExtW;
+                mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = alignedExtH;
                 // Set External Display MDP Downscale mode indicator
                 mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode =true;
             }
         }
+        ALOGD_IF(DEBUG_MDPDOWNSCALE, "Selected external resolution [%d X %d] "
+                 "maxMDPDownScale %d MDPDownScaleMode %d srcSplitEnabled %d "
+                 "MDPDownscale feature %d",
+                 mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres,
+                 mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres,
+                 qdutils::MDPVersion::getInstance().getMaxMDPDownscale(),
+                 mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode,
+                 qdutils::MDPVersion::getInstance().isSrcSplit(),
+                 mHwcContext->mMDPDownscaleEnabled);
         //Initialize the display viewFrame info
         mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].left = 0;
         mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].top = 0;
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index ccf6ed5..73bbe23 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -34,12 +34,14 @@
 #include <fcntl.h>
 #include <cutils/log.h>
 #include <errno.h>
+#include <utils/Trace.h>
 #include "gralloc_priv.h"
 #include "ionalloc.h"
 
 using gralloc::IonAlloc;
 
 #define ION_DEVICE "/dev/ion"
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
 
 int IonAlloc::open_device()
 {
@@ -64,6 +66,7 @@
 
 int IonAlloc::alloc_buffer(alloc_data& data)
 {
+    ATRACE_CALL();
     Locker::Autolock _l(mLock);
     int err = 0;
     struct ion_handle_data handle_data;
@@ -123,6 +126,7 @@
 int IonAlloc::free_buffer(void* base, unsigned int size, unsigned int offset,
         int fd)
 {
+    ATRACE_CALL();
     Locker::Autolock _l(mLock);
     ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d",
           base, size, fd);
@@ -140,6 +144,7 @@
 int IonAlloc::map_buffer(void **pBase, unsigned int size, unsigned int offset,
         int fd)
 {
+    ATRACE_CALL();
     int err = 0;
     void *base = 0;
     // It is a (quirky) requirement of ION to have opened the
@@ -165,6 +170,7 @@
 int IonAlloc::unmap_buffer(void *base, unsigned int size,
         unsigned int /*offset*/)
 {
+    ATRACE_CALL();
     ALOGD_IF(DEBUG, "ion: Unmapping buffer  base:%p size:%u", base, size);
     int err = 0;
     if(munmap(base, size)) {
@@ -178,6 +184,8 @@
 int IonAlloc::clean_buffer(void *base, unsigned int size, unsigned int offset,
         int fd, int op)
 {
+    ATRACE_CALL();
+    ATRACE_INT("operation id", op);
     struct ion_flush_data flush_data;
     struct ion_fd_data fd_data;
     struct ion_handle_data handle_data;
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 2f2ddc1..13e662a 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -29,6 +29,7 @@
 
 #include <cutils/log.h>
 #include <cutils/atomic.h>
+#include <utils/Trace.h>
 
 #include <hardware/hardware.h>
 #include <hardware/gralloc.h>
@@ -39,6 +40,8 @@
 #include "memalloc.h"
 #include <qdMetaData.h>
 
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
 using namespace gralloc;
 /*****************************************************************************/
 
@@ -55,6 +58,7 @@
 static int gralloc_map(gralloc_module_t const* module,
                        buffer_handle_t handle)
 {
+    ATRACE_CALL();
     if(!module)
         return -EINVAL;
 
@@ -92,6 +96,7 @@
 static int gralloc_unmap(gralloc_module_t const* module,
                          buffer_handle_t handle)
 {
+    ATRACE_CALL();
     if(!module)
         return -EINVAL;
 
@@ -130,6 +135,7 @@
 int gralloc_register_buffer(gralloc_module_t const* module,
                             buffer_handle_t handle)
 {
+    ATRACE_CALL();
     if (!module || private_handle_t::validate(handle) < 0)
         return -EINVAL;
 
@@ -157,6 +163,7 @@
 int gralloc_unregister_buffer(gralloc_module_t const* module,
                               buffer_handle_t handle)
 {
+    ATRACE_CALL();
     if (!module || private_handle_t::validate(handle) < 0)
         return -EINVAL;
 
@@ -179,6 +186,7 @@
 int terminateBuffer(gralloc_module_t const* module,
                     private_handle_t* hnd)
 {
+    ATRACE_CALL();
     if(!module)
         return -EINVAL;
 
@@ -207,6 +215,7 @@
 static int gralloc_map_and_invalidate (gralloc_module_t const* module,
                                        buffer_handle_t handle, int usage)
 {
+    ATRACE_CALL();
     if (!module || private_handle_t::validate(handle) < 0)
         return -EINVAL;
 
@@ -243,6 +252,7 @@
                  int /*l*/, int /*t*/, int /*w*/, int /*h*/,
                  void** vaddr)
 {
+    ATRACE_CALL();
     private_handle_t* hnd = (private_handle_t*)handle;
     int err = gralloc_map_and_invalidate(module, handle, usage);
     if(!err)
@@ -255,6 +265,7 @@
                  int /*l*/, int /*t*/, int /*w*/, int /*h*/,
                  struct android_ycbcr *ycbcr)
 {
+    ATRACE_CALL();
     private_handle_t* hnd = (private_handle_t*)handle;
     int err = gralloc_map_and_invalidate(module, handle, usage);
     if(!err)
@@ -265,6 +276,7 @@
 int gralloc_unlock(gralloc_module_t const* module,
                    buffer_handle_t handle)
 {
+    ATRACE_CALL();
     if (!module || private_handle_t::validate(handle) < 0)
         return -EINVAL;
 
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 24fd771..8164fd3 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -597,6 +597,21 @@
     for(int j = 0; j < ptorInfo->count; j++) {
         int ovlapIndex = ptorInfo->layerIndex[j];
         hwc_rect_t overlap = list->hwLayers[ovlapIndex].displayFrame;
+        if(j) {
+            /**
+             * It's possible that 2 PTOR layers might have overlapping.
+             * In such case, remove the intersection(again if peripheral)
+             * from the lower PTOR layer to avoid overlapping.
+             * If intersection is not on peripheral then compromise
+             * by reducing number of PTOR layers.
+             **/
+            int prevOvlapIndex = ptorInfo->layerIndex[0];
+            hwc_rect_t prevOvlap = list->hwLayers[prevOvlapIndex].displayFrame;
+            hwc_rect_t commonRect = getIntersection(prevOvlap, overlap);
+            if(isValidRect(commonRect)) {
+                overlap = deductRect(overlap, commonRect);
+            }
+        }
 
         // Draw overlapped content of layers on render buffer
         for (int i = 0; i <= ovlapIndex; i++) {
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 5df0fa0..b222d32 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -333,7 +333,7 @@
             // Color layer
             return true;
         }
-        ALOGE("%s: layer handle is NULL", __FUNCTION__);
+        ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
         return false;
     }
 
@@ -425,14 +425,21 @@
         ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
                 __FUNCTION__);
         ret = false;
-    } else if(isSecondaryConfiguring(ctx)) {
-        ALOGD_IF( isDebug(),"%s: External Display connection is pending",
-                  __FUNCTION__);
-        ret = false;
-    } else if(ctx->isPaddingRound) {
-        ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
-                 __FUNCTION__,mDpy);
-        ret = false;
+    } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
+       /* TODO: freeing up all the resources only for the targets having total
+                number of pipes < 8. Need to analyze number of VIG pipes used
+                for primary in previous draw cycle and accordingly decide
+                whether to fall back to full GPU comp or video only comp
+        */
+        if(isSecondaryConfiguring(ctx)) {
+            ALOGD_IF( isDebug(),"%s: External Display connection is pending",
+                      __FUNCTION__);
+            ret = false;
+        } else if(ctx->isPaddingRound) {
+            ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
+                     __FUNCTION__,mDpy);
+            ret = false;
+        }
     }
     return ret;
 }
@@ -691,6 +698,18 @@
         return false;
     }
 
+    // if secondary is configuring or Padding round, fall back to video only
+    // composition and release all assigned non VIG pipes from primary.
+    if(isSecondaryConfiguring(ctx)) {
+        ALOGD_IF( isDebug(),"%s: External Display connection is pending",
+                  __FUNCTION__);
+        return false;
+    } else if(ctx->isPaddingRound) {
+        ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
+                 __FUNCTION__,mDpy);
+        return false;
+    }
+
     MDPVersion& mdpHw = MDPVersion::getInstance();
     if(mDpy > HWC_DISPLAY_PRIMARY &&
             (priDispW >  mdpHw.getMaxMixerWidth()) &&
@@ -876,28 +895,10 @@
         }
     }
 
-    if(isValidRect(getIntersection(overlapRect[0], overlapRect[1]))) {
-        ALOGD_IF(isDebug(), "%s: Ignore Rect2 its intersects with Rect1",
-                 __FUNCTION__);
-        // reset second minLayerIndex[1];
-        minLayerIndex[1] = -1;
-        numPTORLayersFound--;
-    }
-
     // No overlap layers
     if (!numPTORLayersFound)
         return false;
 
-    ctx->mPtorInfo.count = numPTORLayersFound;
-    for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
-        ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
-    }
-
-    if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
-        // reset PTOR
-        ctx->mPtorInfo.count = 0;
-        return false;
-    }
     // Store the displayFrame and the sourceCrops of the layers
     hwc_rect_t displayFrame[numAppLayers];
     hwc_rect_t sourceCrop[numAppLayers];
@@ -907,6 +908,35 @@
         sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
     }
 
+    /**
+     * It's possible that 2 PTOR layers might have overlapping.
+     * In such case, remove the intersection(again if peripheral)
+     * from the lower PTOR layer to avoid overlapping.
+     * If intersection is not on peripheral then compromise
+     * by reducing number of PTOR layers.
+     **/
+    hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
+    if(isValidRect(commonRect)) {
+        overlapRect[1] = deductRect(overlapRect[1], commonRect);
+        list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
+    }
+
+    ctx->mPtorInfo.count = numPTORLayersFound;
+    for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
+        ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
+    }
+
+    if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
+        // reset PTOR
+        ctx->mPtorInfo.count = 0;
+        if(isValidRect(commonRect)) {
+            // If PTORs are intersecting restore displayframe of PTOR[1]
+            // before returning, as we have modified it above.
+            list->hwLayers[minLayerIndex[1]].displayFrame =
+                    displayFrame[minLayerIndex[1]];
+        }
+        return false;
+    }
     private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
     Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
 
@@ -1771,13 +1801,15 @@
     }
 
     const int numLayers = ctx->listStats[mDpy].numAppLayers;
-
-    if(property_get("debug.hwc.simulate", property, NULL) > 0) {
-        int currentFlags = atoi(property);
-        if(currentFlags != sSimulationFlags) {
-            sSimulationFlags = currentFlags;
-            ALOGE("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
-                    sSimulationFlags, sSimulationFlags);
+    if(mDpy == HWC_DISPLAY_PRIMARY) {
+        sSimulationFlags = 0;
+        if(property_get("debug.hwc.simulate", property, NULL) > 0) {
+            int currentFlags = atoi(property);
+            if(currentFlags != sSimulationFlags) {
+                sSimulationFlags = currentFlags;
+                ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
+                        sSimulationFlags, sSimulationFlags);
+            }
         }
     }
     // reset PTOR
@@ -1829,6 +1861,8 @@
             memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
             mCurrentFrame.dropCount = 0;
             ret = -1;
+            ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
+                    "MDP Composition Strategies Failed");
         }
     } else {
         ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
@@ -2477,6 +2511,9 @@
         else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
             whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
     }
+    /* Calculate the external display position based on MDP downscale,
+       ActionSafe, and extorientation features. */
+    calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
 
     int downscale = getRotDownscale(ctx, layer);
     eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index dcd9cf3..b339cb7 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -620,6 +620,10 @@
                 displayFrame.top = int(hRatio*(float)displayFrame.top);
                 displayFrame.right = int(wRatio*(float)displayFrame.right);
                 displayFrame.bottom = int(hRatio*(float)displayFrame.bottom);
+                ALOGD_IF(DEBUG_MDPDOWNSCALE, "Calculated external display frame"
+                         " for MDPDownscale feature [%d %d %d %d]",
+                         displayFrame.left, displayFrame.top,
+                         displayFrame.right, displayFrame.bottom);
             }
         }else {
             if(extOrient || ctx->dpyAttr[dpy].mDownScaleMode) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 51742be..4858b3a 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -21,7 +21,9 @@
 #ifndef HWC_UTILS_H
 #define HWC_UTILS_H
 
+#define DEBUG_MDPDOWNSCALE 0
 #define HWC_REMOVE_DEPRECATED_VERSIONS 1
+
 #include <fcntl.h>
 #include <math.h>
 #include <hardware/hwcomposer.h>
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index 0b53a47..575a97c 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -183,6 +183,7 @@
         size_t len = PAGE_SIZE;
         ssize_t read;
         char *readLine = (char *) malloc (len);
+        char property[PROPERTY_VALUE_MAX];
         while((read = getline((char **)&readLine, &len,
                               panelInfoNodeFP)) != -1) {
             int token_ct=0;
@@ -227,6 +228,12 @@
                 }
             }
         }
+        if((property_get("persist.hwc.pubypass", property, 0) > 0) &&
+            (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+            (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+                mPanelInfo.mPartialUpdateEnable = 0;
+                ALOGI("PartialUpdate disabled by property");
+        }
         fclose(panelInfoNodeFP);
     } else {
         ALOGE("Failed to open msm_fb_panel_info node");