sdm: Move display creation to respective classes

Move display creation to their respective classes to handle specific
create-time requirements.

Change-Id: I784ab9cc7fbadfd448b4ced37b125d4c5b0bad08
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
index 52c64d1..4987def 100644
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -37,21 +37,62 @@
 
 namespace sdm {
 
-HWCDisplayExternal::HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
-  : HWCDisplay(core_intf, hwc_procs, kHDMI, HWC_DISPLAY_EXTERNAL) {
+static void AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height, uint32_t *src_width,
+                                   uint32_t *src_height) {
+  *src_height = (dst_width * (*src_height)) / (*src_width);
+  *src_width = dst_width;
 }
 
-int HWCDisplayExternal::Init() {
-  int status = 0;
+int HWCDisplayExternal::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                               uint32_t primary_width, uint32_t primary_height,
+                               HWCDisplay **hwc_display) {
+  uint32_t external_width = 0;
+  uint32_t external_height = 0;
+  char property[PROPERTY_VALUE_MAX];
 
-  status = HWCDisplay::Init();
-  if (status != 0) {
+  HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, hwc_procs);
+  int status = hwc_display_external->Init();
+  if (status) {
+    delete hwc_display_external;
     return status;
   }
 
+  hwc_display_external->GetPanelResolution(&external_width, &external_height);
+
+  if (property_get("sys.hwc.mdp_downscale_enabled", property, "false") &&
+      !strcmp(property, "true")) {
+    uint32_t primary_area = primary_width * primary_height;
+    uint32_t external_area = external_width * external_height;
+
+    if (primary_area > external_area) {
+      if (primary_height > primary_width) {
+        Swap(primary_height, primary_width);
+      }
+      AdjustSourceResolution(primary_width, primary_height,
+                             &external_width, &external_height);
+    }
+  }
+
+  status = hwc_display_external->SetFrameBufferResolution(external_width, external_height);
+  if (status) {
+    Destroy(hwc_display_external);
+    return status;
+  }
+
+  *hwc_display = hwc_display_external;
+
   return status;
 }
 
+void HWCDisplayExternal::Destroy(HWCDisplay *hwc_display) {
+  hwc_display->Deinit();
+  delete hwc_display;
+}
+
+HWCDisplayExternal::HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
+  : HWCDisplay(core_intf, hwc_procs, kHDMI, HWC_DISPLAY_EXTERNAL) {
+}
+
 int HWCDisplayExternal::Prepare(hwc_display_contents_1_t *content_list) {
   int status = 0;
 
diff --git a/sdm/libs/hwc/hwc_display_external.h b/sdm/libs/hwc/hwc_display_external.h
index 6d3e229..a98ade3 100644
--- a/sdm/libs/hwc/hwc_display_external.h
+++ b/sdm/libs/hwc/hwc_display_external.h
@@ -31,13 +31,16 @@
 
 class HWCDisplayExternal : public HWCDisplay {
  public:
-  explicit HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
-  virtual int Init();
+  static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, uint32_t primary_width,
+                    uint32_t primary_height, HWCDisplay **hwc_display);
+  static void Destroy(HWCDisplay *hwc_display);
   virtual int Prepare(hwc_display_contents_1_t *content_list);
   virtual int Commit(hwc_display_contents_1_t *content_list);
   virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
+
  private:
-  virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
+  HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+  void ApplyScanAdjustment(hwc_rect_t *display_frame);
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
index 3769d69..2ea7681 100644
--- a/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -27,6 +27,7 @@
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#include <cutils/properties.h>
 #include <utils/constants.h>
 #include <stdarg.h>
 
@@ -37,6 +38,49 @@
 
 namespace sdm {
 
+int HWCDisplayPrimary::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                              HWCDisplay **hwc_display) {
+  int status = 0;
+  uint32_t primary_width = 0;
+  uint32_t primary_height = 0;
+  char property[PROPERTY_VALUE_MAX];
+
+  HWCDisplay *hwc_display_primary = new HWCDisplayPrimary(core_intf, hwc_procs);
+  status = hwc_display_primary->Init();
+  if (status) {
+    delete hwc_display_primary;
+    return status;
+  }
+
+  status = hwc_display_primary->SetPowerMode(HWC_POWER_MODE_NORMAL);
+  if (status) {
+    Destroy(hwc_display_primary);
+    return status;
+  }
+
+  hwc_display_primary->GetPanelResolution(&primary_width, &primary_height);
+  if (property_get("debug.hwc.fbsize", property, NULL) > 0) {
+    char *yptr = strcasestr(property, "x");
+    primary_width = atoi(property);
+    primary_height = atoi(yptr + 1);
+  }
+
+  status = hwc_display_primary->SetFrameBufferResolution(primary_width, primary_height);
+  if (status) {
+    Destroy(hwc_display_primary);
+    return status;
+  }
+
+  *hwc_display = hwc_display_primary;
+
+  return status;
+}
+
+void HWCDisplayPrimary::Destroy(HWCDisplay *hwc_display) {
+  hwc_display->Deinit();
+  delete hwc_display;
+}
+
 HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
   : HWCDisplay(core_intf, hwc_procs, kPrimary, HWC_DISPLAY_PRIMARY) {
 }
diff --git a/sdm/libs/hwc/hwc_display_primary.h b/sdm/libs/hwc/hwc_display_primary.h
index b65457b..2b923a3 100644
--- a/sdm/libs/hwc/hwc_display_primary.h
+++ b/sdm/libs/hwc/hwc_display_primary.h
@@ -30,20 +30,24 @@
 namespace sdm {
 
 class HWCDisplayPrimary : public HWCDisplay {
-public:
+ public:
   enum {
     SET_METADATA_DYN_REFRESH_RATE,
     SET_BINDER_DYN_REFRESH_RATE,
     SET_DISPLAY_MODE,
   };
 
-  explicit HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+  static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                    HWCDisplay **hwc_display);
+  static void Destroy(HWCDisplay *hwc_display);
   virtual int Prepare(hwc_display_contents_1_t *content_list);
   virtual int Commit(hwc_display_contents_1_t *content_list);
   virtual int SetActiveConfig(uint32_t index);
   virtual int SetRefreshRate(uint32_t refresh_rate);
   virtual int Perform(uint32_t operation, ...);
-private:
+
+ private:
+  HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
   void SetMetaDataRefreshRateFlag(bool enable);
   virtual DisplayError SetDisplayMode(uint32_t mode);
 };
diff --git a/sdm/libs/hwc/hwc_display_virtual.cpp b/sdm/libs/hwc/hwc_display_virtual.cpp
index 4d01d28..319c0ee 100644
--- a/sdm/libs/hwc/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc/hwc_display_virtual.cpp
@@ -30,6 +30,7 @@
 #include <utils/constants.h>
 #include <sync/sync.h>
 #include <stdarg.h>
+#include <gr.h>
 
 #include "hwc_display_virtual.h"
 #include "hwc_debugger.h"
@@ -38,7 +39,7 @@
 
 namespace sdm {
 
-static int GetWidthFromMetaData(const private_handle_t* handle) {
+static int GetWidthFromMetaData(const private_handle_t *handle) {
   MetaData_t *metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
   if (metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
     return metadata->bufferDim.sliceWidth;
@@ -47,7 +48,7 @@
   return handle->width;
 }
 
-static int GetHeightFromMetaData(const private_handle_t* handle) {
+static int GetHeightFromMetaData(const private_handle_t *handle) {
   MetaData_t *metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
   if (metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
     return metadata->bufferDim.sliceHeight;
@@ -56,6 +57,46 @@
   return handle->height;
 }
 
+int HWCDisplayVirtual::Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                              hwc_display_contents_1_t *content_list,
+                              HWCDisplay **hwc_display) {
+  int status = 0;
+  HWCDisplay *hwc_display_virtual = new HWCDisplayVirtual(core_intf, hwc_procs);
+
+  status = hwc_display_virtual->Init();
+  if (status) {
+    delete hwc_display_virtual;
+    return status;
+  }
+
+  status = hwc_display_virtual->SetPowerMode(HWC_POWER_MODE_NORMAL);
+  if (status) {
+    Destroy(hwc_display_virtual);
+    return status;
+  }
+
+  const private_handle_t *output_handle =
+    static_cast<const private_handle_t *>(content_list->outbuf);
+  int virtual_width = 0;
+  int virtual_height = 0;
+  getBufferSizeAndDimensions(output_handle->width, output_handle->height, output_handle->format,
+                             virtual_width, virtual_height);
+  status = hwc_display_virtual->SetFrameBufferResolution(virtual_width, virtual_height);
+  if (status) {
+    Destroy(hwc_display_virtual);
+    return status;
+  }
+
+  *hwc_display = hwc_display_virtual;
+
+  return status;
+}
+
+void HWCDisplayVirtual::Destroy(HWCDisplay *hwc_display) {
+  hwc_display->Deinit();
+  delete hwc_display;
+}
+
 HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
   : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL),
     dump_output_layer_(false), output_buffer_(NULL) {
@@ -89,6 +130,12 @@
 
 int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
   int status = 0;
+
+  status = SetOutputSliceFromMetadata(content_list);
+  if (status) {
+    return status;
+  }
+
   if (display_paused_) {
     MarkLayersForGPUBypass(content_list);
     return status;
@@ -151,15 +198,7 @@
   return 0;
 }
 
-int HWCDisplayVirtual::Perform(uint32_t operation, ...) {
-  if(operation != SET_OUTPUT_SLICE_FROM_METADATA) {
-    return -EINVAL;
-  }
-
-  va_list args;
-  va_start(args, operation);
-  hwc_display_contents_1_t *content_list = va_arg(args, hwc_display_contents_1_t *);
-  va_end(args);
+int HWCDisplayVirtual::SetOutputSliceFromMetadata(hwc_display_contents_1_t *content_list) {
   const private_handle_t *output_handle =
         static_cast<const private_handle_t *>(content_list->outbuf);
   DisplayError error = kErrorNone;
diff --git a/sdm/libs/hwc/hwc_display_virtual.h b/sdm/libs/hwc/hwc_display_virtual.h
index 40088fb..e680f71 100644
--- a/sdm/libs/hwc/hwc_display_virtual.h
+++ b/sdm/libs/hwc/hwc_display_virtual.h
@@ -33,29 +33,27 @@
 
 class HWCDisplayVirtual : public HWCDisplay {
  public:
-  enum {
-    SET_OUTPUT_SLICE_FROM_METADATA,
-  };
-
-  explicit HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+  static int Create(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
+                    hwc_display_contents_1_t *content_list, HWCDisplay **hwc_display);
+  static void Destroy(HWCDisplay *hwc_display);
+  static bool IsValidContentList(hwc_display_contents_1_t *content_list);
   virtual int Init();
   virtual int Deinit();
   virtual int Prepare(hwc_display_contents_1_t *content_list);
   virtual int Commit(hwc_display_contents_1_t *content_list);
   virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
-  virtual int Perform(uint32_t operation, ...);
-
-  static bool ValidateContentList(hwc_display_contents_1_t *content_list);
 
  private:
+  HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
   int SetOutputBuffer(hwc_display_contents_1_t *content_list);
   void DumpOutputBuffer(hwc_display_contents_1_t *content_list);
+  int SetOutputSliceFromMetadata(hwc_display_contents_1_t *content_list);
 
   bool dump_output_layer_;
   LayerBuffer *output_buffer_;
 };
 
-inline bool HWCDisplayVirtual::ValidateContentList(hwc_display_contents_1_t *content_list) {
+inline bool HWCDisplayVirtual::IsValidContentList(hwc_display_contents_1_t *content_list) {
   return (content_list && content_list->numHwLayers > 0 && content_list->outbuf);
 }
 
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 8014ae5..b0ff93d 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -130,47 +130,26 @@
   }
 
   // Create and power on primary display
-  hwc_display_[HWC_DISPLAY_PRIMARY] = new HWCDisplayPrimary(core_intf_, &hwc_procs_);
-  if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
-    CoreInterface::DestroyCore();
-    return -ENOMEM;
-  }
-
-  status = hwc_display_[HWC_DISPLAY_PRIMARY]->Init();
+  status = HWCDisplayPrimary::Create(core_intf_, &hwc_procs_,
+                                     &hwc_display_[HWC_DISPLAY_PRIMARY]);
   if (status) {
     CoreInterface::DestroyCore();
-    delete hwc_display_[HWC_DISPLAY_PRIMARY];
-    hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
-    return status;
-  }
-
-  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_NORMAL);
-  if (status) {
-    hwc_display_[HWC_DISPLAY_PRIMARY]->Deinit();
-    delete hwc_display_[HWC_DISPLAY_PRIMARY];
-    hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
-    CoreInterface::DestroyCore();
     return status;
   }
 
   if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {
     DLOGE("Failed to start = %s, error = %s", uevent_thread_name_);
-    hwc_display_[HWC_DISPLAY_PRIMARY]->Deinit();
-    delete hwc_display_[HWC_DISPLAY_PRIMARY];
+    HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
     hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
     CoreInterface::DestroyCore();
     return -errno;
   }
 
-  SetFrameBufferResolution(HWC_DISPLAY_PRIMARY, NULL);
-
   return 0;
 }
 
 int HWCSession::Deinit() {
-  hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_OFF);
-  hwc_display_[HWC_DISPLAY_PRIMARY]->Deinit();
-  delete hwc_display_[HWC_DISPLAY_PRIMARY];
+  HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
   hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
   uevent_thread_exit_ = true;
   pthread_join(uevent_thread_, NULL);
@@ -241,15 +220,11 @@
 
   for (ssize_t dpy = (num_displays - 1); dpy >= 0; dpy--) {
     hwc_display_contents_1_t *content_list = displays[dpy];
-    if(dpy == HWC_DISPLAY_VIRTUAL) {
+    if (dpy == HWC_DISPLAY_VIRTUAL) {
       if (hwc_session->hwc_display_[HWC_DISPLAY_EXTERNAL]) {
         continue;
       }
-      if (HWCDisplayVirtual::ValidateContentList(content_list)) {
-        hwc_session->CreateVirtualDisplay(content_list);
-      } else {
-        hwc_session->DestroyVirtualDisplay();
-      }
+      hwc_session->HandleVirtualDisplayLifeCycle(content_list);
     }
 
     if (hwc_session->hwc_display_[dpy]) {
@@ -275,7 +250,7 @@
 
   for (size_t dpy = 0; dpy < num_displays; dpy++) {
     hwc_display_contents_1_t *content_list = displays[dpy];
-    if(dpy == HWC_DISPLAY_VIRTUAL) {
+    if (dpy == HWC_DISPLAY_VIRTUAL) {
       if (hwc_session->hwc_display_[HWC_DISPLAY_EXTERNAL]) {
         if (content_list) {
           for (size_t i = 0; i < content_list->numHwLayers; i++) {
@@ -311,7 +286,7 @@
 
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
   int status = -EINVAL;
-  if(hwc_session->hwc_display_[disp]) {
+  if (hwc_session->hwc_display_[disp]) {
     status = hwc_session->hwc_display_[disp]->EventControl(event, enable);
   }
 
@@ -327,10 +302,10 @@
 
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
   int status = -EINVAL;
-  if(hwc_session->hwc_display_[disp]) {
+  if (hwc_session->hwc_display_[disp]) {
     status = hwc_session->hwc_display_[disp]->SetPowerMode(mode);
   }
-  if(disp == HWC_DISPLAY_PRIMARY && hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+  if (disp == HWC_DISPLAY_PRIMARY && hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
     // Set the power mode for virtual display while setting power mode for primary, as SF
     // does not invoke SetPowerMode() for virtual display.
     status = hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]->SetPowerMode(mode);
@@ -378,7 +353,7 @@
 
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
   int status = -EINVAL;
-  if(hwc_session->hwc_display_[disp]) {
+  if (hwc_session->hwc_display_[disp]) {
     status = hwc_session->hwc_display_[disp]->GetDisplayConfigs(configs, num_configs);
   }
 
@@ -395,7 +370,7 @@
 
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
   int status = -EINVAL;
-  if(hwc_session->hwc_display_[disp]) {
+  if (hwc_session->hwc_display_[disp]) {
     status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, attributes, values);
   }
 
@@ -411,7 +386,7 @@
 
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
   int active_config = -1;
-  if(hwc_session->hwc_display_[disp]) {
+  if (hwc_session->hwc_display_[disp]) {
     active_config = hwc_session->hwc_display_[disp]->GetActiveConfig();
   }
 
@@ -427,57 +402,26 @@
 
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
   int status = -EINVAL;
-  if(hwc_session->hwc_display_[disp]) {
+  if (hwc_session->hwc_display_[disp]) {
     status = hwc_session->hwc_display_[disp]->SetActiveConfig(index);
   }
 
   return status;
 }
 
-int HWCSession::CreateVirtualDisplay(hwc_display_contents_1_t *content_list) {
+int HWCSession::HandleVirtualDisplayLifeCycle(hwc_display_contents_1_t *content_list) {
   int status = 0;
 
-  if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
-    // Create virtual display device
-    hwc_display_[HWC_DISPLAY_VIRTUAL] = new HWCDisplayVirtual(core_intf_, &hwc_procs_);
+  if (HWCDisplayVirtual::IsValidContentList(content_list)) {
     if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
-      // This is not catastrophic. Leave a warning message for now.
-      DLOGW("Virtual Display creation failed");
-      return -ENOMEM;
+      // Create virtual display device
+      status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, content_list,
+                                         &hwc_display_[HWC_DISPLAY_VIRTUAL]);
     }
-
-    status = hwc_display_[HWC_DISPLAY_VIRTUAL]->Init();
-    if (status) {
-      goto CleanupOnError;
-    }
-
-    status = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetPowerMode(HWC_POWER_MODE_NORMAL);
-    if (status) {
-      goto CleanupOnError;
-    }
-  }
-
-  if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
-    SetFrameBufferResolution(HWC_DISPLAY_VIRTUAL, content_list);
-    status = hwc_display_[HWC_DISPLAY_VIRTUAL]->Perform(
-        HWCDisplayVirtual::SET_OUTPUT_SLICE_FROM_METADATA, content_list);
-  }
-
-  return status;
-
-CleanupOnError:
-  DestroyVirtualDisplay();
-  return status;
-}
-
-int HWCSession::DestroyVirtualDisplay() {
-  int status = 0;
-
-  if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
-    status = hwc_display_[HWC_DISPLAY_VIRTUAL]->Deinit();
-    if (!status) {
-      delete hwc_display_[HWC_DISPLAY_VIRTUAL];
-      hwc_display_[HWC_DISPLAY_VIRTUAL] = NULL;
+  } else {
+    if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
+      HWCDisplayVirtual::Destroy(hwc_display_[HWC_DISPLAY_VIRTUAL]);
+      hwc_display_[HWC_DISPLAY_VIRTUAL] = 0;
       // Signal the HotPlug thread to continue with the external display connection
       locker_.Signal();
     }
@@ -543,7 +487,7 @@
   uint32_t display_status = UINT32(input_parcel->readInt32());
 
   DLOGI("Display %d Status %d", display_id, display_status);
-  if(display_id < HWC_DISPLAY_EXTERNAL || display_id > HWC_DISPLAY_VIRTUAL) {
+  if (display_id < HWC_DISPLAY_EXTERNAL || display_id > HWC_DISPLAY_VIRTUAL) {
     DLOGW("Not supported for display %d", display_id);
     return -EINVAL;
   }
@@ -780,28 +724,24 @@
      DLOGE("HDMI already connected");
      return -1;
     }
+
+    uint32_t primary_width = 0;
+    uint32_t primary_height = 0;
+    hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
     // Create hdmi display
-    hwc_display_[HWC_DISPLAY_EXTERNAL] = new HWCDisplayExternal(core_intf_, &hwc_procs_);
-    if (!hwc_display_[HWC_DISPLAY_EXTERNAL]) {
-      return -1;
-    }
-    int status = hwc_display_[HWC_DISPLAY_EXTERNAL]->Init();
+    int status = HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width,
+                                            primary_height, &hwc_display_[HWC_DISPLAY_EXTERNAL]);
     if (status) {
-      delete hwc_display_[HWC_DISPLAY_EXTERNAL];
-      hwc_display_[HWC_DISPLAY_EXTERNAL] = NULL;
-      return -1;
+      return status;
     }
-    SetFrameBufferResolution(HWC_DISPLAY_EXTERNAL, NULL);
   } else {
     SEQUENCE_WAIT_SCOPE_LOCK(locker_);
     if (!hwc_display_[HWC_DISPLAY_EXTERNAL]) {
      DLOGE("HDMI not connected");
      return -1;
     }
-    hwc_display_[HWC_DISPLAY_EXTERNAL]->SetPowerMode(HWC_POWER_MODE_OFF);
-    hwc_display_[HWC_DISPLAY_EXTERNAL]->Deinit();
-    delete hwc_display_[HWC_DISPLAY_EXTERNAL];
-    hwc_display_[HWC_DISPLAY_EXTERNAL] = NULL;
+    HWCDisplayExternal::Destroy(hwc_display_[HWC_DISPLAY_EXTERNAL]);
+    hwc_display_[HWC_DISPLAY_EXTERNAL] = 0;
   }
 
   // notify client and trigger a screen refresh
@@ -811,72 +751,5 @@
   return 0;
 }
 
-void HWCSession::SetFrameBufferResolution(int disp, hwc_display_contents_1_t *content_list) {
-  char property[PROPERTY_VALUE_MAX];
-  uint32_t primary_width = 0;
-  uint32_t primary_height = 0;
-
-  switch (disp) {
-  case HWC_DISPLAY_PRIMARY:
-  {
-    hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelResolution(&primary_width, &primary_height);
-    if (property_get("debug.hwc.fbsize", property, NULL) > 0) {
-      char *yptr = strcasestr(property, "x");
-      primary_width = atoi(property);
-      primary_height = atoi(yptr + 1);
-    }
-    hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameBufferResolution(primary_width, primary_height);
-    break;
-  }
-
-  case HWC_DISPLAY_EXTERNAL:
-  {
-    uint32_t external_width = 0;
-    uint32_t external_height = 0;
-    hwc_display_[HWC_DISPLAY_EXTERNAL]->GetPanelResolution(&external_width, &external_height);
-
-    if (property_get("sys.hwc.mdp_downscale_enabled", property, "false") &&
-        !strcmp(property, "true")) {
-      hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
-      uint32_t primary_area = primary_width * primary_height;
-      uint32_t external_area = external_width * external_height;
-
-      if (primary_area > external_area) {
-        if (primary_height > primary_width) {
-          Swap(primary_height, primary_width);
-        }
-        AdjustSourceResolution(primary_width, primary_height,
-                               &external_width, &external_height);
-      }
-    }
-    hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameBufferResolution(external_width, external_height);
-    break;
-  }
-
-  case HWC_DISPLAY_VIRTUAL:
-  {
-    if (HWCDisplayVirtual::ValidateContentList(content_list)) {
-      const private_handle_t *output_handle =
-              static_cast<const private_handle_t *>(content_list->outbuf);
-      int virtual_width = 0;
-      int virtual_height = 0;
-      getBufferSizeAndDimensions(output_handle->width, output_handle->height, output_handle->format,
-                                 virtual_width, virtual_height);
-      hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameBufferResolution(virtual_width, virtual_height);
-    }
-    break;
-  }
-
-  default:
-    break;
-  }
-}
-
-void HWCSession::AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height,
-                                        uint32_t *src_width, uint32_t *src_height) {
-  *src_height = (dst_width * (*src_height)) / (*src_width);
-  *src_width = dst_width;
-}
-
 }  // namespace sdm
 
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
index 6d4a07a..5f844eb 100644
--- a/sdm/libs/hwc/hwc_session.h
+++ b/sdm/libs/hwc/hwc_session.h
@@ -76,8 +76,7 @@
   int GetEventValue(const char *uevent_data, int length, const char *event_info);
   int HotPlugHandler(bool connected);
   void ResetPanel();
-  int CreateVirtualDisplay(hwc_display_contents_1_t *content_list);
-  int DestroyVirtualDisplay();
+  int HandleVirtualDisplayLifeCycle(hwc_display_contents_1_t *content_list);
 
   // QClient methods
   virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -87,9 +86,6 @@
   android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
   android::status_t SetDisplayMode(const android::Parcel *input_parcel);
   android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel);
-  void SetFrameBufferResolution(int disp, hwc_display_contents_1_t *content_list);
-  void AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height,
-                              uint32_t *src_width, uint32_t *src_height);
   android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
 
   static Locker locker_;