Merge "gralloc1: Add support to provide interlace info"
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 46ab782..71767e7 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -218,6 +218,7 @@
 enum struct DRMRotation {
   FLIP_H = 0x1,
   FLIP_V = 0x2,
+  ROT_180 = FLIP_H | FLIP_V,
   ROT_90 = 0x4,
 };
 
@@ -358,6 +359,7 @@
   int wmin;
   int hmin;
   bool roi_merge;
+  DRMRotation panel_orientation;
 };
 
 /* Identifier token for a display */
diff --git a/libgralloc/Makefile.am b/libgralloc/Makefile.am
index d57ad32..3cf3960 100644
--- a/libgralloc/Makefile.am
+++ b/libgralloc/Makefile.am
@@ -1,11 +1,12 @@
+HEADER_PATH := ${WORKSPACE}/display/display-hal/include
 h_sources = alloc_controller.h \
             memalloc.h
 
 cpp_sources = ionalloc.cpp \
               alloc_controller.cpp
 
-library_includedir = $(pkgincludedir)
-library_include_HEADERS = $(h_sources)
+memalloc_includedir = $(pkgincludedir)
+memalloc_include_HEADERS = $(h_sources)
 
 lib_LTLIBRARIES = libmemalloc.la
 libmemalloc_la_CC = @CC@
@@ -17,7 +18,9 @@
 libmemalloc_la_LDFLAGS = -shared -avoid-version
 
 header_sources = gralloc_priv.h \
-                 gr.h
+                 gr.h \
+                 adreno_utils.h \
+                 $(HEADER_PATH)/color_metadata.h
 
 c_sources = gpu.cpp \
             gralloc.cpp \
@@ -36,4 +39,4 @@
 libgralloc_la_LIBADD += ../libqdutils/libqdMetaData.la
 libgralloc_la_LIBADD += -lhardware -lcutils -llog -lutils -lbinder
 libgralloc_la_LIBADD += libmemalloc.la
-libgralloc_la_LDFLAGS = -shared -avoid-version
\ No newline at end of file
+libgralloc_la_LDFLAGS = -shared -avoid-version
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 1779312..d2a522e 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -247,6 +247,8 @@
                 aligned_w = ALIGN(width, alignment);
                 break;
             case HAL_PIXEL_FORMAT_RAW16:
+            case HAL_PIXEL_FORMAT_Y16:
+            case HAL_PIXEL_FORMAT_Y8:
                 aligned_w = ALIGN(width, 16);
                 break;
             case HAL_PIXEL_FORMAT_RAW12:
@@ -564,6 +566,7 @@
         case HAL_PIXEL_FORMAT_RGBA_5551:
         case HAL_PIXEL_FORMAT_RGBA_4444:
         case HAL_PIXEL_FORMAT_RAW16:
+        case HAL_PIXEL_FORMAT_Y16:
             size = alignedw * alignedh * 2;
             break;
         case HAL_PIXEL_FORMAT_RAW12:
@@ -573,6 +576,7 @@
             size = ALIGN(alignedw * alignedh, 4096);
             break;
         case HAL_PIXEL_FORMAT_RAW8:
+        case HAL_PIXEL_FORMAT_Y8:
             size = alignedw * alignedh;
             break;
             // adreno formats
@@ -815,9 +819,11 @@
         case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
         case HAL_PIXEL_FORMAT_NV21_ZSL:
         case HAL_PIXEL_FORMAT_RAW16:
+        case HAL_PIXEL_FORMAT_Y16:
         case HAL_PIXEL_FORMAT_RAW12:
         case HAL_PIXEL_FORMAT_RAW10:
         case HAL_PIXEL_FORMAT_RAW8:
+        case HAL_PIXEL_FORMAT_Y8:
             getYuvSPPlaneInfo(hnd->base, width, height, 1, ycbcr);
             std::swap(ycbcr->cb, ycbcr->cr);
         break;
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index 72ff9dc..7e0ba14 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -211,11 +211,10 @@
     return GRALLOC1_ERROR_BAD_HANDLE;
   }
 
-  // TODO(user): delete handle once framework bug around this is confirmed
-  // to be resolved. This is tracked in bug 36355756
   private_handle_t * handle = const_cast<private_handle_t *>(hnd);
   handle->fd = -1;
   handle->fd_metadata = -1;
+  delete handle;
   return GRALLOC1_ERROR_NONE;
 }
 
@@ -278,6 +277,10 @@
 }
 
 gralloc1_error_t BufferManager::RetainBuffer(private_handle_t const *hnd) {
+  if (hnd->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED) {
+    return GRALLOC1_ERROR_NONE;
+  }
+
   ALOGD_IF(DEBUG, "Retain buffer handle:%p id: %" PRIu64, hnd, hnd->id);
   gralloc1_error_t err = GRALLOC1_ERROR_NONE;
   std::lock_guard<std::mutex> lock(buffer_lock_);
@@ -299,6 +302,10 @@
 }
 
 gralloc1_error_t BufferManager::ReleaseBuffer(private_handle_t const *hnd) {
+  if (hnd->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED) {
+    return GRALLOC1_ERROR_NONE;
+  }
+
   ALOGD_IF(DEBUG, "Release buffer handle:%p id: %" PRIu64, hnd, hnd->id);
   std::lock_guard<std::mutex> lock(buffer_lock_);
   auto buf = GetBufferFromHandleLocked(hnd);
@@ -327,16 +334,16 @@
     return GRALLOC1_ERROR_BAD_VALUE;
   }
 
-  if (hnd->base == 0) {
-    // we need to map for real
-    err = MapBuffer(hnd);
-  }
-
   auto buf = GetBufferFromHandleLocked(hnd);
   if (buf == nullptr) {
     return GRALLOC1_ERROR_BAD_HANDLE;
   }
 
+  if (hnd->base == 0) {
+    // we need to map for real
+    err = MapBuffer(hnd);
+  }
+
   // Invalidate if CPU reads in software and there are non-CPU
   // writers. No need to do this for the metadata buffer as it is
   // only read/written in software.
@@ -793,9 +800,11 @@
     case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
     case HAL_PIXEL_FORMAT_NV21_ZSL:
     case HAL_PIXEL_FORMAT_RAW16:
+    case HAL_PIXEL_FORMAT_Y16:
     case HAL_PIXEL_FORMAT_RAW12:
     case HAL_PIXEL_FORMAT_RAW10:
     case HAL_PIXEL_FORMAT_YV12:
+    case HAL_PIXEL_FORMAT_Y8:
       return true;
     default:
       return false;
diff --git a/libgralloc1/gr_device_impl.cpp b/libgralloc1/gr_device_impl.cpp
index b955e19..ee90090 100644
--- a/libgralloc1/gr_device_impl.cpp
+++ b/libgralloc1/gr_device_impl.cpp
@@ -106,11 +106,12 @@
 void GrallocImpl::GetCapabilities(struct gralloc1_device *device, uint32_t *out_count,
                                   int32_t  /*gralloc1_capability_t*/ *out_capabilities) {
   if (device != nullptr) {
-    if (out_capabilities != nullptr && *out_count >= 2) {
+    if (out_capabilities != nullptr && *out_count >= 3) {
       out_capabilities[0] = GRALLOC1_CAPABILITY_TEST_ALLOCATE;
       out_capabilities[1] = GRALLOC1_CAPABILITY_LAYERED_BUFFERS;
+      out_capabilities[2] = GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE;
     }
-    *out_count = 2;
+    *out_count = 3;
   }
   return;
 }
diff --git a/libgralloc1/gr_utils.cpp b/libgralloc1/gr_utils.cpp
index 30afe4c..b3056e1 100644
--- a/libgralloc1/gr_utils.cpp
+++ b/libgralloc1/gr_utils.cpp
@@ -201,6 +201,7 @@
   // Below switch should be for only YUV/custom formats
   switch (format) {
     case HAL_PIXEL_FORMAT_RAW16:
+    case HAL_PIXEL_FORMAT_Y16:
       size = alignedw * alignedh * 2;
       break;
     case HAL_PIXEL_FORMAT_RAW10:
@@ -208,6 +209,7 @@
       size = ALIGN(alignedw * alignedh, SIZE_4K);
       break;
     case HAL_PIXEL_FORMAT_RAW8:
+    case HAL_PIXEL_FORMAT_Y8:
       size = alignedw * alignedh * 1;
       break;
 
@@ -421,8 +423,10 @@
     case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
     case HAL_PIXEL_FORMAT_NV21_ZSL:
     case HAL_PIXEL_FORMAT_RAW16:
+    case HAL_PIXEL_FORMAT_Y16:
     case HAL_PIXEL_FORMAT_RAW10:
     case HAL_PIXEL_FORMAT_RAW8:
+    case HAL_PIXEL_FORMAT_Y8:
       GetYuvSPPlaneInfo(hnd->base, width, height, 1, ycbcr);
       std::swap(ycbcr->cb, ycbcr->cr);
       break;
@@ -701,6 +705,8 @@
       aligned_w = ALIGN(width, alignment);
       break;
     case HAL_PIXEL_FORMAT_RAW16:
+    case HAL_PIXEL_FORMAT_Y16:
+    case HAL_PIXEL_FORMAT_Y8:
       aligned_w = ALIGN(width, 16);
       break;
     case HAL_PIXEL_FORMAT_RAW12:
diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk
index 7afd00f..60efb3a 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -20,12 +20,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_COPY_HEADERS_TO           := $(common_header_export_path)
-LOCAL_COPY_HEADERS              := qdMetaData.h
+LOCAL_COPY_HEADERS              := qdMetaData.h qd_utils.h
 LOCAL_SHARED_LIBRARIES          := liblog libcutils
 LOCAL_C_INCLUDES                := $(common_includes)
 LOCAL_HEADER_LIBRARIES          := display_headers
 LOCAL_ADDITIONAL_DEPENDENCIES   := $(common_deps)
-LOCAL_SRC_FILES                 := qdMetaData.cpp
+LOCAL_SRC_FILES                 := qdMetaData.cpp qd_utils.cpp
 LOCAL_CFLAGS                    := $(common_flags) -Wno-sign-conversion
 LOCAL_CFLAGS                    += -DLOG_TAG=\"DisplayMetaData\"
 
@@ -34,3 +34,18 @@
 LOCAL_VENDOR_MODULE             := true
 include $(BUILD_SHARED_LIBRARY)
 
+
+include $(CLEAR_VARS)
+
+LOCAL_SHARED_LIBRARIES          := liblog libcutils
+LOCAL_C_INCLUDES                := $(common_includes)
+LOCAL_HEADER_LIBRARIES          := display_headers
+LOCAL_ADDITIONAL_DEPENDENCIES   := $(common_deps)
+LOCAL_SRC_FILES                 := qdMetaData.cpp qd_utils.cpp
+LOCAL_CFLAGS                    := $(common_flags) -Wno-sign-conversion
+LOCAL_CFLAGS                    += -DLOG_TAG=\"DisplayMetaData\"
+
+LOCAL_MODULE_TAGS               := optional
+LOCAL_MODULE                    := libqdMetaData.system
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk
index 1d55d96..c5002a9 100644
--- a/sdm/libs/core/Android.mk
+++ b/sdm/libs/core/Android.mk
@@ -7,7 +7,7 @@
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_HEADER_LIBRARIES        := display_headers
-LOCAL_CFLAGS                  := -Wno-unused-parameter -DLOG_TAG=\"SDM\" \
+LOCAL_CFLAGS                  := -fno-operator-names -Wno-unused-parameter -DLOG_TAG=\"SDM\" \
                                  $(common_flags)
 LOCAL_HW_INTF_PATH_1          := fb
 LOCAL_SHARED_LIBRARIES        := libdl libsdmutils
@@ -51,6 +51,7 @@
                                  $(LOCAL_HW_INTF_PATH_2)/hw_device_drm.cpp \
                                  $(LOCAL_HW_INTF_PATH_2)/hw_events_drm.cpp \
                                  $(LOCAL_HW_INTF_PATH_2)/hw_scale_drm.cpp \
+                                 $(LOCAL_HW_INTF_PATH_2)/hw_virtual_drm.cpp \
                                  $(LOCAL_HW_INTF_PATH_2)/hw_color_manager_drm.cpp
 endif
 
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 6bc4434..f6f0787 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -216,14 +216,6 @@
 }
 
 void HWDeviceDRM::Registry::RegisterCurrent(HWLayers *hw_layers) {
-  DRMMaster *master = nullptr;
-  DRMMaster::GetInstance(&master);
-
-  if (!master) {
-    DLOGE("Failed to acquire DRM Master instance");
-    return;
-  }
-
   HWLayersInfo &hw_layer_info = hw_layers->info;
   uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
 
@@ -237,28 +229,41 @@
       input_buffer = &hw_rotator_session->output_buffer;
     }
 
-    int fd = input_buffer->planes[0].fd;
-    if (fd >= 0 && hashmap_[current_index_].find(fd) == hashmap_[current_index_].end()) {
-      AllocatedBufferInfo buf_info {};
-      DRMBuffer layout {};
-      buf_info.fd = layout.fd = fd;
-      buf_info.aligned_width = layout.width = input_buffer->width;
-      buf_info.aligned_height = layout.height = input_buffer->height;
-      buf_info.format = input_buffer->format;
-      GetDRMFormat(buf_info.format, &layout.drm_format, &layout.drm_format_modifier);
-      buffer_allocator_->GetBufferLayout(buf_info, layout.stride, layout.offset,
-                                         &layout.num_planes);
-      uint32_t fb_id = 0;
-      int ret = master->CreateFbId(layout, &fb_id);
-      if (ret < 0) {
-        DLOGE("CreateFbId failed. width %d, height %d, format: %s, stride %u, error %d",
-              layout.width, layout.height, GetFormatString(buf_info.format), layout.stride[0],
-              errno);
-      } else {
-        hashmap_[current_index_][fd] = fb_id;
-      }
+    MapBufferToFbId(input_buffer);
+  }
+}
+
+void HWDeviceDRM::Registry::MapBufferToFbId(LayerBuffer* buffer) {
+  int fd = buffer->planes[0].fd;
+  DRMMaster *master = nullptr;
+  DRMMaster::GetInstance(&master);
+
+  if (!master) {
+    DLOGE("Failed to acquire DRM Master instance");
+    return;
+  }
+
+  if (fd >= 0 && hashmap_[current_index_].find(fd) == hashmap_[current_index_].end()) {
+    AllocatedBufferInfo buf_info{};
+    DRMBuffer layout{};
+    buf_info.fd = layout.fd = fd;
+    buf_info.aligned_width = layout.width = buffer->width;
+    buf_info.aligned_height = layout.height = buffer->height;
+    buf_info.format = buffer->format;
+    GetDRMFormat(buf_info.format, &layout.drm_format, &layout.drm_format_modifier);
+    buffer_allocator_->GetBufferLayout(buf_info, layout.stride, layout.offset,
+        &layout.num_planes);
+    uint32_t fb_id = 0;
+    int ret = master->CreateFbId(layout, &fb_id);
+    if (ret < 0) {
+      DLOGE("CreateFbId failed. width %d, height %d, format: %s, stride %u, error %d",
+          layout.width, layout.height, GetFormatString(buf_info.format), layout.stride[0],
+          errno);
+    } else {
+      hashmap_[current_index_][fd] = fb_id;
     }
   }
+  return;
 }
 
 void HWDeviceDRM::Registry::UnregisterNext() {
@@ -300,6 +305,7 @@
     : hw_info_intf_(hw_info_intf), buffer_sync_handler_(buffer_sync_handler),
       registry_(buffer_allocator) {
   device_type_ = kDevicePrimary;
+  disp_type_ = DRMDisplayType::PERIPHERAL;
   device_name_ = "Peripheral Display";
   hw_info_intf_ = hw_info_intf;
 }
@@ -309,15 +315,13 @@
 
   if (!default_mode_) {
     DRMMaster *drm_master = {};
-    int dev_fd = -1;
     DRMMaster::GetInstance(&drm_master);
-    drm_master->GetHandle(&dev_fd);
-    DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd, &drm_mgr_intf_);
-    if (drm_mgr_intf_->RegisterDisplay(DRMDisplayType::PERIPHERAL, &token_)) {
-      DLOGE("RegisterDisplay failed");
+    drm_master->GetHandle(&dev_fd_);
+    DRMLibLoader::GetInstance()->FuncGetDRMManager()(dev_fd_, &drm_mgr_intf_);
+    if (drm_mgr_intf_->RegisterDisplay(disp_type_, &token_)) {
+      DLOGE("RegisterDisplay failed for display %d", disp_type_);
       return kErrorResources;
     }
-
     drm_mgr_intf_->CreateAtomicReq(token_, &drm_atomic_intf_);
     drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
     InitializeConfigs();
@@ -325,17 +329,18 @@
 
     drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
     // Commit to setup pipeline with mode, which then tells us the topology etc
-    if (drm_atomic_intf_->Commit(true /* synchronous */)) {
-      DLOGE("Setting up CRTC %d, Connector %d for %s failed", token_.crtc_id, token_.conn_id,
-            device_name_);
-      return kErrorResources;
+
+    if (!deferred_initialize_) {
+      if (drm_atomic_intf_->Commit(true /* synchronous */)) {
+        DRM_LOGI("Setting up CRTC %d, Connector %d for %s failed", token_.crtc_id,
+          token_.conn_id, device_name_);
+        return kErrorResources;
+      }
+      // Reload connector info for updated info after 1st commit
+
+      drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
     }
-
-    // Reload connector info for updated info after 1st commit
-    drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
-    DLOGI("Setup CRTC %d, Connector %d for %s", token_.crtc_id, token_.conn_id, device_name_);
   }
-
   PopulateDisplayAttributes();
   PopulateHWPanelInfo();
   UpdateMixerAttributes();
@@ -445,6 +450,15 @@
   hw_panel_info_.is_primary_panel = connector_info_.is_primary;
   hw_panel_info_.is_pluggable = 0;
 
+  // no supprt for 90 rotation only flips or 180 supported
+  hw_panel_info_.panel_orientation.rotation = 0;
+  hw_panel_info_.panel_orientation.flip_horizontal =
+    (connector_info_.panel_orientation == DRMRotation::FLIP_H) ||
+    (connector_info_.panel_orientation == DRMRotation::ROT_180);
+  hw_panel_info_.panel_orientation.flip_vertical =
+    (connector_info_.panel_orientation == DRMRotation::FLIP_V) ||
+    (connector_info_.panel_orientation == DRMRotation::ROT_180);
+
   GetHWDisplayPortAndMode();
   GetHWPanelMaxBrightness();
 
@@ -796,7 +810,7 @@
 
   int ret = drm_atomic_intf_->Commit(false /* synchronous */);
   if (ret) {
-    DLOGE("%s failed with error %d", __FUNCTION__, ret);
+    DLOGE("%s failed with error %d crtc %d", __FUNCTION__, ret, token_.crtc_id);
     return kErrorHardware;
   }
 
@@ -872,7 +886,6 @@
 
 DisplayError HWDeviceDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) {
   struct DRMPPFeatureInfo info = {};
-
   for (uint32_t i = 0; i < kMaxNumPPFeatures; i++) {
     memset(&info, 0, sizeof(struct DRMPPFeatureInfo));
     info.id = HWColorManagerDrm::ToDrmFeatureId(i);
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 16954af..ad7a3e3 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -49,7 +49,7 @@
 
 class HWDeviceDRM : public HWInterface {
  public:
-  explicit HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
+  HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
                        HWInfoInterface *hw_info_intf);
   virtual ~HWDeviceDRM() {}
   virtual DisplayError Init();
@@ -93,6 +93,7 @@
   virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
   virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
   virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
+  virtual void InitializeConfigs();
 
   enum {
     kHWEventVSync,
@@ -115,7 +116,6 @@
   void ResetDisplayParams();
   bool EnableHotPlugDetection(int enable);
   void UpdateMixerAttributes();
-  void InitializeConfigs();
   void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target);
   void SetSrcConfig(const LayerBuffer &input_buffer, uint32_t *config);
   void SetRect(const LayerRect &source, sde_drm::DRMRect *target);
@@ -132,6 +132,8 @@
     void UnregisterNext();
     // Call on display disconnect to release all gem handles and fb_ids
     void Clear();
+    // Maps given fd to FB ID
+    void MapBufferToFbId(LayerBuffer* buffer);
     // Finds an fb_id corresponding to an fd in current map
     uint32_t GetFbId(int fd);
 
@@ -144,24 +146,30 @@
     BufferAllocator *buffer_allocator_ = {};
   };
 
-  HWResourceInfo hw_resource_ = {};
-  HWPanelInfo hw_panel_info_ = {};
+ protected:
+  const char *device_name_ = {};
+  bool deferred_initialize_ = false;
+  sde_drm::DRMDisplayType disp_type_ = {};
   HWInfoInterface *hw_info_intf_ = {};
   BufferSyncHandler *buffer_sync_handler_ = {};
+  int dev_fd_ = -1;
+  Registry registry_;
+  sde_drm::DRMDisplayToken token_ = {};
+  HWResourceInfo hw_resource_ = {};
+  HWPanelInfo hw_panel_info_ = {};
   HWDeviceType device_type_ = {};
-  const char *device_name_ = {};
-  bool synchronous_commit_ = false;
-  HWDisplayAttributes display_attributes_ = {};
-  HWMixerAttributes mixer_attributes_ = {};
   sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
   sde_drm::DRMAtomicReqInterface *drm_atomic_intf_ = {};
-  sde_drm::DRMDisplayToken token_ = {};
-  drmModeModeInfo current_mode_ = {};
-  bool default_mode_ = false;
   sde_drm::DRMConnectorInfo connector_info_ = {};
+  drmModeModeInfo current_mode_ = {};
+  HWDisplayAttributes display_attributes_ = {};
+
+ private:
+  bool synchronous_commit_ = false;
+  HWMixerAttributes mixer_attributes_ = {};
+  bool default_mode_ = false;
   std::string interface_str_ = "DSI";
   HWScaleDRM *hw_scale_ = {};
-  Registry registry_;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_virtual_drm.cpp b/sdm/libs/core/drm/hw_virtual_drm.cpp
new file mode 100644
index 0000000..5fe1d86
--- /dev/null
+++ b/sdm/libs/core/drm/hw_virtual_drm.cpp
@@ -0,0 +1,188 @@
+/*
+Copyright (c) 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
+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 <stdio.h>
+#include <ctype.h>
+#include <drm_logger.h>
+#include <utils/debug.h>
+#include "hw_device_drm.h"
+#include "hw_virtual_drm.h"
+#include "hw_info_drm.h"
+
+#define __CLASS__ "HWVirtualDRM"
+
+using sde_drm::DRMDisplayType;
+using sde_drm::DRMConnectorInfo;
+using sde_drm::DRMRect;
+using sde_drm::DRMOps;
+
+namespace sdm {
+
+HWVirtualDRM::HWVirtualDRM(BufferSyncHandler *buffer_sync_handler,
+                           BufferAllocator *buffer_allocator,
+                           HWInfoInterface *hw_info_intf)
+                           : HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf) {
+  HWDeviceDRM::deferred_initialize_ = true;
+  HWDeviceDRM::device_name_ = "Virtual Display Device";
+  HWDeviceDRM::hw_info_intf_ = hw_info_intf;
+  HWDeviceDRM::disp_type_ = DRMDisplayType::VIRTUAL;
+}
+
+DisplayError HWVirtualDRM::Init() {
+  return kErrorNone;
+}
+
+DisplayError HWVirtualDRM::DeferredInit() {
+  if (HWDeviceDRM::Init() != kErrorNone)
+    return kErrorResources;
+
+  drm_mgr_intf_->SetScalerLUT(drm_lut_info_);
+  DLOGI_IF(kTagDriverConfig, "Setup CRTC %d, Connector %d for %s",
+            token_.crtc_id, token_.conn_id, device_name_);
+
+  return kErrorNone;
+}
+
+void HWVirtualDRM::ConfigureWbConnectorFbId(uint32_t fb_id) {
+  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_FB_ID, token_.conn_id, fb_id);
+  return;
+}
+
+void HWVirtualDRM::ConfigureWbConnectorDestRect() {
+  DRMRect dst = {};
+  dst.left = 0;
+  dst.bottom = height_;
+  dst.top = 0;
+  dst.right = width_;
+  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_RECT, token_.conn_id, dst);
+  return;
+}
+
+void HWVirtualDRM::InitializeConfigs() {
+  current_mode_.hdisplay = current_mode_.hsync_start = current_mode_.hsync_end \
+  = current_mode_.htotal = (uint16_t) width_;
+  current_mode_.vdisplay = current_mode_.vsync_start = current_mode_.vsync_end \
+  = current_mode_.vtotal = (uint16_t) height_;
+  // Not sure SF has a way to configure refresh rate. Hardcoding to 60 fps for now.
+  // TODO(user): Make this configurable.
+  current_mode_.vrefresh = 60;
+  current_mode_.clock = (current_mode_.htotal * current_mode_.vtotal \
+  * current_mode_.vrefresh) / 1000;
+  struct sde_drm_wb_cfg wb_cfg;
+  wb_cfg.connector_id = token_.conn_id;
+  wb_cfg.flags |= SDE_DRM_WB_CFG_FLAGS_CONNECTED;
+  wb_cfg.count_modes = 1;
+  wb_cfg.modes = (uint64_t)&current_mode_;
+  #ifdef DRM_IOCTL_SDE_WB_CONFIG
+  int ret = drmIoctl(dev_fd_, DRM_IOCTL_SDE_WB_CONFIG, &wb_cfg);
+  #endif
+  if (ret) {
+    DLOGE("WB config failed\n");
+  } else {
+    drm_mgr_intf_->GetConnectorInfo(token_.conn_id, &connector_info_);
+    current_mode_ = connector_info_.modes[0];
+    DumpConfigs();
+  }
+}
+
+void HWVirtualDRM::DumpConfigs() {
+  for (uint32_t i = 0; i < (uint32_t)connector_info_.num_modes; i++) {
+  DLOGI(
+    "Name: %s\tvref: %d\thdisp: %d\t hsync_s: %d\thsync_e:%d\thtotal: %d\t"
+    "vdisp: %d\tvsync_s: %d\tvsync_e: %d\tvtotal: %d\n",
+    connector_info_.modes[i].name, connector_info_.modes[i].vrefresh,
+    connector_info_.modes[i].hdisplay,
+    connector_info_.modes[i].hsync_start, connector_info_.modes[i].hsync_end,
+    connector_info_.modes[i].htotal, connector_info_.modes[i].vdisplay,
+    connector_info_.modes[i].vsync_start, connector_info_.modes[i].vsync_end,
+    connector_info_.modes[i].vtotal);
+  }
+}
+
+DisplayError HWVirtualDRM::Commit(HWLayers *hw_layers) {
+  LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+  DisplayError err = kErrorNone;
+
+  registry_.RegisterCurrent(hw_layers);
+  registry_.MapBufferToFbId(output_buffer);
+  uint32_t fb_id = registry_.GetFbId(output_buffer->planes[0].fd);
+
+  ConfigureWbConnectorFbId(fb_id);
+  ConfigureWbConnectorDestRect();
+
+  err = HWDeviceDRM::AtomicCommit(hw_layers);
+  registry_.UnregisterNext();
+  return(err);
+}
+
+DisplayError HWVirtualDRM::Validate(HWLayers *hw_layers) {
+  // TODO(user) : Add validate support
+  return kErrorNone;
+}
+
+
+DisplayError HWVirtualDRM::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
+  if (display_attributes.x_pixels == 0 || display_attributes.y_pixels == 0) {
+    return kErrorParameters;
+  }
+
+  display_attributes_ = display_attributes;
+
+  if (display_attributes_.x_pixels > hw_resource_.max_mixer_width) {
+    display_attributes_.is_device_split = true;
+  }
+
+  width_ = display_attributes_.x_pixels;
+  height_ = display_attributes_.y_pixels;
+  DeferredInit();
+
+  return kErrorNone;
+}
+
+DisplayError HWVirtualDRM::GetPPFeaturesVersion(PPFeatureVersion *vers) {
+  return kErrorNone;
+}
+
+DisplayError HWVirtualDRM::SetScaleLutConfig(HWScaleLutInfo *lut_info) {
+  drm_lut_info_.cir_lut = lut_info->cir_lut;
+  drm_lut_info_.dir_lut = lut_info->dir_lut;
+  drm_lut_info_.sep_lut = lut_info->sep_lut;
+  drm_lut_info_.cir_lut_size = lut_info->cir_lut_size;
+  drm_lut_info_.dir_lut_size = lut_info->dir_lut_size;
+  drm_lut_info_.sep_lut_size = lut_info->sep_lut_size;
+
+  // Due to differed Init in WB case, we cannot set scaler config immediately as we
+  // won't have SDE DRM initialized at this point. Hence have to cache LUT info here
+  // and set it in ::DeferredInit
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/drm/hw_virtual_drm.h b/sdm/libs/core/drm/hw_virtual_drm.h
new file mode 100644
index 0000000..b63519a
--- /dev/null
+++ b/sdm/libs/core/drm/hw_virtual_drm.h
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 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
+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.
+*/
+
+#ifndef __HW_VIRTUAL_DRM_H__
+#define __HW_VIRTUAL_DRM_H__
+
+#include "hw_device_drm.h"
+#include <drm/msm_drm.h>
+#include <drm/sde_drm.h>
+
+namespace sdm {
+
+class HWVirtualDRM : public HWDeviceDRM {
+ public:
+  HWVirtualDRM(BufferSyncHandler *buffer_sync_handler,
+               BufferAllocator *buffer_allocator, HWInfoInterface *hw_info_intf);
+  virtual ~HWVirtualDRM() {}
+  virtual DisplayError SetVSyncState(bool enable) { return kErrorNotSupported; }
+  virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
+
+ protected:
+  virtual DisplayError Init();
+  virtual DisplayError Validate(HWLayers *hw_layers);
+  virtual DisplayError DeferredInit();
+  virtual void InitializeConfigs();
+  virtual DisplayError Commit(HWLayers *hw_layers);
+  virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
+  virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
+  void ConfigureWbConnectorFbId(uint32_t fb_id);
+  void ConfigureWbConnectorDestRect();
+  void DumpConfigs();
+
+ private:
+  uint32_t width_ = 0;
+  uint32_t height_ = 0;
+  sde_drm::DRMScalerLUTInfo drm_lut_info_ = {};
+};
+
+}  // namespace sdm
+
+#endif  // __HW_VIRTUAL_DRM_H__
+
diff --git a/sdm/libs/core/hw_interface.cpp b/sdm/libs/core/hw_interface.cpp
index b5c9fe9..a27c5f8 100644
--- a/sdm/libs/core/hw_interface.cpp
+++ b/sdm/libs/core/hw_interface.cpp
@@ -37,6 +37,7 @@
 #include "fb/hw_virtual.h"
 #ifdef COMPILE_DRM
 #include "drm/hw_device_drm.h"
+#include "drm/hw_virtual_drm.h"
 #endif
 
 #define __CLASS__ "HWInterface"
@@ -69,9 +70,11 @@
       break;
     case kVirtual:
       if (driver_type == DriverType::FB) {
-        hw = new HWVirtual(buffer_sync_handler, hw_info_intf);
+        hw = new HWVirtual(buffer_sync_handler,hw_info_intf);
       } else {
-        return kErrorNotSupported;
+#ifdef COMPILE_DRM
+        hw = new HWVirtualDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
+#endif
       }
       break;
     default:
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index 07ec2ce..2c5c885 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -58,15 +58,6 @@
 
 namespace sdm {
 
-static void ApplyDeInterlaceAdjustment(Layer *layer) {
-  // De-interlacing adjustment
-  if (layer->input_buffer.flags.interlace) {
-    float height = (layer->src_rect.bottom - layer->src_rect.top) / 2.0f;
-    layer->src_rect.top = ROUND_UP_ALIGN_DOWN(layer->src_rect.top / 2.0f, 2);
-    layer->src_rect.bottom = layer->src_rect.top + floorf(height);
-  }
-}
-
 void HWCColorMode::Init() {
   int ret = PopulateColorModes();
   if (ret != 0) {
@@ -575,7 +566,6 @@
         }
     }
     SetRect(hwc_layer.sourceCropf, &layer->src_rect);
-    ApplyDeInterlaceAdjustment(layer);
 
     uint32_t num_visible_rects = UINT32(hwc_layer.visibleRegionScreen.numRects);
     uint32_t num_dirty_rects = UINT32(hwc_layer.surfaceDamage.numRects);
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 8a5bd81..98e14ee 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -289,7 +289,7 @@
     }
 
     if (hwc_session->need_invalidate_) {
-      hwc_procs->invalidate(hwc_procs);
+      hwc_session->AsyncRefresh();
       hwc_session->need_invalidate_ = false;
     }
 
@@ -420,6 +420,8 @@
     hwc_session->bw_mode_release_fd_ = dup(content_list->retireFenceFd);
   }
 
+  locker_.Signal();
+
   // This is only indicative of how many times SurfaceFlinger posts
   // frames to the display.
   CALC_FPS();
@@ -693,6 +695,14 @@
   return 0;
 }
 
+static void PostRefresh(hwc_procs_t const *hwc_procs) {
+  hwc_procs->invalidate(hwc_procs);
+}
+
+void HWCSession::AsyncRefresh() {
+  future_ = std::async(PostRefresh, hwc_procs_);
+}
+
 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
                                              android::Parcel *output_parcel) {
   SEQUENCE_WAIT_SCOPE_LOCK(locker_);
@@ -705,7 +715,7 @@
     break;
 
   case qService::IQService::SCREEN_REFRESH:
-    hwc_procs_->invalidate(hwc_procs_);
+    AsyncRefresh();
     break;
 
   case qService::IQService::SET_IDLE_TIMEOUT:
@@ -856,7 +866,7 @@
 }
 
 android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
-                                                   android::Parcel *out) {
+                                                   android::Parcel *output_parcel) {
   DisplayError error = kErrorNone;
   int ret = 0;
   uint32_t disp_id = UINT32(input_parcel->readInt32());
@@ -865,14 +875,14 @@
   if (disp_id != HWC_DISPLAY_PRIMARY) {
     DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
     ret = -EINVAL;
-    out->writeInt32(ret);
+    output_parcel->writeInt32(ret);
     return ret;
   }
 
   if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
     DLOGE("primary display object is not instantiated");
     ret = -EINVAL;
-    out->writeInt32(ret);
+    output_parcel->writeInt32(ret);
     return ret;
   }
 
@@ -881,31 +891,30 @@
 
   if (error == kErrorNone) {
     if (!pending) {
-      out->writeInt32(ret);
+      output_parcel->writeInt32(ret);
       return ret;
     }
   } else if (error == kErrorNotSupported) {
-    out->writeInt32(ret);
+    output_parcel->writeInt32(ret);
     return ret;
   } else {
     ret = -EINVAL;
-    out->writeInt32(ret);
+    output_parcel->writeInt32(ret);
     return ret;
   }
 
-  // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
-  hwc_procs_->invalidate(hwc_procs_);
+  AsyncRefresh();
 
   // Wait until partial update control is complete
   ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
 
-  out->writeInt32(ret);
+  output_parcel->writeInt32(ret);
 
   return ret;
 }
 
 android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
-                                                     android::Parcel *output_parcel) {
+                                                           android::Parcel *output_parcel) {
   int config = input_parcel->readInt32();
   int dpy = input_parcel->readInt32();
   int error = android::BAD_VALUE;
@@ -917,7 +926,7 @@
   if (hwc_display_[dpy]) {
     error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
     if (error == 0) {
-      hwc_procs_->invalidate(hwc_procs_);
+      AsyncRefresh();
     }
   }
 
@@ -1128,7 +1137,7 @@
   HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault;
 
   // trigger invalidate to apply new bw caps.
-  hwc_procs_->invalidate(hwc_procs_);
+  AsyncRefresh();
 
     error = core_intf_->SetMaxBandwidthMode(mode);
   if (error != kErrorNone) {
@@ -1325,7 +1334,7 @@
 
   switch (pending_action.action) {
     case kInvalidating:
-      hwc_procs_->invalidate(hwc_procs_);
+      AsyncRefresh();
       break;
     case kEnterQDCMMode:
       ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
@@ -1336,12 +1345,12 @@
     case kApplySolidFill:
       ret = color_mgr_->SetSolidFill(pending_action.params,
                                      true, hwc_display_[HWC_DISPLAY_PRIMARY]);
-      hwc_procs_->invalidate(hwc_procs_);
+      AsyncRefresh();
       break;
     case kDisableSolidFill:
       ret = color_mgr_->SetSolidFill(pending_action.params,
                                      false, hwc_display_[HWC_DISPLAY_PRIMARY]);
-      hwc_procs_->invalidate(hwc_procs_);
+      AsyncRefresh();
       break;
     case kSetPanelBrightness:
       brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
@@ -1355,7 +1364,7 @@
     case kEnableFrameCapture:
       ret = color_mgr_->SetFrameCapture(pending_action.params,
                                         true, hwc_display_[HWC_DISPLAY_PRIMARY]);
-      hwc_procs_->invalidate(hwc_procs_);
+      AsyncRefresh();
       break;
     case kDisableFrameCapture:
       ret = color_mgr_->SetFrameCapture(pending_action.params,
@@ -1364,7 +1373,7 @@
     case kConfigureDetailedEnhancer:
       ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
                                             hwc_display_[HWC_DISPLAY_PRIMARY]);
-      hwc_procs_->invalidate(hwc_procs_);
+      AsyncRefresh();
       break;
     case kInvalidatingAndkSetPanelBrightness:
       brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
@@ -1374,7 +1383,7 @@
       }
       if (HWC_DISPLAY_PRIMARY == display_id)
         ret = hwc_display_[HWC_DISPLAY_PRIMARY]->CachePanelBrightness(*brightness_value);
-      hwc_procs_->invalidate(hwc_procs_);
+      AsyncRefresh();
       break;
     case kNoAction:
       break;
@@ -1460,7 +1469,7 @@
       if (panel_reset == 0) {
         if (hwc_procs_) {
           reset_panel_ = true;
-          hwc_procs_->invalidate(hwc_procs_);
+          AsyncRefresh();
         } else {
           DLOGW("Ignore resetpanel - hwc_proc not registered");
         }
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
index 1cd3e33..ce21c46 100644
--- a/sdm/libs/hwc/hwc_session.h
+++ b/sdm/libs/hwc/hwc_session.h
@@ -28,6 +28,7 @@
 #include <hardware/hwcomposer.h>
 #include <core/core_interface.h>
 #include <utils/locker.h>
+#include <future>   // NOLINT
 
 #include "hwc_display_primary.h"
 #include "hwc_display_external.h"
@@ -88,6 +89,7 @@
   int GetVsyncPeriod(int disp);
   int CreateExternalDisplay(int disp, uint32_t primary_width, uint32_t primary_height,
                             bool use_primary_res);
+  void AsyncRefresh();
 
   // QClient methods
   virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -103,7 +105,8 @@
   android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
   android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
                                    android::Parcel *output_parcel);
-  android::status_t ControlPartialUpdate(const android::Parcel *input_parcel, android::Parcel *out);
+  android::status_t ControlPartialUpdate(const android::Parcel *input_parcel,
+                                         android::Parcel *output_parcel);
   android::status_t OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
                                                    android::Parcel *output_parcel);
   android::status_t SetPanelBrightness(const android::Parcel *input_parcel,
@@ -151,6 +154,7 @@
   qService::QService *qservice_ = NULL;
   bool is_hdmi_primary_ = false;
   bool is_hdmi_yuv_ = false;
+  std::future<void> future_;
   std::bitset<HWC_NUM_DISPLAY_TYPES> connected_displays_;  // Bit mask of connected displays
   HWCSocketHandler socket_handler_;
   Locker uevent_locker_;
diff --git a/sdm/libs/hwc2/hwc_buffer_allocator.cpp b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
index da40a34..3c8d460 100644
--- a/sdm/libs/hwc2/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
@@ -114,10 +114,6 @@
   alloc_buffer_info->fd = -1;
   alloc_buffer_info->stride = 0;
   alloc_buffer_info->size = 0;
-  // Works around b/36355756
-  if (hnd != nullptr) {
-    delete hnd;
-  }
   buffer_info->private_data = NULL;
   return err;
 }
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index f48ed2d..4f623ce 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -54,26 +54,6 @@
 
 namespace sdm {
 
-static void ApplyDeInterlaceAdjustment(HWCLayer *hwc_layer, Layer *sdm_layer) {
-  // De-interlacing adjustment
-  if (sdm_layer->input_buffer.flags.interlace) {
-    // Adjust src_rect only if new source crop was set
-    if (hwc_layer->GetGeometryChanges() & kSourceCrop) {
-      float height = (sdm_layer->src_rect.bottom - sdm_layer->src_rect.top) / 2.0f;
-      sdm_layer->src_rect.top = ROUND_UP_ALIGN_DOWN(sdm_layer->src_rect.top / 2.0f, 2);
-      sdm_layer->src_rect.bottom = sdm_layer->src_rect.top + floorf(height);
-    }
-
-    // Handle deinterlacing for UBWC Interlaced format.
-    if (IsUBWCFormat(sdm_layer->input_buffer.format)) {
-      sdm_layer->input_buffer.height /= 2;
-      sdm_layer->input_buffer.unaligned_height /= 2;
-      // After adjustments layer needs to be treated as UBWC progressive. Reset interlace flag.
-      sdm_layer->input_buffer.flags.interlace = 0;
-    }
-  }
-}
-
 // This weight function is needed because the color primaries are not sorted by gamut size
 static ColorPrimaries WidestPrimaries(ColorPrimaries p1, ColorPrimaries p2) {
   int weight = 10;
@@ -417,6 +397,7 @@
   HWCLayer *layer = *layer_set_.emplace(new HWCLayer(id_, buffer_allocator_));
   layer_map_.emplace(std::make_pair(layer->GetId(), layer));
   *out_layer_id = layer->GetId();
+  validated_ = false;
   geometry_changes_ |= GeometryChanges::kAdded;
   return HWC2::Error::None;
 }
@@ -447,6 +428,7 @@
       break;
     }
   }
+  validated_ = false;
 
   geometry_changes_ |= GeometryChanges::kRemoved;
   return HWC2::Error::None;
@@ -462,6 +444,9 @@
   // Add one layer for fb target
   // TODO(user): Add blit target layers
   for (auto hwc_layer : layer_set_) {
+    // Reset layer data which SDM may change
+    hwc_layer->ResetPerFrameData();
+
     Layer *layer = hwc_layer->GetSDMLayer();
     layer->flags = {};   // Reset earlier flags
     if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Client) {
@@ -536,7 +521,6 @@
                                        INT(layer->dst_rect.right), INT(layer->dst_rect.bottom)};
     ApplyScanAdjustment(&scaled_display_frame);
     hwc_layer->SetLayerDisplayFrame(scaled_display_frame);
-    ApplyDeInterlaceAdjustment(hwc_layer, layer);
     // SDM requires these details even for solid fill
     if (layer->flags.solid_fill) {
       LayerBuffer *layer_buffer = &layer->input_buffer;
@@ -604,6 +588,7 @@
     DLOGE("[%" PRIu64 "] updateLayerZ failed to find layer", id_);
     return HWC2::Error::BadLayer;
   }
+  validated_ = false;
 
   const auto layer = map_layer->second;
   const auto z_range = layer_set_.equal_range(layer);
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index a375831..1b04c84 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -137,6 +137,18 @@
   virtual int GetDisplayConfigCount(uint32_t *count);
   virtual int GetDisplayAttributesForConfig(int config,
                                             DisplayConfigVariableInfo *display_attributes);
+  template <typename... Args>
+  int32_t CallLayerFunction(hwc2_layer_t layer, HWC2::Error (HWCLayer::*member)(Args... ),
+                            Args... args) {
+    auto status = HWC2::Error::BadLayer;
+    validated_ = false;
+    auto hwc_layer = GetHWCLayer(layer);
+    if (hwc_layer != nullptr) {
+      status = (hwc_layer->*member)(std::forward<Args>(args)...);
+    }
+
+    return INT32(status);
+  }
 
   int SetPanelBrightness(int level);
   int GetPanelBrightness(int *level);
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 7fef9cf..7fcd56b 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -258,14 +258,21 @@
 
 HWC2::Error HWCLayer::SetLayerDisplayFrame(hwc_rect_t frame) {
   LayerRect dst_rect = {};
+
   SetRect(frame, &dst_rect);
-  if (layer_->dst_rect != dst_rect) {
+  if (dst_rect_ != dst_rect) {
     geometry_changes_ |= kDisplayFrame;
-    layer_->dst_rect = dst_rect;
+    dst_rect_ = dst_rect;
   }
+
   return HWC2::Error::None;
 }
 
+void HWCLayer::ResetPerFrameData() {
+  layer_->dst_rect = dst_rect_;
+  layer_->transform = layer_transform_;
+}
+
 HWC2::Error HWCLayer::SetLayerPlaneAlpha(float alpha) {
   // Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter
   uint8_t plane_alpha = static_cast<uint8_t>(std::round(255.0f * alpha));
@@ -322,10 +329,11 @@
       break;
   }
 
-  if (layer_->transform != layer_transform) {
+  if (layer_transform_ != layer_transform) {
     geometry_changes_ |= kTransform;
-    layer_->transform = layer_transform;
+    layer_transform_ = layer_transform;
   }
+
   return HWC2::Error::None;
 }
 
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index bc3d84d..82bf466 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -61,6 +61,7 @@
   uint32_t GetZ() const { return z_; }
   hwc2_layer_t GetId() const { return id_; }
   Layer *GetSDMLayer() { return layer_; }
+  void ResetPerFrameData();
 
   HWC2::Error SetLayerBlendMode(HWC2::BlendMode mode);
   HWC2::Error SetLayerBuffer(buffer_handle_t buffer, int32_t acquire_fence);
@@ -96,6 +97,8 @@
   int ion_fd_ = -1;
   HWCBufferAllocator *buffer_allocator_ = NULL;
   int32_t dataspace_ =  HAL_DATASPACE_UNKNOWN;
+  LayerTransform layer_transform_ = {};
+  LayerRect dst_rect_ = {};
 
   // Composition requested by client(SF)
   HWC2::Composition client_requested_ = HWC2::Composition::Device;
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 87d41d7..7d31a3a 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -70,15 +70,11 @@
     }
 
     HWCSession *hwc_session = static_cast<HWCSession *>(device);
-    auto status = HWC2::Error::BadDisplay;
+    int32_t status = INT32(HWC2::Error::BadDisplay);
     if (hwc_session->hwc_display_[display]) {
-      status = HWC2::Error::BadLayer;
-      auto hwc_layer = hwc_session->hwc_display_[display]->GetHWCLayer(layer);
-      if (hwc_layer != nullptr) {
-        status = (hwc_layer->*member)(std::forward<Args>(args)...);
-      }
+      status = hwc_session->hwc_display_[display]->CallLayerFunction(layer, member, args...);
     }
-    return INT32(status);
+    return status;
   }
 
   // HWC2 Functions that require a concrete implementation in hwc session