sdm: Add support for rotator with DRM

Add support for using rotator with DRM driver

Change-Id: I7fda6cb5bda571c3cc80dcae53238800cc875c0b
CRs-fixed: 1114808
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 805948b..f3e9dd4 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -27,6 +27,9 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifdef COMPILE_DRM
+#include <drm/drm_fourcc.h>
+#endif
 #include <cutils/log.h>
 #include <fcntl.h>
 #include <dlfcn.h>
@@ -73,6 +76,12 @@
 #define ION_SC_PREVIEW_FLAGS ION_SECURE
 #endif
 
+#ifdef COMPILE_DRM
+#ifndef DRM_FORMAT_MOD_QCOM_COMPRESSED
+#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
+#endif
+#endif
+
 using namespace gralloc;
 using namespace qdutils;
 using namespace android;
@@ -1091,3 +1100,195 @@
     *rgb_data = (void*)(hnd->base + meta_size);
     return err;
 }
+
+#ifdef COMPILE_DRM
+int getPlaneStrideOffset(private_handle_t *hnd, uint32_t *stride,
+        uint32_t *offset, uint32_t *num_planes) {
+    if (!hnd || !stride || !offset || !num_planes) {
+        return -EINVAL;
+    }
+
+    struct android_ycbcr yuvInfo = {};
+    *num_planes = 1;
+    stride[0] = 0;
+
+    switch (hnd->format) {
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGR_565:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+            stride[0] = hnd->width * 2;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_888:
+            stride[0] = hnd->width * 3;
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_BGRX_8888:
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+        case HAL_PIXEL_FORMAT_ARGB_2101010:
+        case HAL_PIXEL_FORMAT_RGBX_1010102:
+        case HAL_PIXEL_FORMAT_XRGB_2101010:
+        case HAL_PIXEL_FORMAT_BGRA_1010102:
+        case HAL_PIXEL_FORMAT_ABGR_2101010:
+        case HAL_PIXEL_FORMAT_BGRX_1010102:
+        case HAL_PIXEL_FORMAT_XBGR_2101010:
+            stride[0] = hnd->width * 4;
+            break;
+    }
+
+    // Format is RGB
+    if (stride[0]) {
+        return 0;
+    }
+
+    (*num_planes)++;
+    int ret = getYUVPlaneInfo(hnd, &yuvInfo);
+    if (ret < 0) {
+        ALOGE("%s failed", __FUNCTION__);
+        return ret;
+    }
+
+    stride[0] = static_cast<uint32_t>(yuvInfo.ystride);
+    offset[0] = static_cast<uint32_t>(
+                    reinterpret_cast<uint64_t>(yuvInfo.y) - hnd->base);
+    stride[1] = static_cast<uint32_t>(yuvInfo.cstride);
+    switch (hnd->format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+        case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+            offset[1] = static_cast<uint32_t>(
+                    reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+            offset[1] = static_cast<uint32_t>(
+                    reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base);
+            break;
+        case HAL_PIXEL_FORMAT_YV12:
+            offset[1] = static_cast<uint32_t>(
+                    reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base);
+            stride[2] = static_cast<uint32_t>(yuvInfo.cstride);
+            offset[2] = static_cast<uint32_t>(
+                    reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
+            (*num_planes)++;
+            break;
+        default:
+            ALOGW("%s: Unsupported format %s", __FUNCTION__,
+                    qdutils::GetHALPixelFormatString(hnd->format));
+            ret = -EINVAL;
+    }
+
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+        std::fill(offset, offset + 4, 0);
+    }
+
+    return 0;
+}
+
+void getDRMFormat(int hal_format, int flags, uint32_t *drm_format,
+        uint64_t *drm_format_modifier) {
+
+    if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+        *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+    }
+
+    switch (hal_format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+            *drm_format = DRM_FORMAT_RGBA8888;
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+            *drm_format = DRM_FORMAT_RGBA5551;
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+            *drm_format = DRM_FORMAT_RGBA4444;
+            break;
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            *drm_format = DRM_FORMAT_BGRA8888;
+            break;
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+            *drm_format = DRM_FORMAT_RGBX8888;
+            break;
+        case HAL_PIXEL_FORMAT_BGRX_8888:
+            *drm_format = DRM_FORMAT_BGRX8888;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_888:
+            *drm_format = DRM_FORMAT_RGB888;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_565:
+            *drm_format = DRM_FORMAT_RGB565;
+            break;
+        case HAL_PIXEL_FORMAT_BGR_565:
+            *drm_format = DRM_FORMAT_BGR565;
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_1010102:
+            *drm_format = DRM_FORMAT_RGBA1010102;
+            break;
+        case HAL_PIXEL_FORMAT_ARGB_2101010:
+            *drm_format = DRM_FORMAT_ARGB2101010;
+            break;
+        case HAL_PIXEL_FORMAT_RGBX_1010102:
+            *drm_format = DRM_FORMAT_RGBX1010102;
+            break;
+        case HAL_PIXEL_FORMAT_XRGB_2101010:
+            *drm_format = DRM_FORMAT_XRGB2101010;
+            break;
+        case HAL_PIXEL_FORMAT_BGRA_1010102:
+            *drm_format = DRM_FORMAT_BGRA1010102;
+            break;
+        case HAL_PIXEL_FORMAT_ABGR_2101010:
+            *drm_format = DRM_FORMAT_ABGR2101010;
+            break;
+        case HAL_PIXEL_FORMAT_BGRX_1010102:
+            *drm_format = DRM_FORMAT_BGRX1010102;
+            break;
+        case HAL_PIXEL_FORMAT_XBGR_2101010:
+            *drm_format = DRM_FORMAT_XBGR2101010;
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+            *drm_format = DRM_FORMAT_NV12;
+            break;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+            *drm_format = DRM_FORMAT_NV12;
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+            *drm_format = DRM_FORMAT_NV12;
+            *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            *drm_format = DRM_FORMAT_NV21;
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+            *drm_format = DRM_FORMAT_NV21;
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+            // TODO *drm_format = DRM_FORMAT_P010;
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+            // TODO *drm_format = DRM_FORMAT_P010;
+            // *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
+            //        DRM_FORMAT_MOD_QCOM_TIGHT;
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+            *drm_format = DRM_FORMAT_NV16;
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+            *drm_format = DRM_FORMAT_NV61;
+            break;
+        case HAL_PIXEL_FORMAT_YV12:
+            *drm_format = DRM_FORMAT_YVU420;
+            break;
+        default:
+            ALOGW("%s: Unsupported format %s", __FUNCTION__,
+                    qdutils::GetHALPixelFormatString(hal_format));
+    }
+}
+#endif
+
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 848c741..641712c 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -22,7 +22,6 @@
 #include <sys/mman.h>
 #include <linux/msm_ion.h>
 #ifdef COMPILE_DRM
-#include <drm/drm_fourcc.h>
 #include <drm_master.h>
 #endif
 #include <qdMetaData.h>
@@ -36,200 +35,11 @@
 #include "alloc_controller.h"
 
 #ifdef COMPILE_DRM
-#ifndef DRM_FORMAT_MOD_QCOM_COMPRESSED
-#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
-#endif
+using namespace drm_utils;
 #endif
 
 using namespace gralloc;
 
-#ifdef COMPILE_DRM
-using namespace drm_utils;
-
-static int getPlaneStrideOffset(private_handle_t *hnd, uint32_t *stride,
-        uint32_t *offset, uint32_t *num_planes) {
-    struct android_ycbcr yuvInfo = {};
-    *num_planes = 1;
-
-    switch (hnd->format) {
-        case HAL_PIXEL_FORMAT_RGB_565:
-        case HAL_PIXEL_FORMAT_BGR_565:
-        case HAL_PIXEL_FORMAT_RGBA_5551:
-        case HAL_PIXEL_FORMAT_RGBA_4444:
-            stride[0] = hnd->width * 2;
-            break;
-        case HAL_PIXEL_FORMAT_RGB_888:
-            stride[0] = hnd->width * 3;
-            break;
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-        case HAL_PIXEL_FORMAT_BGRA_8888:
-        case HAL_PIXEL_FORMAT_RGBX_8888:
-        case HAL_PIXEL_FORMAT_BGRX_8888:
-        case HAL_PIXEL_FORMAT_RGBA_1010102:
-        case HAL_PIXEL_FORMAT_ARGB_2101010:
-        case HAL_PIXEL_FORMAT_RGBX_1010102:
-        case HAL_PIXEL_FORMAT_XRGB_2101010:
-        case HAL_PIXEL_FORMAT_BGRA_1010102:
-        case HAL_PIXEL_FORMAT_ABGR_2101010:
-        case HAL_PIXEL_FORMAT_BGRX_1010102:
-        case HAL_PIXEL_FORMAT_XBGR_2101010:
-            stride[0] = hnd->width * 4;
-            break;
-    }
-
-    // Format is RGB
-    if (stride[0]) {
-        return 0;
-    }
-
-    (*num_planes)++;
-    int ret = getYUVPlaneInfo(hnd, &yuvInfo);
-    if (ret < 0) {
-        ALOGE("%s failed", __FUNCTION__);
-        return ret;
-    }
-
-    stride[0] = static_cast<uint32_t>(yuvInfo.ystride);
-    offset[0] = static_cast<uint32_t>(
-                    reinterpret_cast<uint64_t>(yuvInfo.y) - hnd->base);
-    stride[1] = static_cast<uint32_t>(yuvInfo.cstride);
-    switch (hnd->format) {
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
-        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
-        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
-        case HAL_PIXEL_FORMAT_YCbCr_420_P010:
-        case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
-            offset[1] = static_cast<uint32_t>(
-                    reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
-            break;
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
-        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
-            offset[1] = static_cast<uint32_t>(
-                    reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base);
-            break;
-        case HAL_PIXEL_FORMAT_YV12:
-            offset[1] = static_cast<uint32_t>(
-                    reinterpret_cast<uint64_t>(yuvInfo.cr) - hnd->base);
-            stride[2] = static_cast<uint32_t>(yuvInfo.cstride);
-            offset[2] = static_cast<uint32_t>(
-                    reinterpret_cast<uint64_t>(yuvInfo.cb) - hnd->base);
-            (*num_planes)++;
-            break;
-        default:
-            ALOGW("%s: Unsupported format %s", __FUNCTION__,
-                    qdutils::GetHALPixelFormatString(hnd->format));
-    }
-
-    if (hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
-        std::fill(offset, offset + 4, 0);
-    }
-
-    return 0;
-}
-
-static void getDRMFormat(int hal_format, int flags, uint32_t *drm_format,
-        uint64_t *drm_format_modifier) {
-
-    if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
-        *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
-    }
-
-    switch (hal_format) {
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-            *drm_format = DRM_FORMAT_RGBA8888;
-            break;
-        case HAL_PIXEL_FORMAT_RGBA_5551:
-            *drm_format = DRM_FORMAT_RGBA5551;
-            break;
-        case HAL_PIXEL_FORMAT_RGBA_4444:
-            *drm_format = DRM_FORMAT_RGBA4444;
-            break;
-        case HAL_PIXEL_FORMAT_BGRA_8888:
-            *drm_format = DRM_FORMAT_BGRA8888;
-            break;
-        case HAL_PIXEL_FORMAT_RGBX_8888:
-            *drm_format = DRM_FORMAT_RGBX8888;
-            break;
-        case HAL_PIXEL_FORMAT_BGRX_8888:
-            *drm_format = DRM_FORMAT_BGRX8888;
-            break;
-        case HAL_PIXEL_FORMAT_RGB_888:
-            *drm_format = DRM_FORMAT_RGB888;
-            break;
-        case HAL_PIXEL_FORMAT_RGB_565:
-            *drm_format = DRM_FORMAT_RGB565;
-            break;
-        case HAL_PIXEL_FORMAT_BGR_565:
-            *drm_format = DRM_FORMAT_BGR565;
-            break;
-        case HAL_PIXEL_FORMAT_RGBA_1010102:
-            *drm_format = DRM_FORMAT_RGBA1010102;
-            break;
-        case HAL_PIXEL_FORMAT_ARGB_2101010:
-            *drm_format = DRM_FORMAT_ARGB2101010;
-            break;
-        case HAL_PIXEL_FORMAT_RGBX_1010102:
-            *drm_format = DRM_FORMAT_RGBX1010102;
-            break;
-        case HAL_PIXEL_FORMAT_XRGB_2101010:
-            *drm_format = DRM_FORMAT_XRGB2101010;
-            break;
-        case HAL_PIXEL_FORMAT_BGRA_1010102:
-            *drm_format = DRM_FORMAT_BGRA1010102;
-            break;
-        case HAL_PIXEL_FORMAT_ABGR_2101010:
-            *drm_format = DRM_FORMAT_ABGR2101010;
-            break;
-        case HAL_PIXEL_FORMAT_BGRX_1010102:
-            *drm_format = DRM_FORMAT_BGRX1010102;
-            break;
-        case HAL_PIXEL_FORMAT_XBGR_2101010:
-            *drm_format = DRM_FORMAT_XBGR2101010;
-            break;
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
-            *drm_format = DRM_FORMAT_NV12;
-            break;
-        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
-            *drm_format = DRM_FORMAT_NV12;
-            break;
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
-            *drm_format = DRM_FORMAT_NV12;
-            *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
-            break;
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
-            *drm_format = DRM_FORMAT_NV21;
-            break;
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
-            *drm_format = DRM_FORMAT_NV21;
-            break;
-        case HAL_PIXEL_FORMAT_YCbCr_420_P010:
-            // TODO *drm_format = DRM_FORMAT_P010;
-            break;
-        case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
-            // TODO *drm_format = DRM_FORMAT_P010;
-            // *drm_format_modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED |
-            //        DRM_FORMAT_MOD_QCOM_TIGHT;
-            break;
-        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
-            *drm_format = DRM_FORMAT_NV16;
-            break;
-        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
-            *drm_format = DRM_FORMAT_NV61;
-            break;
-        case HAL_PIXEL_FORMAT_YV12:
-            *drm_format = DRM_FORMAT_YVU420;
-            break;
-        default:
-            ALOGW("%s: Unsupported format %s", __FUNCTION__,
-                    qdutils::GetHALPixelFormatString(hal_format));
-    }
-}
-#endif
-
 gpu_context_t::gpu_context_t(const private_module_t* module,
                              IAllocController* alloc_ctrl ) :
     mAllocCtrl(alloc_ctrl)
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index ae26df9..edeca3f 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -71,6 +71,13 @@
 // Function to check if the format is an RGB format
 bool isUncompressedRgbFormat(int format);
 
+#ifdef COMPILE_DRM
+int getPlaneStrideOffset(private_handle_t *hnd, uint32_t *stride,
+        uint32_t *offset, uint32_t *num_planes);
+
+void getDRMFormat(int hal_format, int flags, uint32_t *drm_format,
+        uint64_t *drm_format_modifier);
+#endif
 /*****************************************************************************/
 
 class Locker {
diff --git a/sdm/include/core/buffer_allocator.h b/sdm/include/core/buffer_allocator.h
index 4dc4125..3d805ae 100644
--- a/sdm/include/core/buffer_allocator.h
+++ b/sdm/include/core/buffer_allocator.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015 - 2017, 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
@@ -68,6 +68,8 @@
   uint32_t aligned_width = 0;    //!< Specifies aligned allocated buffer width in pixels.
   uint32_t aligned_height = 0;   //!< Specifies aligned allocated buffer height in pixels.
   uint32_t size = 0;             //!< Specifies the size of the allocated buffer.
+  uint32_t fb_id = 0;            // Registered id with the DRM driver
+  uint32_t gem_handle = 0;       // GEM driver handle for correspoding import of ION buffer
 };
 
 /*! @brief Holds the information about the input/output configuration of an output buffer.
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index a72aae7..a33738d 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -368,9 +368,11 @@
 
   for (uint32_t i = 0; i < hw_layer_count; i++) {
     Layer &layer = hw_layer_info.hw_layers.at(i);
-    LayerBuffer &input_buffer = layer.input_buffer;
+    LayerBuffer *input_buffer = &layer.input_buffer;
     HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
     HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+    bool needs_rotation = false;
 
     // TODO(user): Add support for solid fill
     if (layer.flags.solid_fill) {
@@ -379,9 +381,16 @@
 
     for (uint32_t count = 0; count < 2; count++) {
       HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+      HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
+
+      if (hw_rotate_info->valid) {
+        input_buffer = &hw_rotator_session->output_buffer;
+        needs_rotation = true;
+      }
+
       if (pipe_info->valid) {
         uint32_t pipe_id = pipe_info->pipe_id;
-        if (input_buffer.fb_id == 0) {
+        if (input_buffer->fb_id == 0) {
           // We set these to 0 to clear any previous cycle's state from another buffer.
           // Unfortunately this layer will be skipped from validation because it's dimensions are
           // tied to fb_id which is not available yet.
@@ -400,24 +409,28 @@
         DRMRect dst = {};
         SetRect(pipe_info->dst_roi, &dst);
         drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst);
+
         uint32_t rot_bit_mask = 0;
-        if (layer.transform.flip_horizontal) {
-          rot_bit_mask |= 1 << DRM_REFLECT_X;
-        }
-        if (layer.transform.flip_vertical) {
-          rot_bit_mask |= 1 << DRM_REFLECT_Y;
+        // In case of rotation, rotator handles flips
+        if (!needs_rotation) {
+          if (layer.transform.flip_horizontal) {
+            rot_bit_mask |= 1 << DRM_REFLECT_X;
+          }
+          if (layer.transform.flip_vertical) {
+            rot_bit_mask |= 1 << DRM_REFLECT_Y;
+          }
         }
 
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION, pipe_id, rot_bit_mask);
         drm_atomic_intf_->Perform(DRMOps::PLANE_SET_H_DECIMATION, pipe_id,
                                   pipe_info->horizontal_decimation);
         drm_atomic_intf_->Perform(DRMOps::PLANE_SET_V_DECIMATION, pipe_id,
                                   pipe_info->vertical_decimation);
-        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION, pipe_id, rot_bit_mask);
-        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_FB_ID, pipe_id, input_buffer.fb_id);
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_FB_ID, pipe_id, input_buffer->fb_id);
         drm_atomic_intf_->Perform(DRMOps::PLANE_SET_CRTC, pipe_id, token_.crtc_id);
-        if (!validate && input_buffer.acquire_fence_fd >= 0) {
+        if (!validate && input_buffer->acquire_fence_fd >= 0) {
           drm_atomic_intf_->Perform(DRMOps::PLANE_SET_INPUT_FENCE, pipe_id,
-                                    input_buffer.acquire_fence_fd);
+                                    input_buffer->acquire_fence_fd);
         }
       }
     }
@@ -518,8 +531,14 @@
   LayerStack *stack = hw_layer_info.stack;
   stack->retire_fence_fd = retire_fence;
 
-  for (Layer &layer : hw_layer_info.hw_layers) {
-    layer.input_buffer.release_fence_fd = Sys::dup_(release_fence);
+  for (uint32_t i = 0; i < hw_layer_info.hw_layers.size(); i++) {
+    Layer &layer = hw_layer_info.hw_layers.at(i);
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+    if (hw_rotator_session->hw_block_count) {
+      hw_rotator_session->output_buffer.release_fence_fd = Sys::dup_(release_fence);
+    } else {
+      layer.input_buffer.release_fence_fd = Sys::dup_(release_fence);
+    }
   }
 
   hw_layer_info.sync_handle = release_fence;
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 4bcd791..d41206f 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -33,6 +33,7 @@
 #include <drm_master.h>
 #include <drm_res_mgr.h>
 #include <fcntl.h>
+#include <media/msm_sde_rotator.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -342,6 +343,93 @@
   drm_mgr_intf_->UnregisterDisplay(token);
 }
 
+void HWInfoDRM::GetSDMFormat(uint32_t v4l2_format, LayerBufferFormat *sdm_format) {
+  switch (v4l2_format) {
+    case SDE_PIX_FMT_ARGB_8888:         *sdm_format = kFormatARGB8888;                 break;
+    case SDE_PIX_FMT_RGBA_8888:         *sdm_format = kFormatRGBA8888;                 break;
+    case SDE_PIX_FMT_BGRA_8888:         *sdm_format = kFormatBGRA8888;                 break;
+    case SDE_PIX_FMT_RGBX_8888:         *sdm_format = kFormatRGBX8888;                 break;
+    case SDE_PIX_FMT_BGRX_8888:         *sdm_format = kFormatBGRX8888;                 break;
+    case SDE_PIX_FMT_RGBA_5551:         *sdm_format = kFormatRGBA5551;                 break;
+    case SDE_PIX_FMT_RGBA_4444:         *sdm_format = kFormatRGBA4444;                 break;
+    case SDE_PIX_FMT_RGB_888:           *sdm_format = kFormatRGB888;                   break;
+    case SDE_PIX_FMT_BGR_888:           *sdm_format = kFormatBGR888;                   break;
+    case SDE_PIX_FMT_RGB_565:           *sdm_format = kFormatRGB565;                   break;
+    case SDE_PIX_FMT_BGR_565:           *sdm_format = kFormatBGR565;                   break;
+    case SDE_PIX_FMT_Y_CB_CR_H2V2:      *sdm_format = kFormatYCbCr420Planar;           break;
+    case SDE_PIX_FMT_Y_CR_CB_H2V2:      *sdm_format = kFormatYCrCb420Planar;           break;
+    case SDE_PIX_FMT_Y_CR_CB_GH2V2:     *sdm_format = kFormatYCrCb420PlanarStride16;   break;
+    case SDE_PIX_FMT_Y_CBCR_H2V2:       *sdm_format = kFormatYCbCr420SemiPlanar;       break;
+    case SDE_PIX_FMT_Y_CRCB_H2V2:       *sdm_format = kFormatYCrCb420SemiPlanar;       break;
+    case SDE_PIX_FMT_Y_CBCR_H1V2:       *sdm_format = kFormatYCbCr422H1V2SemiPlanar;   break;
+    case SDE_PIX_FMT_Y_CRCB_H1V2:       *sdm_format = kFormatYCrCb422H1V2SemiPlanar;   break;
+    case SDE_PIX_FMT_Y_CBCR_H2V1:       *sdm_format = kFormatYCbCr422H2V1SemiPlanar;   break;
+    case SDE_PIX_FMT_Y_CRCB_H2V1:       *sdm_format = kFormatYCrCb422H2V1SemiPlanar;   break;
+    case SDE_PIX_FMT_YCBYCR_H2V1:       *sdm_format = kFormatYCbCr422H2V1Packed;       break;
+    case SDE_PIX_FMT_Y_CBCR_H2V2_VENUS: *sdm_format = kFormatYCbCr420SemiPlanarVenus;  break;
+    case SDE_PIX_FMT_Y_CRCB_H2V2_VENUS: *sdm_format = kFormatYCrCb420SemiPlanarVenus;  break;
+    case SDE_PIX_FMT_RGBA_8888_UBWC:    *sdm_format = kFormatRGBA8888Ubwc;             break;
+    case SDE_PIX_FMT_RGBX_8888_UBWC:    *sdm_format = kFormatRGBX8888Ubwc;             break;
+    case SDE_PIX_FMT_RGB_565_UBWC:      *sdm_format = kFormatBGR565Ubwc;               break;
+    case SDE_PIX_FMT_Y_CBCR_H2V2_UBWC:  *sdm_format = kFormatYCbCr420SPVenusUbwc;      break;
+    case SDE_PIX_FMT_RGBA_1010102:      *sdm_format = kFormatRGBA1010102;              break;
+    case SDE_PIX_FMT_ARGB_2101010:      *sdm_format = kFormatARGB2101010;              break;
+    case SDE_PIX_FMT_RGBX_1010102:      *sdm_format = kFormatRGBX1010102;              break;
+    case SDE_PIX_FMT_XRGB_2101010:      *sdm_format = kFormatXRGB2101010;              break;
+    case SDE_PIX_FMT_BGRA_1010102:      *sdm_format = kFormatBGRA1010102;              break;
+    case SDE_PIX_FMT_ABGR_2101010:      *sdm_format = kFormatABGR2101010;              break;
+    case SDE_PIX_FMT_BGRX_1010102:      *sdm_format = kFormatBGRX1010102;              break;
+    case SDE_PIX_FMT_XBGR_2101010:      *sdm_format = kFormatXBGR2101010;              break;
+    case SDE_PIX_FMT_RGBA_1010102_UBWC: *sdm_format = kFormatRGBA1010102Ubwc;          break;
+    case SDE_PIX_FMT_RGBX_1010102_UBWC: *sdm_format = kFormatRGBX1010102Ubwc;          break;
+    case SDE_PIX_FMT_Y_CBCR_H2V2_P010:  *sdm_format = kFormatYCbCr420P010;             break;
+    case SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC: *sdm_format = kFormatYCbCr420TP10Ubwc;     break;
+    default: *sdm_format = kFormatInvalid;
+  }
+}
+
+void HWInfoDRM::GetRotatorFormatsForType(int fd, uint32_t type,
+                                         vector<LayerBufferFormat> *supported_formats) {
+  int ret = 0;
+  struct v4l2_fmtdesc fmtdesc = {};
+  fmtdesc.type = type;
+  while (!ret) {
+    ret = Sys::ioctl_(fd, static_cast<int>(VIDIOC_ENUM_FMT), &fmtdesc);
+    if (!ret) {
+      LayerBufferFormat sdm_format = kFormatInvalid;
+      GetSDMFormat(fmtdesc.pixelformat, &sdm_format);
+      if (sdm_format != kFormatInvalid) {
+        supported_formats->push_back(sdm_format);
+      }
+    }
+    fmtdesc.index++;
+  }
+}
+
+DisplayError HWInfoDRM::GetRotatorSupportedFormats(uint32_t v4l2_index,
+                                                   HWResourceInfo *hw_resource) {
+  string path = "/dev/video" + to_string(v4l2_index);
+  int fd = Sys::open_(path.c_str(), O_RDONLY);
+  if (fd < 0) {
+    DLOGE("Failed to open %s with error %d", path.c_str(), errno);
+    return kErrorNotSupported;
+  }
+
+  vector<LayerBufferFormat> supported_formats = {};
+  GetRotatorFormatsForType(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, &supported_formats);
+  hw_resource->supported_formats_map.erase(kHWRotatorInput);
+  hw_resource->supported_formats_map.insert(make_pair(kHWRotatorInput, supported_formats));
+
+  supported_formats = {};
+  GetRotatorFormatsForType(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, &supported_formats);
+  hw_resource->supported_formats_map.erase(kHWRotatorOutput);
+  hw_resource->supported_formats_map.insert(make_pair(kHWRotatorOutput, supported_formats));
+
+  Sys::close_(fd);
+
+  return kErrorNone;
+}
+
 DisplayError HWInfoDRM::GetHWRotatorInfo(HWResourceInfo *hw_resource) {
   const uint32_t kMaxV4L2Nodes = 64;
   bool found = false;
@@ -361,6 +449,7 @@
       hw_resource->hw_rot_info.has_downscale = true;
       // We support only 1 rotator
       found = true;
+      GetRotatorSupportedFormats(i, hw_resource);
     }
   }
 
diff --git a/sdm/libs/core/drm/hw_info_drm.h b/sdm/libs/core/drm/hw_info_drm.h
index 9c9a0e0..b955e63 100644
--- a/sdm/libs/core/drm/hw_info_drm.h
+++ b/sdm/libs/core/drm/hw_info_drm.h
@@ -56,6 +56,10 @@
   DisplayError GetDynamicBWLimits(HWResourceInfo *hw_resource);
   void GetSDMFormat(uint32_t drm_format, uint64_t drm_format_modifier,
                     std::vector<LayerBufferFormat> *sdm_formats);
+  void GetSDMFormat(uint32_t v4l2_format, LayerBufferFormat *sdm_format);
+  void GetRotatorFormatsForType(int fd, uint32_t type,
+                                std::vector<LayerBufferFormat> *supported_formats);
+  DisplayError GetRotatorSupportedFormats(uint32_t v4l2_index, HWResourceInfo *hw_resource);
 
   sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
   bool default_mode_ = false;
diff --git a/sdm/libs/hwc/Android.mk b/sdm/libs/hwc/Android.mk
index c39e1f9..9c78cd3 100644
--- a/sdm/libs/hwc/Android.mk
+++ b/sdm/libs/hwc/Android.mk
@@ -15,7 +15,8 @@
 
 LOCAL_SHARED_LIBRARIES        := libsdmcore libqservice libbinder libhardware libhardware_legacy \
                                  libutils libcutils libsync libmemalloc libqdutils libdl \
-                                 libpowermanager libsdmutils libgpu_tonemapper  libc++ liblog
+                                 libpowermanager libsdmutils libgpu_tonemapper  libc++ liblog \
+                                 libdrmutils
 
 LOCAL_SRC_FILES               := hwc_session.cpp \
                                  hwc_display.cpp \
diff --git a/sdm/libs/hwc/hwc_buffer_allocator.cpp b/sdm/libs/hwc/hwc_buffer_allocator.cpp
index 7e32d65..8e5c5bd 100644
--- a/sdm/libs/hwc/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc/hwc_buffer_allocator.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015 - 2017, 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
@@ -34,12 +34,17 @@
 #include <utils/constants.h>
 #include <utils/debug.h>
 #include <core/buffer_allocator.h>
+#include <drm_master.h>
+#include <qd_utils.h>
 
 #include "hwc_debugger.h"
 #include "hwc_buffer_allocator.h"
 
 #define __CLASS__ "HWCBufferAllocator"
 
+using drm_utils::DRMMaster;
+using drm_utils::DRMBuffer;
+
 namespace sdm {
 
 HWCBufferAllocator::HWCBufferAllocator() {
@@ -118,12 +123,54 @@
 
   buffer_info->private_data = meta_buffer_info;
 
+  if (qdutils::getDriverType() == qdutils::DriverType::DRM) {
+    private_handle_t handle(-1, 0, 0, 0, 0, 0, 0);
+    // Setup only the required stuff, skip rest
+    handle.base = reinterpret_cast<uint64_t>(data.base);
+    handle.format = format;
+    handle.width = aligned_width;
+    handle.height = aligned_height;
+    if (alloc_flags & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC) {
+      handle.flags = private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+    }
+    private_handle_t *hnd = &handle;
+    DRMBuffer buf = {};
+    int ret = getPlaneStrideOffset(hnd, buf.stride, buf.offset,
+                                   &buf.num_planes);
+    if (ret < 0) {
+      DLOGE("getPlaneStrideOffset failed");
+      return kErrorParameters;
+    }
+
+    buf.fd = data.fd;
+    buf.width = UINT32(hnd->width);
+    buf.height = UINT32(hnd->height);
+    getDRMFormat(hnd->format, hnd->flags, &buf.drm_format,
+                 &buf.drm_format_modifier);
+
+    DRMMaster *master = nullptr;
+    ret = DRMMaster::GetInstance(&master);
+    if (ret < 0) {
+      DLOGE("Failed to acquire DRMMaster instance");
+      return kErrorParameters;
+    }
+
+    ret = master->CreateFbId(buf, &alloc_buffer_info->gem_handle, &alloc_buffer_info->fb_id);
+    if (ret < 0) {
+      DLOGE("CreateFbId failed. width %d, height %d, " \
+            "format: %s, stride %u, error %d",
+            buf.width, buf.height,
+            qdutils::GetHALPixelFormatString(hnd->format),
+            buf.stride[0], errno);
+      return kErrorParameters;
+    }
+  }
+
   return kErrorNone;
 }
 
 DisplayError HWCBufferAllocator::FreeBuffer(BufferInfo *buffer_info) {
   int ret = 0;
-
   AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
 
   // Deallocate the buffer, only if the buffer fd is valid.
@@ -154,6 +201,25 @@
 
     delete meta_buffer_info;
     meta_buffer_info = NULL;
+
+    if (alloc_buffer_info->fb_id) {
+      DRMMaster *master = nullptr;
+      int ret = DRMMaster::GetInstance(&master);
+      if (ret < 0) {
+        DLOGE("Failed to acquire DRMMaster instance");
+        return kErrorParameters;
+      }
+
+      ret = master->RemoveFbId(alloc_buffer_info->gem_handle, alloc_buffer_info->fb_id);
+      if (ret < 0) {
+        DLOGE("Removing fb_id %d failed with error %d",
+              alloc_buffer_info->fb_id, errno);
+        return kErrorParameters;
+      }
+
+      alloc_buffer_info->fb_id = 0;
+      alloc_buffer_info->gem_handle = 0;
+    }
   }
 
   return kErrorNone;
@@ -215,7 +281,10 @@
   case kFormatYCbCr422H2V1SemiPlanar:   *target = HAL_PIXEL_FORMAT_YCbCr_422_SP;          break;
   case kFormatYCbCr420SemiPlanarVenus:  *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;    break;
   case kFormatYCrCb420SemiPlanarVenus:  *target = HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS;    break;
-  case kFormatYCbCr420SPVenusUbwc:    *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC; break;
+  case kFormatYCbCr420SPVenusUbwc:
+    *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
   case kFormatRGBA5551:                 *target = HAL_PIXEL_FORMAT_RGBA_5551;             break;
   case kFormatRGBA4444:                 *target = HAL_PIXEL_FORMAT_RGBA_4444;             break;
   case kFormatRGBA1010102:              *target = HAL_PIXEL_FORMAT_RGBA_1010102;          break;
@@ -227,7 +296,10 @@
   case kFormatBGRX1010102:              *target = HAL_PIXEL_FORMAT_BGRX_1010102;          break;
   case kFormatXBGR2101010:              *target = HAL_PIXEL_FORMAT_XBGR_2101010;          break;
   case kFormatYCbCr420P010:             *target = HAL_PIXEL_FORMAT_YCbCr_420_P010;        break;
-  case kFormatYCbCr420TP10Ubwc:         *target = HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC;   break;
+  case kFormatYCbCr420TP10Ubwc:
+    *target = HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
   case kFormatRGBA8888Ubwc:
     *target = HAL_PIXEL_FORMAT_RGBA_8888;
     *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;