Merge "hwcomposer: 8x26-1080p: dont allow mdp comp with HFLIP."
diff --git a/common.mk b/common.mk
index b48a38c..3fb003b 100644
--- a/common.mk
+++ b/common.mk
@@ -37,8 +37,12 @@
 
 # Executed only on QCOM BSPs
 ifeq ($(TARGET_USES_QCOM_BSP),true)
+# On jb_mr2- dont enable QCOM Display features
+ifneq ($(call is-platform-sdk-version-at-least,18),true)
 # This flag is used to compile out any features that depend on framework changes
     common_flags += -DQCOM_BSP
+    common_flags += -DANDROID_JELLYBEAN_MR1=1
+endif
 endif
 ifeq ($(call is-vendor-board-platform,QCOM),true)
 # This check is to pick the kernel headers from the right location.
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index 73e145f..6f5cc09 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -498,32 +498,34 @@
             return 9; // 576p 4:3
         case HDMI_VFRMT_720x576p50_16_9:
             return 10; // 576p 16:9
+        case HDMI_VFRMT_1024x768p60_4_3:
+            return 11; // 768p 4:3 Vesa format
         case HDMI_VFRMT_1280x1024p60_5_4:
-            return 11; // 1024p; Vesa format
+            return 12; // 1024p Vesa format
         case HDMI_VFRMT_1280x720p50_16_9:
-            return 12; // 720p@50Hz
+            return 13; // 720p@50Hz
         case HDMI_VFRMT_1280x720p60_16_9:
-            return 13; // 720p@60Hz
+            return 14; // 720p@60Hz
         case HDMI_VFRMT_1920x1080p24_16_9:
-            return 14; //1080p@24Hz
+            return 15; //1080p@24Hz
         case HDMI_VFRMT_1920x1080p25_16_9:
-            return 15; //108-p@25Hz
+            return 16; //108-p@25Hz
         case HDMI_VFRMT_1920x1080p30_16_9:
-            return 16; //1080p@30Hz
+            return 17; //1080p@30Hz
         case HDMI_VFRMT_1920x1080p50_16_9:
-            return 17; //1080p@50Hz
+            return 18; //1080p@50Hz
         case HDMI_VFRMT_1920x1080p60_16_9:
-            return 18; //1080p@60Hz
+            return 19; //1080p@60Hz
         case HDMI_VFRMT_2560x1600p60_16_9:
-            return 19; //WQXGA@60Hz541
+            return 20; //WQXGA@60Hz541
         case HDMI_VFRMT_3840x2160p24_16_9:
-            return 20;//2160@24Hz
+            return 21;//2160@24Hz
         case HDMI_VFRMT_3840x2160p25_16_9:
-            return 21;//2160@25Hz
+            return 22;//2160@25Hz
         case HDMI_VFRMT_3840x2160p30_16_9:
-            return 22; //2160@30Hz
+            return 23; //2160@30Hz
         case HDMI_VFRMT_4096x2160p24_16_9:
-            return 23; //4kx2k@24Hz
+            return 24; //4kx2k@24Hz
     }
 }
 
@@ -580,8 +582,10 @@
         case HDMI_VFRMT_1440x576i50_16_9:
         case HDMI_VFRMT_1920x1080i60_16_9:
             interlaced = true;
+            break;
         default:
             interlaced = false;
+            break;
     }
     return interlaced;
 }
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 79b453d..0ae3eb4 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -75,7 +75,9 @@
 
 static bool useUncached(int usage)
 {
-    if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED)
+    if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED ||
+        usage & GRALLOC_USAGE_SW_WRITE_RARELY  ||
+        usage & GRALLOC_USAGE_SW_READ_RARELY)
         return true;
     return false;
 }
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 0e7576e..1f757bc 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -26,7 +26,6 @@
 #include "memalloc.h"
 #include "alloc_controller.h"
 #include <qdMetaData.h>
-#include "mdp_version.h"
 
 using namespace gralloc;
 
@@ -69,11 +68,13 @@
         data.align = getpagesize();
 
     /* force 1MB alignment selectively for secure buffers, MDP5 onwards */
-    if ((qdutils::MDPVersion::getInstance().getMDPVersion() >= \
-         qdutils::MDSS_V5) && (usage & GRALLOC_USAGE_PROTECTED)) {
+#ifdef MDSS_TARGET
+    if (usage & GRALLOC_USAGE_PROTECTED) {
         data.align = ALIGN(data.align, SZ_1M);
         size = ALIGN(size, data.align);
     }
+#endif
+
     data.size = size;
     data.pHandle = (unsigned int) pHandle;
     err = mAllocCtrl->allocate(data, usage);
@@ -105,16 +106,15 @@
 
         if (bufferType == BUFFER_TYPE_VIDEO) {
             if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
-                if ((qdutils::MDPVersion::getInstance().getMDPVersion() <
-                     qdutils::MDSS_V5)) { //A-Family
-                    flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
-                } else {
+#ifndef MDSS_TARGET
+                flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
+#else
                     if (usage & (GRALLOC_USAGE_HW_TEXTURE |
                                  GRALLOC_USAGE_HW_VIDEO_ENCODER))
                         flags |= private_handle_t::PRIV_FLAGS_ITU_R_709;
                     else if (usage & GRALLOC_USAGE_HW_CAMERA_ZSL)
                         flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
-                }
+#endif
             } else {
                 flags |= private_handle_t::PRIV_FLAGS_ITU_R_601;
             }
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 5a32975..10d372a 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -222,16 +222,17 @@
             pthread_mutex_unlock(lock);
         }
         *vaddr = (void*)hnd->base;
-        //Invalidate if reading in software. No need to do this for the metadata
-        //buffer as it is only read/written in software.
-        IMemAlloc* memalloc = getAllocator(hnd->flags) ;
-        err = memalloc->clean_buffer((void*)hnd->base,
-                                     hnd->size, hnd->offset, hnd->fd,
-                                     CACHE_INVALIDATE);
-        if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) &&
-            !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
-            // Mark the buffer to be flushed after cpu read/write
-            hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
+            //Invalidate if reading in software. No need to do this for the
+            //metadata buffer as it is only read/written in software.
+            IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+            err = memalloc->clean_buffer((void*)hnd->base,
+                                         hnd->size, hnd->offset, hnd->fd,
+                                         CACHE_INVALIDATE);
+            if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
+                // Mark the buffer to be flushed after cpu read/write
+                hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+            }
         }
     } else {
         hnd->flags |= private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
@@ -248,19 +249,21 @@
     private_handle_t* hnd = (private_handle_t*)handle;
     IMemAlloc* memalloc = getAllocator(hnd->flags);
 
-    if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
-        err = memalloc->clean_buffer((void*)hnd->base,
-                                     hnd->size, hnd->offset, hnd->fd,
-                                     CACHE_CLEAN_AND_INVALIDATE);
-        hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
-    } else if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
-        hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
-    } else {
-        //Probably a round about way to do this, but this avoids adding new
-        //flags
-        err = memalloc->clean_buffer((void*)hnd->base,
-                                     hnd->size, hnd->offset, hnd->fd,
-                                     CACHE_INVALIDATE);
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
+            err = memalloc->clean_buffer((void*)hnd->base,
+                                         hnd->size, hnd->offset, hnd->fd,
+                                         CACHE_CLEAN_AND_INVALIDATE);
+            hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+        } else if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
+            hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
+        } else {
+            //Probably a round about way to do this, but this avoids adding new
+            //flags
+            err = memalloc->clean_buffer((void*)hnd->base,
+                                         hnd->size, hnd->offset, hnd->fd,
+                                         CACHE_INVALIDATE);
+        }
     }
 
     return err;
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index e812c01..d7375f8 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -88,7 +88,6 @@
 //Helper
 static void reset(hwc_context_t *ctx, int numDisplays,
                   hwc_display_contents_1_t** displays) {
-    memset(ctx->listStats, 0, sizeof(ctx->listStats));
     for(int i = 0; i < MAX_DISPLAYS; i++) {
         hwc_display_contents_1_t *list = displays[i];
         // XXX:SurfaceFlinger no longer guarantees that this
@@ -497,6 +496,7 @@
     // frames to the display.
     CALC_FPS();
     MDPComp::resetIdleFallBack();
+    ctx->mVideoTransFlag = false;
     return ret;
 }
 
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 8707edf..7ed0577 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -82,8 +82,13 @@
         ovutils::Whf info(hnd->width, hnd->height,
                           ovutils::getMdpFormat(hnd->format), hnd->size);
 
-        //Request an RGB pipe
-        ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy);
+        //Request a pipe
+        ovutils::eMdpPipeType type = ovutils::OV_MDP_PIPE_ANY;
+        if(qdutils::MDPVersion::getInstance().is8x26() && mDpy) {
+            //For 8x26 external always use DMA pipe
+            type = ovutils::OV_MDP_PIPE_DMA;
+        }
+        ovutils::eDest dest = ov.nextPipe(type, mDpy);
         if(dest == ovutils::OV_INVALID) { //None available
             ALOGE("%s: No pipes available to configure fb for dpy %d",
                 __FUNCTION__, mDpy);
@@ -119,15 +124,17 @@
             displayFrame = sourceCrop;
         } else if((!mDpy || (mDpy && !ctx->mExtOrientation))
                                && extOnlyLayerIndex == -1) {
-            getNonWormholeRegion(list, sourceCrop);
-            displayFrame = sourceCrop;
+            if(!qdutils::MDPVersion::getInstance().is8x26()) {
+                getNonWormholeRegion(list, sourceCrop);
+                displayFrame = sourceCrop;
+            }
         }
         ovutils::Dim dpos(displayFrame.left,
                           displayFrame.top,
                           displayFrame.right - displayFrame.left,
                           displayFrame.bottom - displayFrame.top);
 
-        if(mDpy) {
+        if(mDpy && !qdutils::MDPVersion::getInstance().is8x26()) {
             // Get Aspect Ratio for external
             getAspectRatioPosition(ctx, mDpy, ctx->mExtOrientation, dpos.x,
                                     dpos.y, dpos.w, dpos.h);
@@ -231,15 +238,15 @@
         ovutils::Whf info(hnd->width, hnd->height,
                           ovutils::getMdpFormat(hnd->format), hnd->size);
 
-        //Request left RGB pipe
-        ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
+        //Request left pipe
+        ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy);
         if(destL == ovutils::OV_INVALID) { //None available
             ALOGE("%s: No pipes available to configure fb for dpy %d's left"
                     " mixer", __FUNCTION__, mDpy);
             return false;
         }
-        //Request right RGB pipe
-        ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
+        //Request right pipe
+        ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy);
         if(destR == ovutils::OV_INVALID) { //None available
             ALOGE("%s: No pipes available to configure fb for dpy %d's right"
                     " mixer", __FUNCTION__, mDpy);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index f0465eb..ba6cae7 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -366,6 +366,13 @@
     if(!isEnabled()) {
         ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
         ret = false;
+    } else if(qdutils::MDPVersion::getInstance().is8x26() &&
+            ctx->mVideoTransFlag &&
+            ctx->mExtDisplay->isExternalConnected()) {
+        //1 Padding round to shift pipes across mixers
+        ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
+                __FUNCTION__);
+        ret = false;
     } else if(ctx->mExtDispConfiguring) {
         ALOGD_IF( isDebug(),"%s: External Display connection is pending",
                   __FUNCTION__);
@@ -374,10 +381,6 @@
         ctx->isPaddingRound = false;
         ALOGD_IF(isDebug(), "%s: padding round",__FUNCTION__);
         ret = false;
-    } else if(numAppLayers > MAX_NUM_APP_LAYERS) {
-        ALOGD_IF(isDebug(), "%s: Number of App layers exceeded the limit ",
-                 __FUNCTION__);
-        ret = false;
     }
     return ret;
 }
@@ -744,8 +747,16 @@
 
 int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
 
-    //reset old data
     const int numLayers = ctx->listStats[mDpy].numAppLayers;
+
+    //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
+    //do not cache the information for next draw cycle.
+    if(numLayers > MAX_NUM_APP_LAYERS) {
+        ALOGD_IF(isDebug(), "%s: Number of App layers exceeded the limit ",
+                 __FUNCTION__);
+        return 0;
+    }
+    //reset old data
     mCurrentFrame.reset(numLayers);
 
     //Hard conditions, if not met, cannot do MDP comp
@@ -786,7 +797,7 @@
         //Destination over
         mCurrentFrame.fbZ = -1;
         if(mCurrentFrame.fbCount)
-            mCurrentFrame.fbZ = ctx->listStats[mDpy].yuvCount;
+            mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
 
         mCurrentFrame.map();
         if(!programYUV(ctx, list)) {
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index b314317..1751cba 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -202,9 +202,6 @@
         case EXTERNAL_PAUSE:
             {   // pause case
                 ALOGD("%s Received Pause event",__FUNCTION__);
-                // This is required to ensure that composition
-                // fall back to FB, closing all MDP pipes.
-                ctx->mExtDispConfiguring = true;
                 ctx->dpyAttr[dpy].isActive = true;
                 ctx->dpyAttr[dpy].isPause = true;
                 break;
@@ -212,6 +209,8 @@
         case EXTERNAL_RESUME:
             {  // resume case
                 ALOGD("%s Received resume event",__FUNCTION__);
+                // treat Resume as Online event
+                ctx->mExtDispConfiguring = true;
                 ctx->dpyAttr[dpy].isActive = true;
                 ctx->dpyAttr[dpy].isPause = false;
                 break;
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index e8641ff..d6d9759 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -308,12 +308,19 @@
     switch(orientation) {
         case HAL_TRANSFORM_ROT_90:
         case HAL_TRANSFORM_ROT_270:
-            x = (fbWidth - (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres
-                        * fbHeight/ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres))/2;
             y = 0;
-            w = (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres *
-                    fbHeight/ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres);
             h = fbHeight;
+            if (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres <
+                ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres) {
+                // Portrait primary panel
+                w = (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres *
+                     fbHeight/ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres);
+            } else {
+                //Landscape primary panel
+                w = (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres *
+                     fbHeight/ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres);
+            }
+            x = (fbWidth - w)/2;
             break;
         default:
             //Do nothing
@@ -368,7 +375,8 @@
 
 void setListStats(hwc_context_t *ctx,
         const hwc_display_contents_1_t *list, int dpy) {
-
+    const int prevYuvCount = ctx->listStats[dpy].yuvCount;
+    memset(&ctx->listStats[dpy], 0, sizeof(ListStats));
     ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
     ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1;
     ctx->listStats[dpy].skipCount = 0;
@@ -457,6 +465,12 @@
             Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
         }
     }
+
+    //The marking of video begin/end is useful on some targets where we need
+    //to have a padding round to be able to shift pipes across mixers.
+    if(prevYuvCount != ctx->listStats[dpy].yuvCount) {
+        ctx->mVideoTransFlag = true;
+    }
 }
 
 
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 54a118c..916a59d 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -316,6 +316,8 @@
     bool isPaddingRound;
     // External Orientation
     int mExtOrientation;
+    //Flags the transition of a video session
+    bool mVideoTransFlag;
 };
 
 namespace qhwc {
diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp
index c0a33c1..2f4475e 100644
--- a/libhwcomposer/hwc_vsync.cpp
+++ b/libhwcomposer/hwc_vsync.cpp
@@ -25,6 +25,7 @@
 #include <linux/msm_mdp.h>
 #include <sys/resource.h>
 #include <sys/prctl.h>
+#include <poll.h>
 #include "hwc_utils.h"
 #include "string.h"
 #include "external.h"
@@ -61,10 +62,11 @@
 
     const int MAX_DATA = 64;
     static char vdata[MAX_DATA];
+    struct pollfd pfd;
 
     uint64_t cur_timestamp=0;
     ssize_t len = -1;
-    int fd_timestamp = -1;
+    int fb0_fd = -1;
     int ret = 0;
     bool fb1_vsync = false;
     bool logvsync = false;
@@ -83,8 +85,11 @@
     /* Currently read vsync timestamp from drivers
        e.g. VSYNC=41800875994
        */
-    fd_timestamp = open(vsync_timestamp_fb0, O_RDONLY);
-    if (fd_timestamp < 0) {
+    fb0_fd = open(vsync_timestamp_fb0, O_RDONLY);
+    pfd.fd = fb0_fd;
+    pfd.events = POLLPRI | POLLERR;
+
+    if (fb0_fd < 0) {
         // Make sure fb device is opened before starting this thread so this
         // never happens.
         ALOGE ("FATAL:%s:not able to open file:%s, %s",  __FUNCTION__,
@@ -95,24 +100,30 @@
 
     do {
         if (LIKELY(!ctx->vstate.fakevsync)) {
-            len = pread(fd_timestamp, vdata, MAX_DATA, 0);
-            if (len < 0) {
-                // If the read was just interrupted - it is not a fatal error
-                // In either case, just continue.
-                if (errno != EAGAIN &&
-                    errno != EINTR  &&
-                    errno != EBUSY) {
-                    ALOGE ("FATAL:%s:not able to read file:%s, %s",
-                           __FUNCTION__,
-                           vsync_timestamp_fb0, strerror(errno));
+            int err = poll(&pfd, 1, -1);
+            if(err > 0) {
+                if (pfd.revents & POLLPRI) {
+                    len = pread(fb0_fd, vdata, MAX_DATA, 0);
+                    if (UNLIKELY(len < 0)) {
+                        // If the read was just interrupted - it is not a fatal
+                        // error. Just continue in this case
+                        ALOGE ("FATAL:%s:not able to read file:%s, %s",
+                               __FUNCTION__,
+                               vsync_timestamp_fb0, strerror(errno));
+                        continue;
+                    }
+                    // extract timestamp
+                    const char *str = vdata;
+                    if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) {
+                        cur_timestamp = strtoull(str + strlen("VSYNC="),
+                                                 NULL, 0);
+                    }
                 }
+            } else {
+                ALOGE("%s: vsync poll failed errno: %s", __FUNCTION__,
+                      strerror(errno));
                 continue;
             }
-            // extract timestamp
-            const char *str = vdata;
-            if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) {
-                cur_timestamp = strtoull(str + strlen("VSYNC="), NULL, 0);
-            }
         } else {
             usleep(16666);
             cur_timestamp = systemTime();
@@ -125,8 +136,8 @@
         }
 
     } while (true);
-    if(fd_timestamp >= 0)
-        close (fd_timestamp);
+    if(fb0_fd >= 0)
+        close (fb0_fd);
 
     return NULL;
 }
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 71e7e5b..2d88376 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -29,10 +29,12 @@
         return ((int)(f1*100) == (int)(f2*100)) ? true : false;
 }
 
-//Since this is unavailable on Android, defining it in terms of base 10
+#ifdef ANDROID_JELLYBEAN_MR1
+//Since this is unavailable on Android 4.2.2, defining it in terms of base 10
 static inline float log2f(const float& x) {
     return log(x) / log(2);
 }
+#endif
 
 namespace ovutils = overlay::utils;
 namespace overlay {
@@ -165,7 +167,6 @@
     int mdpVersion = MDPVersion::getInstance().getMDPVersion();
     //deferred calcs, so APIs could be called in any order.
     doTransform();
-    doDownscale();
     utils::Whf whf = getSrcWhf();
     if(utils::isYuv(whf.format)) {
         utils::normalizeCrop(mOVInfo.src_rect.x, mOVInfo.src_rect.w);
@@ -179,8 +180,18 @@
                 (mOVInfo.src_rect.h % 4))
                 mOVInfo.src_rect.h = utils::aligndown(mOVInfo.src_rect.h, 4);
         }
+    } else {
+        if (mdpVersion >= MDSS_V5) {
+            // Check for 1-pixel down-scaling
+            if (mOVInfo.src_rect.w - mOVInfo.dst_rect.w == 1)
+                mOVInfo.src_rect.w -= 1;
+            if (mOVInfo.src_rect.h - mOVInfo.dst_rect.h == 1)
+                mOVInfo.src_rect.h -= 1;
+        }
     }
 
+    doDownscale();
+
     if(this->ovChanged() || mForceSet) {
         mForceSet = false;
         if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) {