hwc: vd: Add support for Dynamic Resolution Change (DRC)

1. Add support for Dynamic Resolution Change

We add support for DRC on virtual displays. This is achieved
by reading the width and height attributes that are set as
part of the buffer handle metadata.

For the WFD use cases, the WFD  MultiMedia framework will
update the width and height during DRC by using setMetaData
API with UPDATE_BUFFER_GEOMETRY. We then proceed to configure
WB with the new resolution for subsequent frames.

2. Update WB dump with output buffer format and resolution

Update WB dump with output buffer format and resolution. This is
helpful for debugging purposes.

Change-Id: I537277499041bffc7bfc5c6e3d024b67f80fce44
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index 0a1335a..a615f5f 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -581,14 +581,14 @@
         // Always set dpyAttr res to mVInfo res
         mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = width;
         mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = height;
-        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode = false;
+        mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mMDPScalingMode = false;
         if(mHwcContext->mOverlay->isUIScalingOnExternalSupported()
                 && mHwcContext->mMDPDownscaleEnabled) {
             int priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
             int priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
             // if primary resolution is more than the hdmi resolution
-            // configure dpy attr to primary resolution and set
-            // downscale mode
+            // configure dpy attr to primary resolution and set MDP
+            // scaling mode.
             // Restrict this upto 1080p resolution max, if target does not
             // support source split feature.
             if((priW * priH) > (width * height) &&
@@ -632,16 +632,17 @@
                 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;
+                mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mMDPScalingMode
+                        = true;
             }
         }
         ALOGD_IF(DEBUG_MDPDOWNSCALE, "Selected external resolution [%d X %d] "
-                 "maxMDPDownScale %d MDPDownScaleMode %d srcSplitEnabled %d "
+                 "maxMDPDownScale %d mMDPScalingMode %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,
+                 mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mMDPScalingMode,
                  qdutils::MDPVersion::getInstance().isSrcSplit(),
                  mHwcContext->mMDPDownscaleEnabled);
         //Initialize the display viewFrame info
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index d5139f4..7839139 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -182,11 +182,11 @@
         // Do not use getNonWormholeRegion() function to calculate the
         // sourceCrop during animation on external display and
         // Dont do wormhole calculation when extorientation is set on External
-        // Dont do wormhole calculation when extDownscale is enabled on External
+        // Dont do wormhole calculation when scaling mode is set on External
         if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
             sourceCrop = layer->displayFrame;
         } else if((mDpy && !extOrient
-                  && !ctx->dpyAttr[mDpy].mDownScaleMode)) {
+                  && !ctx->dpyAttr[mDpy].mMDPScalingMode)) {
             if(ctx->mOverlay->isUIScalingOnExternalSupported() &&
                 !ctx->dpyAttr[mDpy].customFBSize) {
                 getNonWormholeRegion(list, sourceCrop);
@@ -307,11 +307,11 @@
         // Do not use getNonWormholeRegion() function to calculate the
         // sourceCrop during animation on external display and
         // Dont do wormhole calculation when extorientation is set on External
-        // Dont do wormhole calculation when extDownscale is enabled on External
+        // Dont do wormhole calculation when scaling mode is set on External
         if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
             sourceCrop = layer->displayFrame;
         } else if((mDpy && !extOrient
-                  && !ctx->dpyAttr[mDpy].mDownScaleMode)) {
+                  && !ctx->dpyAttr[mDpy].mMDPScalingMode)) {
             if(!qdutils::MDPVersion::getInstance().is8x26() &&
                 !ctx->dpyAttr[mDpy].customFBSize) {
                 getNonWormholeRegion(list, sourceCrop);
@@ -473,11 +473,11 @@
     // Do not use getNonWormholeRegion() function to calculate the
     // sourceCrop during animation on external display and
     // Dont do wormhole calculation when extorientation is set on External
-    // Dont do wormhole calculation when extDownscale is enabled on External
+    // Dont do wormhole calculation when scaling mode is set on External
     if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
         sourceCrop = layer->displayFrame;
     } else if((mDpy && !extOrient
-              && !ctx->dpyAttr[mDpy].mDownScaleMode)) {
+              && !ctx->dpyAttr[mDpy].mMDPScalingMode)) {
         if(!qdutils::MDPVersion::getInstance().is8x26() &&
             !ctx->dpyAttr[mDpy].customFBSize) {
             getNonWormholeRegion(list, sourceCrop);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 8546af0..a93a8f6 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -704,9 +704,9 @@
         return false;
     }
 
-    // check for action safe flag and downscale mode which requires scaling.
+    // check for action safe flag and MDP scaling mode which requires scaling.
     if(ctx->dpyAttr[mDpy].mActionSafePresent
-            || ctx->dpyAttr[mDpy].mDownScaleMode) {
+            || ctx->dpyAttr[mDpy].mMDPScalingMode) {
         ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
         return false;
     }
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index b339cb7..cc9dc5b 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -223,9 +223,9 @@
     ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = false;
     ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = false;
     ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected = false;
-    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].mDownScaleMode= false;
-    ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode = false;
-    ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = false;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].mMDPScalingMode= false;
+    ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].mMDPScalingMode = false;
+    ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].mMDPScalingMode = false;
 
     ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
          MDPComp::getObject(ctx, HWC_DISPLAY_PRIMARY);
@@ -398,8 +398,8 @@
 
     int fbWidth = ctx->dpyAttr[dpy].xres;
     int fbHeight = ctx->dpyAttr[dpy].yres;
-    if(ctx->dpyAttr[dpy].mDownScaleMode) {
-        // if downscale Mode is enabled for external, need to query
+    if(ctx->dpyAttr[dpy].mMDPScalingMode) {
+        // if MDP scaling mode is enabled for external, need to query
         // the actual width and height, as that is the physical w & h
          ctx->mExtDisplay->getAttributes(fbWidth, fbHeight);
     }
@@ -530,9 +530,17 @@
                  outPos.x, outPos.y,
                  outPos.w, outPos.h);
     }
-    if(ctx->dpyAttr[dpy].mDownScaleMode) {
-        int extW, extH;
-        ctx->mExtDisplay->getAttributes(extW, extH);
+    if(ctx->dpyAttr[dpy].mMDPScalingMode) {
+        int extW = 0, extH = 0;
+        if(dpy == HWC_DISPLAY_EXTERNAL) {
+            ctx->mExtDisplay->getAttributes(extW, extH);
+        } else if(dpy == HWC_DISPLAY_VIRTUAL) {
+            extW = ctx->mHWCVirtual->getScalingWidth();
+            extH = ctx->mHWCVirtual->getScalingHeight();
+        }
+        ALOGD_IF(HWC_UTILS_DEBUG, "%s: Scaling mode extW=%d extH=%d",
+                __FUNCTION__, extW, extH);
+
         fbWidth  = (float)ctx->dpyAttr[dpy].xres;
         fbHeight = (float)ctx->dpyAttr[dpy].yres;
         //Calculate the position...
@@ -603,14 +611,22 @@
                     displayFrame.bottom = dstHeight;
                 }
             }
-            if(ctx->dpyAttr[dpy].mDownScaleMode) {
-                int extW, extH;
-                // if downscale is enabled, map the co-ordinates to new
+            if(ctx->dpyAttr[dpy].mMDPScalingMode) {
+                int extW = 0, extH = 0;
+                // if MDP scaling mode is enabled, map the co-ordinates to new
                 // domain(downscaled)
                 float fbWidth  = (float)ctx->dpyAttr[dpy].xres;
                 float fbHeight = (float)ctx->dpyAttr[dpy].yres;
                 // query MDP configured attributes
-                ctx->mExtDisplay->getAttributes(extW, extH);
+                if(dpy == HWC_DISPLAY_EXTERNAL) {
+                    ctx->mExtDisplay->getAttributes(extW, extH);
+                } else if(dpy == HWC_DISPLAY_VIRTUAL) {
+                    extW = ctx->mHWCVirtual->getScalingWidth();
+                    extH = ctx->mHWCVirtual->getScalingHeight();
+                }
+                ALOGD_IF(HWC_UTILS_DEBUG, "%s: Scaling mode extW=%d extH=%d",
+                        __FUNCTION__, extW, extH);
+
                 //Calculate the ratio...
                 float wRatio = ((float)extW)/fbWidth;
                 float hRatio = ((float)extH)/fbHeight;
@@ -626,7 +642,7 @@
                          displayFrame.right, displayFrame.bottom);
             }
         }else {
-            if(extOrient || ctx->dpyAttr[dpy].mDownScaleMode) {
+            if(extOrient || ctx->dpyAttr[dpy].mMDPScalingMode) {
                 getAspectRatioPosition(ctx, dpy, extOrient,
                                        displayFrame, displayFrame);
             }
@@ -1791,7 +1807,7 @@
             whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
     }
 
-    /* Calculate the external display position based on MDP downscale,
+    /* Calculate the external display position based on MDP scaling mode,
        ActionSafe, and extorientation features. */
     calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
     int downscale = getRotDownscale(ctx, layer);
@@ -2085,13 +2101,19 @@
     if (ohnd != NULL && ohnd->base) {
         char dumpFilename[PATH_MAX];
         bool bResult = false;
+        int width = getWidth(ohnd);
+        int height = getHeight(ohnd);
+        int format = ohnd->format;
+        //dummy aligned w & h.
+        int alW = 0, alH = 0;
+        int size = getBufferSizeAndDimensions(width, height, format, alW, alH);
         snprintf(dumpFilename, sizeof(dumpFilename), "/data/%s.%s.%dx%d.raw",
             bufferName,
-            overlay::utils::getFormatString(utils::getMdpFormat(ohnd->format)),
-            getWidth(ohnd), getHeight(ohnd));
+            overlay::utils::getFormatString(utils::getMdpFormat(format)),
+            width, height);
         FILE* fp = fopen(dumpFilename, "w+");
         if (NULL != fp) {
-            bResult = (bool) fwrite((void*)ohnd->base, ohnd->size, 1, fp);
+            bResult = (bool) fwrite((void*)ohnd->base, size, 1, fp);
             fclose(fp);
         }
         ALOGD("Buffer[%s] Dump to %s: %s",
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 4858b3a..e670990 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -97,8 +97,8 @@
     // To trigger padding round to clean up mdp
     // pipes
     bool isConfiguring;
-    // External Display is in MDP Downscale mode indicator
-    bool mDownScaleMode;
+    // Indicates whether external/virtual display is in MDP scaling mode
+    bool mMDPScalingMode;
     // Ext dst Rect
     hwc_rect_t mDstRect;
     //Action safe attributes
@@ -445,21 +445,17 @@
 }
 
 static inline int getWidth(const private_handle_t* hnd) {
-    if(isYuvBuffer(hnd)) {
-        MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
-        if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
-            return metadata->bufferDim.sliceWidth;
-        }
+    MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
+    if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+        return metadata->bufferDim.sliceWidth;
     }
     return hnd->width;
 }
 
 static inline int getHeight(const private_handle_t* hnd) {
-    if(isYuvBuffer(hnd)) {
-        MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
-        if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
-            return metadata->bufferDim.sliceHeight;
-        }
+    MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
+    if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+        return metadata->bufferDim.sliceHeight;
     }
     return hnd->height;
 }
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index b1dde9d..146d671 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -40,6 +40,7 @@
 
 void HWCVirtualVDS::init(hwc_context_t *ctx) {
     const int dpy = HWC_DISPLAY_VIRTUAL;
+    mScalingWidth = 0, mScalingHeight = 0;
     ctx->mFBUpdate[dpy] =
             IFBUpdate::getObject(ctx, dpy);
     ctx->mMDPComp[dpy] =  MDPComp::getObject(ctx, dpy);
@@ -106,8 +107,14 @@
             ctx->dpyAttr[dpy].isConfiguring = false;
             ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd();
             private_handle_t *ohnd = (private_handle_t *)list->outbuf;
-            Writeback::getInstance()->configureDpyInfo(ohnd->width,
-                                                          ohnd->height);
+
+            setMDPScalingMode(ctx, ohnd, dpy);
+
+            mScalingWidth = getWidth(ohnd);
+            mScalingHeight = getHeight(ohnd);
+
+            Writeback::getInstance()->configureDpyInfo(mScalingWidth,
+                                                        mScalingHeight);
             setListStats(ctx, list, dpy);
 
             if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
@@ -258,3 +265,20 @@
     }
     return;
 }
+
+/* We set scaling mode on the VD if the output handle width and height
+   differs from the virtual frame buffer width and height. */
+void HWCVirtualVDS::setMDPScalingMode(hwc_context_t* ctx,
+        private_handle_t* ohnd, int dpy) {
+    bool scalingMode = false;
+    int fbWidth = ctx->dpyAttr[dpy].xres;
+    int fbHeight =  ctx->dpyAttr[dpy].yres;
+    if((getWidth(ohnd) != fbWidth) || (getHeight(ohnd) != fbHeight)) {
+        scalingMode = true;
+    }
+    ctx->dpyAttr[dpy].mMDPScalingMode = scalingMode;
+
+    ALOGD_IF(HWCVIRTUAL_LOG, "%s fb(%dx%d) outputBuffer(%dx%d) scalingMode=%d",
+            __FUNCTION__, fbWidth, fbHeight,
+            getWidth(ohnd), getHeight(ohnd), scalingMode);
+}
diff --git a/libhwcomposer/hwc_virtual.h b/libhwcomposer/hwc_virtual.h
index 5ca99f7..525ae2a 100644
--- a/libhwcomposer/hwc_virtual.h
+++ b/libhwcomposer/hwc_virtual.h
@@ -45,12 +45,21 @@
                        hwc_display_contents_1_t** displays);
     void pause(hwc_context_t* ctx, int dpy);
     void resume(hwc_context_t* ctx, int dpy);
+    int getScalingHeight() const { return mScalingHeight; };
+    int getScalingWidth() const { return mScalingWidth; };
     // We can dump the frame buffer and WB
     // output buffer by dynamically enabling
     // dumping via a binder call:
     // adb shell service call display.qservice 15 i32 3 i32 1
     static bool sVDDumpEnabled;
     static void dynamicDebug(bool enable) {sVDDumpEnabled = enable;};
+
+private:
+    // These variables store the resolution that WB is being configured to
+    // in the current draw cycle.
+    int mScalingWidth, mScalingHeight;
+    void setMDPScalingMode(hwc_context_t* ctx,
+            private_handle_t* ohnd, int dpy);
 };
 
 }; //namespace
diff --git a/liboverlay/overlayWriteback.cpp b/liboverlay/overlayWriteback.cpp
index de18e55..ed42a9f 100644
--- a/liboverlay/overlayWriteback.cpp
+++ b/liboverlay/overlayWriteback.cpp
@@ -263,9 +263,12 @@
 bool Writeback::getDump(char *buf, size_t len) {
     if(sWb) {
         utils::getDump(buf, len, "WBData", sWb->mFbData);
-        char str[4] = {'\0'};
-        snprintf(str, 4, "\n");
-        strlcat(buf, str, len);
+        char outputBufferInfo[256];
+        snprintf(outputBufferInfo, sizeof(outputBufferInfo),
+                "OutputBuffer xres=%d yres=%d format=%s\n\n",
+                sWb->getWidth(), sWb->getHeight(),
+                utils::getFormatString(sWb->getOutputFormat()));
+        strlcat(buf, outputBufferInfo, len);
         return true;
     }
     return false;
diff --git a/liboverlay/overlayWriteback.h b/liboverlay/overlayWriteback.h
index ebd319f..21186e6 100644
--- a/liboverlay/overlayWriteback.h
+++ b/liboverlay/overlayWriteback.h
@@ -81,6 +81,8 @@
     bool queueBuffer(int opFd, uint32_t opOffset);
     uint32_t getOffset() const { return mWbMem.getOffset(); }
     int getDstFd() const { return mWbMem.getDstFd(); }
+    int getWidth() const { return mXres; }
+    int getHeight() const { return mYres; }
     /* Subject to GC if writeback isnt used for a drawing round.
      * Get always if caching the value.
      */