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/liboverlay/overlayCursor.cpp b/liboverlay/overlayCursor.cpp
new file mode 100644
index 0000000..c22dd39
--- /dev/null
+++ b/liboverlay/overlayCursor.cpp
@@ -0,0 +1,147 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+//#include "overlay.h"
+#include "overlayCursor.h"
+#include "mdpWrapper.h"
+
+namespace overlay {
+
+HWCursor* HWCursor::sHwCursor = 0;
+
+//=========== class HWCursor =================================================
+HWCursor* HWCursor::getInstance() {
+    if (sHwCursor == NULL) {
+        sHwCursor = new HWCursor();
+    }
+    return sHwCursor;
+}
+
+bool HWCursor::config(const int fd, void* base, PipeArgs& pargs,
+                    Dim& crop, Dim& dest) {
+    bool ret = true;
+    fb_cursor *cursor = &mfbCursor;
+    fb_image cursorImage;
+
+    cursor->set = FB_CUR_SETIMAGE | FB_CUR_SETPOS;
+    cursor->enable = (uint16_t)1;
+    cursor->rop = 0,
+    cursor->mask = NULL;
+    cursor->hot.x = (uint16_t)crop.x;
+    cursor->hot.y = (uint16_t)crop.y;
+
+    cursorImage.dx = dest.x;
+    cursorImage.dy = dest.y;
+    cursorImage.width = pargs.whf.w;
+    cursorImage.height = pargs.whf.h;
+    cursorImage.fg_color = pargs.planeAlpha; // Hint for PMA
+    cursorImage.bg_color = 0xffffff00;  // RGBA
+    cursorImage.depth = 32;
+    cursorImage.data = (char*)base;
+
+    cursor->image = cursorImage;
+
+    if (!setCursor(fd)) {
+        ALOGE("%s: Failed to setup HW cursor", __FUNCTION__);
+        ret = false;
+        memset(cursor, 0, sizeof(fb_cursor));
+    }
+    return ret;
+}
+
+bool HWCursor::setPositionAsync(const int fd, int x, int y) {
+    bool ret = true;
+    if (isCursorSet()) {
+        fb_cursor *cursor = &mfbCursor;
+        cursor->set = FB_CUR_SETPOS;
+        cursor->image.dx = x;
+        cursor->image.dy = y;
+        if (!setCursor(fd)) {
+            ALOGE("%s: Failed to set position x = %d y = %d", __FUNCTION__, x, y);
+            ret = false;
+        }
+    }
+    return ret;
+}
+
+bool HWCursor::free(const int fd) {
+    fb_cursor *cursor = &mfbCursor;
+    fb_image cursorImage;
+    bool ret = true;
+
+    if(!cursor->enable) {
+        return ret;
+    }
+
+    cursor->enable = (uint16_t)0;
+
+    if (!setCursor(fd)) {
+        ALOGE("%s: Failed to free cursor hw", __FUNCTION__);
+        ret = false;
+    }
+    memset(cursor, 0, sizeof(fb_cursor));
+    return ret;
+}
+
+bool HWCursor::setCursor(const int fd) {
+    bool ret = true;
+    ATRACE_CALL();
+    fb_cursor *cursor = &mfbCursor;
+
+    if(fd <= 0) {
+        ALOGE("%s: Invalid fd", fd);
+        return false;
+    }
+
+    if (ioctl(fd, MSMFB_CURSOR, cursor) < 0) {
+        ALOGE("%s: Failed to call ioctl MSMFB_CURSOR err=%s\n", __FUNCTION__,
+              strerror(errno));
+        ret = false;
+    }
+    return ret;
+}
+
+void HWCursor::getDump(char* buf, size_t len) {
+      char cursordump[len];
+      fb_cursor* cursor = &mfbCursor;
+      if (cursor->enable) {
+          snprintf(cursordump, sizeof(cursordump),
+              "HWCursor on Primary: src w=%d h=%d\n"
+              "\tsrc_rect x=%d y=%d w=%d h=%d\n"
+              "\tdst_rect x=%d y=%d w=%d h=%d\n\n", cursor->image.width,
+              cursor->image.height, cursor->hot.x, cursor->hot.y,
+              cursor->image.width, cursor->image.height,
+              cursor->image.dx, cursor->image.dy, cursor->image.width,
+              cursor->image.height);
+          strlcat(buf, cursordump, len);
+      }
+
+}
+
+} //namespace overlay