hwc: Add support for plane alpha

HWC 1.2 API passes down the plane alpha and the blending
operation to apply. Pass this information to the MDP.

Change-Id: I7fbd17345d9157aa654e4b1031ac3e26adf87f37
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index f90420f..4b0ff9a 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -751,7 +751,7 @@
 
         //Setup HWC methods
         dev->device.common.tag          = HARDWARE_DEVICE_TAG;
-        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_1;
+        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_2;
         dev->device.common.module       = const_cast<hw_module_t*>(module);
         dev->device.common.close        = hwc_device_close;
         dev->device.prepare             = hwc_prepare;
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index ba3b5d2..79baa90 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -171,7 +171,10 @@
         orient = ovutils::OVERLAY_TRANSFORM_0;
         transform = 0;
         ovutils::PipeArgs parg(mdpFlags, info, zOrder, isFg,
-                                static_cast<ovutils::eRotFlags>(rotFlags));
+                               static_cast<ovutils::eRotFlags>(rotFlags),
+                               ovutils::DEFAULT_PLANE_ALPHA,
+                               (ovutils::eBlending)
+                               getBlending(layer->blending));
         ret = true;
         if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
                     NULL, mDest) < 0) {
@@ -268,11 +271,16 @@
 
         ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
 
+        //XXX: FB layer plane alpha is currently sent as zero from
+        //surfaceflinger
         ovutils::PipeArgs pargL(mdpFlagsL,
                                 info,
                                 zOrder,
                                 ovutils::IS_FG_OFF,
-                                ovutils::ROT_FLAGS_NONE);
+                                ovutils::ROT_FLAGS_NONE,
+                                ovutils::DEFAULT_PLANE_ALPHA,
+                                (ovutils::eBlending)
+                                getBlending(layer->blending));
         ov.setSource(pargL, destL);
 
         ovutils::eMdpFlags mdpFlagsR = mdpFlagsL;
@@ -281,7 +289,10 @@
                                 info,
                                 zOrder,
                                 ovutils::IS_FG_OFF,
-                                ovutils::ROT_FLAGS_NONE);
+                                ovutils::ROT_FLAGS_NONE,
+                                ovutils::DEFAULT_PLANE_ALPHA,
+                                (ovutils::eBlending)
+                                getBlending(layer->blending));
         ov.setSource(pargR, destR);
 
         hwc_rect_t sourceCrop = layer->sourceCrop;
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 0e2eb2e..01e4c6d 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -545,6 +545,18 @@
         return false;
 }
 
+int getBlending(int blending) {
+    switch(blending) {
+    case HWC_BLENDING_NONE:
+        return overlay::utils::OVERLAY_BLENDING_OPAQUE;
+    case HWC_BLENDING_PREMULT:
+        return overlay::utils::OVERLAY_BLENDING_PREMULT;
+    case HWC_BLENDING_COVERAGE :
+    default:
+        return overlay::utils::OVERLAY_BLENDING_COVERAGE;
+    }
+}
+
 //Crops source buffer against destination and FB boundaries
 void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
                           const hwc_rect_t& scissor, int orient) {
@@ -1035,7 +1047,10 @@
     //For the mdp, since either we are pre-rotating or MDP does flips
     orient = OVERLAY_TRANSFORM_0;
     transform = 0;
-    PipeArgs parg(mdpFlags, whf, z, isFg, static_cast<eRotFlags>(rotFlags));
+    PipeArgs parg(mdpFlags, whf, z, isFg,
+                  static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+                  (ovutils::eBlending) getBlending(layer->blending));
+
     if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
         ALOGE("%s: commit failed for low res panel", __FUNCTION__);
         return -1;
@@ -1164,7 +1179,9 @@
     //configure left mixer
     if(lDest != OV_INVALID) {
         PipeArgs pargL(mdpFlagsL, whf, z, isFg,
-                static_cast<eRotFlags>(rotFlags));
+                       static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+                       (ovutils::eBlending) getBlending(layer->blending));
+
         if(configMdp(ctx->mOverlay, pargL, orient,
                 tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
             ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
@@ -1175,7 +1192,9 @@
     //configure right mixer
     if(rDest != OV_INVALID) {
         PipeArgs pargR(mdpFlagsR, whf, z, isFg,
-                static_cast<eRotFlags>(rotFlags));
+                       static_cast<eRotFlags>(rotFlags),
+                       layer->planeAlpha,
+                       (ovutils::eBlending) getBlending(layer->blending));
         tmp_dstR.right = tmp_dstR.right - lSplit;
         tmp_dstR.left = tmp_dstR.left - lSplit;
         if(configMdp(ctx->mOverlay, pargR, orient,
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 7b39ae5..b51fec4 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -170,6 +170,7 @@
 bool needsScaling(hwc_context_t* ctx, hwc_layer_1_t const* layer, const int& dpy);
 bool isAlphaPresent(hwc_layer_1_t const* layer);
 int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable);
+int getBlending(int blending);
 
 //Helper function to dump logs
 void dumpsys_log(android::String8& buf, const char* fmt, ...);
@@ -275,8 +276,7 @@
 void init_vsync_thread(hwc_context_t* ctx);
 
 inline void getLayerResolution(const hwc_layer_1_t* layer,
-                               int& width, int& height)
-{
+                               int& width, int& height) {
     hwc_rect_t displayFrame  = layer->displayFrame;
     width = displayFrame.right - displayFrame.left;
     height = displayFrame.bottom - displayFrame.top;
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 2d88376..674e62d 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -94,13 +94,14 @@
     setSrcWhf(args.whf);
 
     //TODO These are hardcoded. Can be moved out of setSource.
-    mOVInfo.alpha = 0xff;
     mOVInfo.transp_mask = 0xffffffff;
 
     //TODO These calls should ideally be a part of setPipeParams API
     setFlags(args.mdpFlags);
     setZ(args.zorder);
     setIsFg(args.isFg);
+    setPlaneAlpha(args.planeAlpha);
+    setBlending(args.blending);
 }
 
 void MdpCtrl::setCrop(const utils::Dim& d) {
diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h
index 056d982..5bfec6b 100644
--- a/liboverlay/overlayMdp.h
+++ b/liboverlay/overlayMdp.h
@@ -99,8 +99,13 @@
     void setZ(utils::eZorder z);
     /* set isFg flag */
     void setIsFg(utils::eIsFg isFg);
-        /* return a copy of src whf*/
+    /* return a copy of src whf*/
     utils::Whf getSrcWhf() const;
+    /* set plane alpha */
+    void setPlaneAlpha(int planeAlpha);
+    /* set blending method */
+    void setBlending(overlay::utils::eBlending blending);
+
     /* set src whf */
     void setSrcWhf(const utils::Whf& whf);
     /* set src/dst rect dim */
@@ -241,6 +246,24 @@
     mDownscale = dscale;
 }
 
+inline void MdpCtrl::setPlaneAlpha(int planeAlpha) {
+    mOVInfo.alpha = planeAlpha;
+}
+
+inline void MdpCtrl::setBlending(overlay::utils::eBlending blending) {
+    switch((int) blending) {
+    case utils::OVERLAY_BLENDING_OPAQUE:
+        mOVInfo.blend_op = BLEND_OP_OPAQUE;
+        break;
+    case utils::OVERLAY_BLENDING_PREMULT:
+        mOVInfo.blend_op = BLEND_OP_PREMULTIPLIED;
+        break;
+    case utils::OVERLAY_BLENDING_COVERAGE:
+    default:
+        mOVInfo.blend_op = BLEND_OP_COVERAGE;
+    }
+}
+
 inline bool MdpCtrl::ovChanged() const {
 #ifdef USES_POST_PROCESSING
     // Some pp params are stored as pointer address,
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index b543018..e49a50c 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -212,6 +212,8 @@
 
 enum { MAX_PATH_LEN = 256 };
 
+enum { DEFAULT_PLANE_ALPHA = 0xFF };
+
 /**
  * Rotator flags: not to be confused with orientation flags.
  * Usually, you want to open the rotator to make sure it is
@@ -329,21 +331,36 @@
     OVERLAY_TRANSFORM_INV = 0x80
 };
 
+enum eBlending {
+    OVERLAY_BLENDING_UNDEFINED = 0x0,
+    /* No blending */
+    OVERLAY_BLENDING_OPAQUE,
+    /* src.rgb + dst.rgb*(1-src_alpha) */
+    OVERLAY_BLENDING_PREMULT,
+    /* src.rgb * src_alpha + dst.rgb (1 - src_alpha) */
+    OVERLAY_BLENDING_COVERAGE,
+};
+
 // Used to consolidate pipe params
 struct PipeArgs {
     PipeArgs() : mdpFlags(OV_MDP_FLAGS_NONE),
         zorder(Z_SYSTEM_ALLOC),
         isFg(IS_FG_OFF),
-        rotFlags(ROT_FLAGS_NONE){
+        rotFlags(ROT_FLAGS_NONE),
+        planeAlpha(DEFAULT_PLANE_ALPHA),
+        blending(OVERLAY_BLENDING_COVERAGE){
     }
 
     PipeArgs(eMdpFlags f, Whf _whf,
-            eZorder z, eIsFg fg, eRotFlags r) :
+            eZorder z, eIsFg fg, eRotFlags r,
+            int pA = DEFAULT_PLANE_ALPHA, eBlending b = OVERLAY_BLENDING_COVERAGE) :
         mdpFlags(f),
         whf(_whf),
         zorder(z),
         isFg(fg),
-        rotFlags(r) {
+        rotFlags(r),
+        planeAlpha(pA),
+        blending(b){
     }
 
     eMdpFlags mdpFlags; // for mdp_overlay flags
@@ -351,6 +368,8 @@
     eZorder zorder; // stage number
     eIsFg isFg; // control alpha & transp
     eRotFlags rotFlags;
+    int planeAlpha;
+    eBlending blending;
 };
 
 // Cannot use HW_OVERLAY_MAGNIFICATION_LIMIT, since at the time