hwc: Support for reading FB format from driver

- Instead of assuming the default format(RGBA_8888),
  read FB format from driver and pass the info to SF
- For now, this is limited to primary and HDMI only.
  WB FBformat is assumed to be in RGBA_8888
- If FB doesn't have alpha channel, disable mixed mode

Change-Id: Iefc0080819749b541483ea47357bb37ec150c544
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index df3e464..c344045 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -13,11 +13,14 @@
                                  libdl libmemalloc libqservice libsync \
                                  libbinder libmedia
 
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
 ifeq ($(TARGET_USES_QCOM_BSP),true)
 LOCAL_SHARED_LIBRARIES += libskia
+ifeq ($(GET_FRAMEBUFFER_FORMAT_FROM_HWC),true)
+    LOCAL_CFLAGS += -DGET_FRAMEBUFFER_FORMAT_FROM_HWC
+endif
 endif #TARGET_USES_QCOM_BSP
 
-LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
 #Enable Dynamic FPS if PHASE_OFFSET is not set
 ifeq ($(VSYNC_EVENT_PHASE_OFFSET_NS),)
     LOCAL_CFLAGS += -DDYNAMIC_FPS
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index adf48e7..a934f3e 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -805,6 +805,9 @@
         HWC_DISPLAY_DPI_X,
         HWC_DISPLAY_DPI_Y,
         HWC_DISPLAY_SECURE,
+#ifdef GET_FRAMEBUFFER_FORMAT_FROM_HWC
+        HWC_DISPLAY_FBFORMAT,
+#endif
         HWC_DISPLAY_NO_ATTRIBUTE,
     };
 
@@ -855,6 +858,11 @@
         case HWC_DISPLAY_SECURE:
             values[i] = (int32_t) (ctx->dpyAttr[disp].secure);
             break;
+#ifdef GET_FRAMEBUFFER_FORMAT_FROM_HWC
+        case HWC_DISPLAY_FBFORMAT:
+            values[i] = ctx->dpyAttr[disp].fbformat;
+            break;
+#endif
         default:
             ALOGE("Unknown display attribute %d",
                     attributes[i]);
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index ef83008..3ac04a8 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -56,7 +56,7 @@
         yres = ctx->dpyAttr[mDpy].yres_new;
     }
     getBufferAttributes((int)xres, (int)yres,
-            HAL_PIXEL_FORMAT_RGBA_8888,
+            ctx->dpyAttr[mDpy].fbformat,
             0,
             mAlignedFBWidth,
             mAlignedFBHeight,
@@ -136,7 +136,7 @@
         int flags = mTileEnabled ?
             private_handle_t::PRIV_FLAGS_TILE_RENDERED : 0;
         ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight,
-                ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888, flags));
+                ovutils::getMdpFormat(ctx->dpyAttr[mDpy].fbformat, flags));
 
         Overlay::PipeSpecs pipeSpecs;
         pipeSpecs.formatClass = Overlay::FORMAT_RGB;
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index b45279f..0986fc6 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -1126,8 +1126,8 @@
 
 bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
 {
-    if(!sEnableMixedMode) {
-        //Mixed mode is disabled. No need to even try caching.
+    if(!sEnableMixedMode || !isAlphaPresentinFB(ctx, mDpy)) {
+        //Mixed mode is disabled/can't be used. No need to even try caching.
         return false;
     }
 
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 05ab503..da9004f 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -86,6 +86,32 @@
 // Std refresh rates for digital videos- 24p, 30p, 48p and 60p
 uint32_t stdRefreshRates[] = { 30, 24, 48, 60 };
 
+static uint32_t getFBformat(fb_var_screeninfo vinfo) {
+    uint32_t fbformat = HAL_PIXEL_FORMAT_RGBA_8888;
+
+#ifdef GET_FRAMEBUFFER_FORMAT_FROM_HWC
+    // Here, we are adding the formats that are supported by both GPU and MDP.
+    // The formats that fall in this category are RGBA_8888, RGB_565, RGB_888
+    switch(vinfo.bits_per_pixel) {
+        case 16:
+            fbformat = HAL_PIXEL_FORMAT_RGB_565;
+            break;
+        case 24:
+            if ((vinfo.transp.offset == 0) && (vinfo.transp.length == 0))
+                fbformat = HAL_PIXEL_FORMAT_RGB_888;
+            break;
+        case 32:
+            if ((vinfo.red.offset == 0) && (vinfo.green.offset == 8) &&
+                    (vinfo.blue.offset == 16) && (vinfo.transp.offset == 24))
+                fbformat = HAL_PIXEL_FORMAT_RGBA_8888;
+            break;
+        default:
+            fbformat = HAL_PIXEL_FORMAT_RGBA_8888;
+    }
+#endif
+    return fbformat;
+}
+
 bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
 {
     return !((xres > qdutils::MDPVersion::getInstance().getMaxPipeWidth() &&
@@ -125,6 +151,14 @@
 // Initialize hdmi display attributes based on
 // hdmi display class state
 void updateDisplayInfo(hwc_context_t* ctx, int dpy) {
+    struct fb_var_screeninfo info;
+
+    if (ioctl(ctx->mHDMIDisplay->getFd(), FBIOGET_VSCREENINFO, &info) == -1) {
+        ALOGE("%s:Error in ioctl FBIOGET_VSCREENINFO: %s",
+                __FUNCTION__, strerror(errno));
+    }
+
+    ctx->dpyAttr[dpy].fbformat = getFBformat(info);
     ctx->dpyAttr[dpy].fd = ctx->mHDMIDisplay->getFd();
     ctx->dpyAttr[dpy].xres = ctx->mHDMIDisplay->getWidth();
     ctx->dpyAttr[dpy].yres = ctx->mHDMIDisplay->getHeight();
@@ -233,6 +267,7 @@
     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].secure = true;
     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period =
             (uint32_t)(1000000000l / fps);
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fbformat = getFBformat(info);
 
     //To change resolution of primary display
     changeResolution(ctx, info.xres, info.yres, info.width, info.height);
@@ -965,6 +1000,16 @@
     return false;
 }
 
+bool isAlphaPresentinFB(hwc_context_t *ctx, int dpy) {
+    switch(ctx->dpyAttr[dpy].fbformat) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            return true;
+        default : return false;
+    }
+    return false;
+}
+
 static void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
         hwc_rect_t& crop, hwc_rect_t& dst) {
     int hw_w = ctx->dpyAttr[dpy].xres;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index f11eed5..0008551 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -90,6 +90,7 @@
     float xdpi;
     float ydpi;
     bool secure;
+    uint32_t fbformat;
     int fd;
     bool connected; //Applies only to pluggable disp.
     //Connected does not mean it ready to use.
@@ -300,6 +301,7 @@
 void sanitizeSourceCrop(hwc_rect_t& cropL, hwc_rect_t& cropR,
                         private_handle_t *hnd);
 bool isAlphaPresent(hwc_layer_1_t const* layer);
+bool isAlphaPresentinFB(hwc_context_t* ctx, int dpy);
 int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable);
 int getBlending(int blending);
 bool isGLESOnlyComp(hwc_context_t *ctx, const int& dpy);
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index a294a75..fa40370 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -90,6 +90,7 @@
             // it up to the consumer to decide how fast to consume frames.
             ctx->dpyAttr[dpy].vsync_period
                               = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period;
+            ctx->dpyAttr[dpy].fbformat = HAL_PIXEL_FORMAT_RGBA_8888;
             init(ctx);
             // Do one padding round for cases where primary has all pipes
             // The virtual composition falls back to GPU in such cases.