display: Add support for HW Cursor

- Retrieve cursor pipe info from driver
- Configure the layer marked with flag HWC_IS_CURSOR_LAYER to the
  HWCursor using the fb_cursor ioctl.
- The config happens only when it satisfies the hw limitions of
  cursor
- HWCursor is supported on primary display
- Since cursor configuration happens first, make use of drop
  layer/count to handle other composition strategies
- Add support for hwc_setCursorPositionAsync as per HWC 1.4

Change-Id: I8663b6da89b0c2dd9b48af96d64a433b2b8a302c
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 85e5d1b..b54cb84 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -29,6 +29,7 @@
 #include <overlay.h>
 #include <overlayRotator.h>
 #include <overlayWriteback.h>
+#include <overlayCursor.h>
 #include <mdp_version.h>
 #include "hwc_utils.h"
 #include "hwc_fbupdate.h"
@@ -443,6 +444,30 @@
     return ret;
 }
 
+static int hwc_setCursorPositionAsync(struct hwc_composer_device_1* dev,
+        int dpy, int x, int y) {
+    int ret = -1;
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    switch(dpy) {
+        case HWC_DISPLAY_PRIMARY:
+        {
+            ATRACE_CALL();
+            HWCursor* hwCursor = HWCursor::getInstance();
+            ctx->mDrawLock.lock();
+            if (hwCursor->isCursorSet() &&
+                  hwCursor->setPositionAsync(ctx->dpyAttr[dpy].fd, x, y)) {
+                ret = 0;
+            }
+            ctx->mDrawLock.unlock();
+            break;
+        }
+        default:
+            ret = 0;
+            break;
+    }
+    return ret;
+}
+
 static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy,
         int mode)
 {
@@ -462,6 +487,7 @@
             ctx->mOverlay->configBegin();
             ctx->mOverlay->configDone();
             ctx->mRotMgr->clear();
+            HWCursor::getInstance()->free(ctx->dpyAttr[dpy].fd);
             // If VDS is connected, do not clear WB object as it
             // will end up detaching IOMMU. This is required
             // to send black frame to WFD sink on power suspend.
@@ -922,17 +948,20 @@
         if(ctx->mMDPComp[dpy])
             ctx->mMDPComp[dpy]->dump(aBuf, ctx);
     }
-    char ovDump[2048] = {'\0'};
-    ctx->mOverlay->getDump(ovDump, 2048);
+    char ovDump[3072] = {'\0'};
+    ctx->mOverlay->getDump(ovDump, 3072);
     dumpsys_log(aBuf, ovDump);
     ovDump[0] = '\0';
     ctx->mRotMgr->getDump(ovDump, 1024);
     dumpsys_log(aBuf, ovDump);
     ovDump[0] = '\0';
-    if(Writeback::getDump(ovDump, 1024)) {
+    if(Writeback::getDump(ovDump, 512)) {
         dumpsys_log(aBuf, ovDump);
         ovDump[0] = '\0';
     }
+    HWCursor::getInstance()->getDump(ovDump, 512);
+    dumpsys_log(aBuf, ovDump);
+    ovDump[0] = '\0';
     dumpsys_log(aBuf, "Copybit::isAbcInUse=%d\n\n",isAbcInUse(ctx) ? 1 : 0);
     strlcpy(buff, aBuf.string(), buff_len);
 }
@@ -1029,6 +1058,7 @@
         dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
         dev->device.getActiveConfig     = hwc_getActiveConfig;
         dev->device.setActiveConfig     = hwc_setActiveConfig;
+        dev->device.setCursorPositionAsync = hwc_setCursorPositionAsync;
         *device = &dev->device.common;
         status = 0;
     }
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 5572cc4..b619395 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -18,7 +18,6 @@
 
 #include <math.h>
 #include "hwc_mdpcomp.h"
-#include <sys/ioctl.h>
 #include <dlfcn.h>
 #include "hdmi.h"
 #include "qdMetaData.h"
@@ -26,6 +25,7 @@
 #include "hwc_fbupdate.h"
 #include "hwc_ad.h"
 #include <overlayRotator.h>
+#include <overlayCursor.h>
 #include "hwc_copybit.h"
 #include "qd_utils.h"
 
@@ -77,8 +77,8 @@
                 (mDpy == 0) ? "\"PRIMARY\"" :
                 (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
     dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
-                "fbCount:%2d \n", mCurrentFrame.layerCount,
-                mCurrentFrame.mdpCount, mCurrentFrame.fbCount);
+                "fbCount:%2d  dropCount:%2d\n", mCurrentFrame.layerCount,
+                mCurrentFrame.mdpCount, mCurrentFrame.fbCount, mCurrentFrame.dropCount);
     dumpsys_log(buf,"needsFBRedraw:%3s  pipesUsed:%2d  MaxPipesPerMixer: %d \n",
                 (mCurrentFrame.needsRedraw? "YES" : "NO"),
                 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
@@ -106,7 +106,8 @@
                     (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
                      mCurrentFrame.layerToMDP[index],
                     (mCurrentFrame.isFBComposed[index] ?
-                    (mCurrentFrame.drop[index] ? "DROP" :
+                    (mCurrentFrame.drop[index] ?
+                    ((mCurrentFrame.hwCursorIndex == index) ? "CURSOR": "DROP"):
                     (mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
                     (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
     mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
@@ -301,7 +302,11 @@
             /* Drop the layer when its already present in FB OR when it lies
              * outside frame's ROI */
             if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
-                layer->compositionType = HWC_OVERLAY;
+                if(index == mCurrentFrame.hwCursorIndex) {
+                    layer->compositionType = HWC_CURSOR_OVERLAY;
+                } else {
+                    layer->compositionType = HWC_OVERLAY;
+                }
             }
         }
     }
@@ -946,6 +951,9 @@
     hwc_display_contents_1_t* list) {
 
     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    // PTOR does not qualify when there are layers dropped, but if
+    // dropped layer is only a cursor, PTOR could qualify
+    const int numNonCursorLayers = numAppLayers - mCurrentFrame.dropCount;
     const int stagesForMDP = min(sMaxPipesPerMixer,
             ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
 
@@ -955,10 +963,11 @@
         return false;
     }
 
-    // Frame level checks
+    // Frame level checks - consider PTOR in case of dropCount only if the cursor
+    // layer is dropped, otherwise bail out of PTOR
     if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
-        isYuvPresent(ctx, mDpy) || mCurrentFrame.dropCount ||
-        isSecurePresent(ctx, mDpy)) {
+        isYuvPresent(ctx, mDpy) || isSecurePresent(ctx, mDpy) ||
+        (mCurrentFrame.dropCount - (int)isCursorPresent(ctx, mDpy))) {
         ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
         return false;
     }
@@ -983,7 +992,7 @@
     memset(overlapRect, 0, sizeof(overlapRect));
     int layerPixelCount, minPixelCount = 0;
     int numPTORLayersFound = 0;
-    for (int i = numAppLayers-1; (i >= 0 &&
+    for (int i = numNonCursorLayers - 1; (i >= 0 &&
                                   numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
         hwc_layer_1_t* layer = &list->hwLayers[i];
         hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
@@ -1028,9 +1037,9 @@
         return false;
 
     // Store the displayFrame and the sourceCrops of the layers
-    hwc_rect_t displayFrame[numAppLayers];
-    hwc_rect_t sourceCrop[numAppLayers];
-    for(int i = 0; i < numAppLayers; i++) {
+    hwc_rect_t displayFrame[numNonCursorLayers];
+    hwc_rect_t sourceCrop[numNonCursorLayers];
+    for(int i = 0; i < numNonCursorLayers; i++) {
         hwc_layer_1_t* layer = &list->hwLayers[i];
         displayFrame[i] = layer->displayFrame;
         sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
@@ -1119,11 +1128,11 @@
         }
     }
 
-    mCurrentFrame.mdpCount = numAppLayers;
+    mCurrentFrame.mdpCount = numNonCursorLayers;
     mCurrentFrame.fbCount = 0;
     mCurrentFrame.fbZ = -1;
 
-    for (int j = 0; j < numAppLayers; j++) {
+    for (int j = 0; j < numNonCursorLayers; j++) {
         if(isValidRect(list->hwLayers[j].displayFrame)) {
             mCurrentFrame.isFBComposed[j] = false;
         } else {
@@ -1135,7 +1144,7 @@
     bool result = postHeuristicsHandling(ctx, list);
 
     // Restore layer attributes
-    for(int i = 0; i < numAppLayers; i++) {
+    for(int i = 0; i < numNonCursorLayers; i++) {
         hwc_layer_1_t* layer = &list->hwLayers[i];
         layer->displayFrame = displayFrame[i];
         layer->sourceCropf.left = (float)sourceCrop[i].left;
@@ -1342,7 +1351,9 @@
         hwc_display_contents_1_t* list){
     if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
             isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
-            !sIsPartialUpdateActive || mDpy ) {
+            isCursorPresent(ctx, mDpy) || !sIsPartialUpdateActive || mDpy) {
+            // On Async position update, the ROI becomes invalid, hence disable PU
+            // when cursor is present
         return false;
     }
     if(ctx->listStats[mDpy].secureUI)
@@ -1910,7 +1921,20 @@
 bool MDPComp::resourceCheck(hwc_context_t* ctx,
         hwc_display_contents_1_t* list) {
     const bool fbUsed = mCurrentFrame.fbCount;
-    if(mCurrentFrame.mdpCount > sMaxPipesPerMixer - fbUsed) {
+    int cursorInUse = 0;
+    if(mDpy == HWC_DISPLAY_PRIMARY) {
+      // check if cursor is in use for primary
+      cursorInUse = HWCursor::getInstance()->isCursorSet();
+    }
+    int maxStages =  qdutils::MDPVersion::getInstance().getBlendStages();
+    // HW Cursor needs one blending stage, account for that in the check below
+    // On high end targets(8994) has 8 blending stages, HAL is configured to use < 8.
+    // Make use of the remaining stages for HW Cursor so that the composition
+    // strategy would not fail due to this limitation.
+    if (maxStages > sMaxPipesPerMixer) {
+        cursorInUse = 0;
+    }
+    if(mCurrentFrame.mdpCount > (sMaxPipesPerMixer - fbUsed - cursorInUse)) {
         ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
         return false;
     }
@@ -1985,6 +2009,52 @@
     return true;
 }
 
+static bool validForCursor(hwc_context_t* ctx, int dpy, hwc_layer_1_t* layer) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    hwc_rect dst = layer->displayFrame;
+    hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
+    int srcW = src.right - src.left;
+    int srcH = src.bottom - src.top;
+    int dstW = dst.right - dst.left;
+    int dstH = dst.bottom - dst.top;
+    qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
+    uint32_t maxCursorSize = mdpVersion.getMaxCursorSize();
+    uint32_t numHwCursors = mdpVersion.getCursorPipes();
+    bool primarySplit = isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY);
+    uint32_t cursorPipesNeeded = 1; // One cursor pipe needed(default)
+    bool ret = false;
+
+    if(dpy > HWC_DISPLAY_PRIMARY) {
+        // Cursor not supported on secondary displays, as it involves scaling
+        // in most of the cases
+        return false;
+    } else if (isSkipLayer(layer)) {
+        return false;
+    // Checks for HW limitation
+    } else if (numHwCursors == 0 || maxCursorSize <= 0) {
+        return false;
+    } else if (needsScaling(layer)) {
+        return false;
+    } else if (layer->transform != 0) {
+        return false;
+    } else if (hnd->format != HAL_PIXEL_FORMAT_RGBA_8888) {
+        return false;
+    } else if (srcW > (int)maxCursorSize || srcH > (int)maxCursorSize) {
+        return false;
+    }
+
+    if (isDisplaySplit(ctx, dpy) && !mdpVersion.isSrcSplit()) {
+        // In case of split display with no srcSplit, the driver allocates two
+        // pipes to support async position update across mixers, hence
+        // need to account for that here.
+        cursorPipesNeeded = 2;
+    }
+    if (cursorPipesNeeded <= numHwCursors) {
+        ret = true;
+    }
+    return ret;
+}
+
 // Checks only if videos or single layer(RGB) is updating
 // which is used for setting dynamic fps or perf hint for single
 // layer video playback
@@ -2029,9 +2099,10 @@
     int ret = 0;
     char property[PROPERTY_VALUE_MAX];
 
-    if(!ctx || !list) {
-        ALOGE("%s: Invalid context or list",__FUNCTION__);
+    if(!list) {
+        ALOGE("%s: Invalid list", __FUNCTION__);
         mCachedFrame.reset();
+        freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
         return -1;
     }
 
@@ -2052,6 +2123,7 @@
     mCurrentFrame.reset(numLayers);
     memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
     mCurrentFrame.dropCount = 0;
+    mCurrentFrame.hwCursorIndex = -1;
 
     //Do not cache the information for next draw cycle.
     if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
@@ -2061,6 +2133,7 @@
 #ifdef DYNAMIC_FPS
         setDynRefreshRate(ctx, list);
 #endif
+        freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
         return -1;
     }
 
@@ -2077,6 +2150,7 @@
 #ifdef DYNAMIC_FPS
         setDynRefreshRate(ctx, list);
 #endif
+        freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
         ret = -1;
         return ret;
     } else {
@@ -2106,6 +2180,23 @@
             dropNonAIVLayers(ctx, list);
         }
 
+        // Configure the cursor if present
+        int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
+        if(ctx->listStats[mDpy].cursorLayerPresent &&
+                validForCursor(ctx, mDpy, &(list->hwLayers[topIndex]))) {
+            if(configHwCursor(ctx->dpyAttr[mDpy].fd, mDpy,
+                                      &(list->hwLayers[topIndex]))) {
+                // As cursor is configured, mark that layer as dropped, so that
+                // it wont be considered for composition by other strategies.
+                mCurrentFrame.hwCursorIndex = topIndex;
+                mCurrentFrame.drop[topIndex] = true;
+                mCurrentFrame.dropCount++;
+            }
+        } else {
+            // Release the hw cursor
+            freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
+        }
+
         // if tryFullFrame fails, try to push all video and secure RGB layers
         // to MDP for composition.
         mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
@@ -2117,6 +2208,12 @@
             reset(ctx);
             memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
             mCurrentFrame.dropCount = 0;
+            // Check if cursor is in use for primary and mark accordingly
+            if(!mDpy && HWCursor::getInstance()->isCursorSet()) {
+                int topIndex = ctx->listStats[mDpy].numAppLayers - 1;
+                hwc_layer_1_t *layer = &(list->hwLayers[topIndex]);
+                layer->compositionType = HWC_CURSOR_OVERLAY;
+            }
             ret = -1;
             ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
                     "MDP Composition Strategies Failed");
@@ -2131,6 +2228,8 @@
         }
         ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
                 __FUNCTION__);
+        // Release the hw cursor
+        freeHwCursor(ctx->dpyAttr[mDpy].fd, mDpy);
         ret = -1;
     }
 
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 676bf24..db68e82 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -119,6 +119,7 @@
 
         bool needsRedraw;
         int fbZ;
+        int hwCursorIndex;
 
         /* c'tor */
         FrameInfo();
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index a3cb196..51c208e 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -30,6 +30,7 @@
 #include <overlay.h>
 #include <overlayRotator.h>
 #include <overlayWriteback.h>
+#include <overlayCursor.h>
 #include "hwc_utils.h"
 #include "hwc_mdpcomp.h"
 #include "hwc_fbupdate.h"
@@ -1085,6 +1086,7 @@
     ctx->listStats[dpy].renderBufIndexforABC = -1;
     ctx->listStats[dpy].secureRGBCount = 0;
     ctx->listStats[dpy].refreshRateRequest = ctx->dpyAttr[dpy].refreshRate;
+    ctx->listStats[dpy].cursorLayerPresent = false;
     uint32_t refreshRate = 0;
     qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
     int s3dFormat = HAL_NO_3D;
@@ -1116,6 +1118,12 @@
         if(ctx->listStats[dpy].numAppLayers > MAX_NUM_APP_LAYERS)
             continue;
 
+        // Valid cursor must be the top most layer
+        if((int)i == (ctx->listStats[dpy].numAppLayers - 1) &&
+                     isCursorLayer(&list->hwLayers[i])) {
+            ctx->listStats[dpy].cursorLayerPresent = true;
+        }
+
         //reset yuv indices
         ctx->listStats[dpy].yuvIndices[i] = -1;
         ctx->listStats[dpy].yuv4k2kIndices[i] = -1;
@@ -1942,6 +1950,46 @@
     crop.bottom = transformedCrop.y + transformedCrop.h;
 }
 
+bool configHwCursor(const int fd, int dpy, hwc_layer_1_t* layer) {
+    if(dpy > HWC_DISPLAY_PRIMARY) {
+        // HWCursor not supported on secondary displays
+        return false;
+    }
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    hwc_rect dst = layer->displayFrame;
+    hwc_rect src = integerizeSourceCrop(layer->sourceCropf);
+    int srcW = src.right - src.left;
+    int srcH = src.bottom - src.top;
+    int dstW = dst.right - dst.left;
+    int dstH = dst.bottom - dst.top;
+
+    Whf whf(getWidth(hnd), getHeight(hnd), hnd->format);
+    Dim crop(src.left, src.top, srcW, srcH);
+    Dim dest(dst.left, dst.top, dstW, dstH);
+
+    ovutils::PipeArgs pargs(ovutils::OV_MDP_FLAGS_NONE,
+                            whf,
+                            Z_SYSTEM_ALLOC,
+                            ovutils::ROT_FLAGS_NONE,
+                            layer->planeAlpha,
+                            (ovutils::eBlending)
+                            getBlending(layer->blending));
+
+    ALOGD_IF(HWC_UTILS_DEBUG, "%s: CursorInfo: w = %d h = %d "
+        "crop [%d, %d, %d, %d] dst [%d, %d, %d, %d]", __FUNCTION__,
+        getWidth(hnd), getHeight(hnd), src.left, src.top, srcW, srcH,
+        dst.left, dst.top, dstW, dstH);
+
+    return HWCursor::getInstance()->config(fd, (void*)hnd->base, pargs,
+                crop, dest);
+}
+
+void freeHwCursor(const int fd, int dpy) {
+    if (dpy == HWC_DISPLAY_PRIMARY) {
+        HWCursor::getInstance()->free(fd);
+    }
+}
+
 int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer) {
     if(not qdutils::MDPVersion::getInstance().isRotDownscaleEnabled()) {
         return 0;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index af43514..7502310 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -165,6 +165,8 @@
     uint32_t refreshRateRequest;
     // Flag related to windowboxing feature
     bool mAIVVideoMode;
+    // curser layer info
+    bool cursorLayerPresent;
 };
 
 //PTOR Comp info
@@ -414,6 +416,9 @@
 void updateSource(ovutils::eTransform& orient, ovutils::Whf& whf,
         hwc_rect_t& crop, overlay::Rotator *rot);
 
+bool configHwCursor(const int fd, int dpy, hwc_layer_1_t* layer);
+void freeHwCursor(const int fd, int dpy);
+
 bool isZoomModeEnabled(hwc_rect_t crop);
 void updateCropAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& crop, int dpy);
 void updateDestAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& dst, int dpy);
@@ -497,6 +502,11 @@
     return (UNLIKELY(l && (l->flags & HWC_AIV_CC)));
 }
 
+static inline bool isCursorLayer(const hwc_layer_1_t* l) {
+    return (UNLIKELY(l && (l->flags & HWC_IS_CURSOR_LAYER)));
+}
+
+
 // Returns true if the buffer is yuv
 static inline bool isYuvBuffer(const private_handle_t* hnd) {
     return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO));
@@ -718,6 +728,10 @@
     return ctx->listStats[dpy].isSecurePresent;
 }
 
+static inline bool isCursorPresent (hwc_context_t *ctx, int dpy) {
+    return  ctx->listStats[dpy].cursorLayerPresent;
+}
+
 static inline bool isSecondaryConfiguring(hwc_context_t* ctx) {
     return (ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isConfiguring ||
             ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isConfiguring);