sdm: Merge release fence after set power mode

On SetPowerMode() with retain pipes, DRM driver triggers the kick off
that enables MDP to read the previously queued buffer, Since the fence
created during SetPowerMode() is not merged with the previously queued
buffer, it may result in tearing. Hence get the release fence from
driver on SetPowerMode and propagate it to hwcomposer to merge it with
the previous release fence of all layer buffers to avoid tearing.

Change-Id: I81c078a1b05dd3fb34f10b9b70e25cfbcfabd117
CRs-Fixed: 2184515
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 303c89b..1f813ac 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -388,12 +388,13 @@
   /*! @brief Method to set current state of the display device.
 
     @param[in] state \link DisplayState \endlink
+    @param[in] pointer to release fence
 
     @return \link DisplayError \endlink
 
     @sa SetDisplayState
   */
-  virtual DisplayError SetDisplayState(DisplayState state) = 0;
+  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence) = 0;
 
   /*! @brief Method to set active configuration for variable properties of the display device.
 
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 82d14d9..0338bb7 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -430,7 +430,7 @@
   return last_power_mode_;
 }
 
-DisplayError DisplayBase::SetDisplayState(DisplayState state) {
+DisplayError DisplayBase::SetDisplayState(DisplayState state, int *release_fence) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   DisplayError error = kErrorNone;
   bool active = false;
@@ -452,7 +452,7 @@
     break;
 
   case kStateOn:
-    error = hw_intf_->PowerOn();
+    error = hw_intf_->PowerOn(release_fence);
     if (error != kErrorNone) {
       return error;
     }
@@ -468,13 +468,13 @@
     break;
 
   case kStateDoze:
-    error = hw_intf_->Doze();
+    error = hw_intf_->Doze(release_fence);
     active = true;
     last_power_mode_ = kStateDoze;
     break;
 
   case kStateDozeSuspend:
-    error = hw_intf_->DozeSuspend();
+    error = hw_intf_->DozeSuspend(release_fence);
     if (display_type_ != kPrimary) {
       active = true;
     }
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 014ea11..bd597c9 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2018, 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:
@@ -62,7 +62,7 @@
   virtual DisplayError GetConfig(DisplayConfigFixedInfo *variable_info);
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
-  virtual DisplayError SetDisplayState(DisplayState state);
+  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
   virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
     return kErrorNotSupported;
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 8466f8b..d9fef33 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -166,10 +166,10 @@
   return error;
 }
 
-DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
+DisplayError DisplayPrimary::SetDisplayState(DisplayState state, int *release_fence) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   DisplayError error = kErrorNone;
-  error = DisplayBase::SetDisplayState(state);
+  error = DisplayBase::SetDisplayState(state, release_fence);
   if (error != kErrorNone) {
     return error;
   }
@@ -391,19 +391,26 @@
 
 void DisplayPrimary::ResetPanel() {
   DisplayError status = kErrorNone;
+  int release_fence = -1;
 
   DLOGI("Powering off primary");
-  status = SetDisplayState(kStateOff);
+  status = SetDisplayState(kStateOff, &release_fence);
   if (status != kErrorNone) {
     DLOGE("power-off on primary failed with error = %d", status);
   }
+  if (release_fence >= 0) {
+    ::close(release_fence);
+  }
 
   DLOGI("Restoring power mode on primary");
   DisplayState mode = GetLastPowerMode();
-  status = SetDisplayState(mode);
+  status = SetDisplayState(mode, &release_fence);
   if (status != kErrorNone) {
     DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
   }
+  if (release_fence >= 0) {
+    ::close(release_fence);
+  }
 
   DLOGI("Enabling HWVsync");
   status = SetVSyncState(true);
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index a4dd4b8..e14c6d7 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -44,7 +44,7 @@
   virtual DisplayError Commit(LayerStack *layer_stack);
   virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
   virtual DisplayError DisablePartialUpdateOneFrame();
-  virtual DisplayError SetDisplayState(DisplayState state);
+  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
   virtual void SetIdleTimeoutMs(uint32_t active_ms);
   virtual DisplayError SetDisplayMode(uint32_t mode);
   virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index d5bf482..d28d911 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -709,7 +709,7 @@
   return kErrorNone;
 }
 
-DisplayError HWDeviceDRM::PowerOn() {
+DisplayError HWDeviceDRM::PowerOn(int *release_fence) {
   DTRACE_SCOPED();
   if (!drm_atomic_intf_) {
     DLOGE("DRM Atomic Interface is null!");
@@ -727,6 +727,7 @@
     DLOGE("Failed with error: %d", ret);
     return kErrorHardware;
   }
+  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, release_fence);
 
   return kErrorNone;
 }
@@ -750,7 +751,7 @@
   return kErrorNone;
 }
 
-DisplayError HWDeviceDRM::Doze() {
+DisplayError HWDeviceDRM::Doze(int *release_fence) {
   DTRACE_SCOPED();
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
   drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::DOZE);
@@ -760,10 +761,12 @@
     return kErrorHardware;
   }
 
+  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, release_fence);
+
   return kErrorNone;
 }
 
-DisplayError HWDeviceDRM::DozeSuspend() {
+DisplayError HWDeviceDRM::DozeSuspend(int *release_fence) {
   DTRACE_SCOPED();
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
   drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id,
@@ -774,6 +777,8 @@
     return kErrorHardware;
   }
 
+  drm_atomic_intf_->Perform(DRMOps::CRTC_GET_RELEASE_FENCE, token_.crtc_id, release_fence);
+
   return kErrorNone;
 }
 
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 3af3b77..a0f579d 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -67,10 +67,10 @@
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
-  virtual DisplayError PowerOn();
+  virtual DisplayError PowerOn(int *release_fence);
   virtual DisplayError PowerOff();
-  virtual DisplayError Doze();
-  virtual DisplayError DozeSuspend();
+  virtual DisplayError Doze(int *release_fence);
+  virtual DisplayError DozeSuspend(int *release_fence);
   virtual DisplayError Standby();
   virtual DisplayError Validate(HWLayers *hw_layers);
   virtual DisplayError Commit(HWLayers *hw_layers);
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index 245b573..adf1f1e 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -165,11 +165,11 @@
   return kErrorNone;
 }
 
-DisplayError HWTVDRM::Doze() {
+DisplayError HWTVDRM::Doze(int *release_fence) {
   return kErrorNone;
 }
 
-DisplayError HWTVDRM::DozeSuspend() {
+DisplayError HWTVDRM::DozeSuspend(int *release_fence) {
   return kErrorNone;
 }
 
diff --git a/sdm/libs/core/drm/hw_tv_drm.h b/sdm/libs/core/drm/hw_tv_drm.h
index 49384a2..3e592f9 100644
--- a/sdm/libs/core/drm/hw_tv_drm.h
+++ b/sdm/libs/core/drm/hw_tv_drm.h
@@ -43,8 +43,8 @@
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
   virtual DisplayError PowerOff();
-  virtual DisplayError Doze();
-  virtual DisplayError DozeSuspend();
+  virtual DisplayError Doze(int *release_fence);
+  virtual DisplayError DozeSuspend(int *release_fence);
   virtual DisplayError Standby();
   virtual DisplayError Commit(HWLayers *hw_layers);
   virtual void PopulateHWPanelInfo();
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 2c529ae..1f733a0 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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
@@ -155,7 +155,7 @@
   return kErrorNone;
 }
 
-DisplayError HWDevice::PowerOn() {
+DisplayError HWDevice::PowerOn(int *release_fence) {
   DTRACE_SCOPED();
 
   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
@@ -174,11 +174,11 @@
   return kErrorNone;
 }
 
-DisplayError HWDevice::Doze() {
+DisplayError HWDevice::Doze(int *release_fence) {
   return kErrorNone;
 }
 
-DisplayError HWDevice::DozeSuspend() {
+DisplayError HWDevice::DozeSuspend(int *release_fence) {
   return kErrorNone;
 }
 
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index f32c5bd..353cce5 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -70,10 +70,10 @@
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
-  virtual DisplayError PowerOn();
+  virtual DisplayError PowerOn(int *release_fence);
   virtual DisplayError PowerOff();
-  virtual DisplayError Doze();
-  virtual DisplayError DozeSuspend();
+  virtual DisplayError Doze(int *release_fence);
+  virtual DisplayError DozeSuspend(int *release_fence);
   virtual DisplayError Standby();
   virtual DisplayError Validate(HWLayers *hw_layers);
   virtual DisplayError Commit(HWLayers *hw_layers);
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index 5ee8121..3f3c28e 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015 - 2018, 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
@@ -344,7 +344,7 @@
   return kErrorNone;
 }
 
-DisplayError HWPrimary::Doze() {
+DisplayError HWPrimary::Doze(int *release_fence) {
   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_NORMAL) < 0) {
     IOCTL_LOGE(FB_BLANK_NORMAL, device_type_);
     return kErrorHardware;
@@ -353,7 +353,7 @@
   return kErrorNone;
 }
 
-DisplayError HWPrimary::DozeSuspend() {
+DisplayError HWPrimary::DozeSuspend(int *release_fence) {
   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_VSYNC_SUSPEND) < 0) {
     IOCTL_LOGE(FB_BLANK_VSYNC_SUSPEND, device_type_);
     return kErrorHardware;
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
index 69b5445..c6ca5a9 100644
--- a/sdm/libs/core/fb/hw_primary.h
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015-2016, 2018 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:
@@ -46,8 +46,8 @@
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
   virtual DisplayError PowerOff();
-  virtual DisplayError Doze();
-  virtual DisplayError DozeSuspend();
+  virtual DisplayError Doze(int *release_fence);
+  virtual DisplayError DozeSuspend(int *release_fence);
   virtual DisplayError Validate(HWLayers *hw_layers);
   virtual DisplayError Commit(HWLayers *hw_layers);
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 9bb825e..483a4df 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2018, 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:
@@ -85,10 +85,10 @@
   virtual DisplayError SetDisplayAttributes(uint32_t index) = 0;
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes) = 0;
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index) = 0;
-  virtual DisplayError PowerOn() = 0;
+  virtual DisplayError PowerOn(int *release_fence) = 0;
   virtual DisplayError PowerOff() = 0;
-  virtual DisplayError Doze() = 0;
-  virtual DisplayError DozeSuspend() = 0;
+  virtual DisplayError Doze(int *release_fence) = 0;
+  virtual DisplayError DozeSuspend(int *release_fence) = 0;
   virtual DisplayError Standby() = 0;
   virtual DisplayError Validate(HWLayers *hw_layers) = 0;
   virtual DisplayError Commit(HWLayers *hw_layers) = 0;
diff --git a/sdm/libs/hwc2/display_null.cpp b/sdm/libs/hwc2/display_null.cpp
index 16f4da6..7e52911 100644
--- a/sdm/libs/hwc2/display_null.cpp
+++ b/sdm/libs/hwc2/display_null.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -50,7 +50,7 @@
   return kErrorNone;
 }
 
-DisplayError DisplayNull::SetDisplayState(DisplayState state) {
+DisplayError DisplayNull::SetDisplayState(DisplayState state, int *release_fence) {
   state_ = state;
   return kErrorNone;
 }
diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h
index f6c0dda..bd49a16 100644
--- a/sdm/libs/hwc2/display_null.h
+++ b/sdm/libs/hwc2/display_null.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2018, 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
@@ -44,7 +44,7 @@
   virtual ~DisplayNull() { }
   virtual DisplayError Commit(LayerStack *layer_stack);
   virtual DisplayError GetDisplayState(DisplayState *state);
-  virtual DisplayError SetDisplayState(DisplayState state);
+  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
   virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
   virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
   virtual bool IsUnderscanSupported() { return true; }
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 978c3bc..4c0b969 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -745,9 +745,10 @@
     default:
       return HWC2::Error::BadParameter;
   }
+  int release_fence = -1;
 
   ATRACE_INT("SetPowerMode ", state);
-  DisplayError error = display_intf_->SetDisplayState(state);
+  DisplayError error = display_intf_->SetDisplayState(state, &release_fence);
   validated_ = false;
 
   if (error == kErrorNone) {
@@ -761,6 +762,20 @@
     return HWC2::Error::BadParameter;
   }
 
+  if (release_fence >= 0) {
+    for (auto hwc_layer : layer_set_) {
+      auto fence = hwc_layer->PopBackReleaseFence();
+      auto merged_fence = -1;
+      if (fence >= 0) {
+        merged_fence = sync_merge("sync_merge", release_fence, fence);
+        ::close(fence);
+      } else {
+        merged_fence = ::dup(release_fence);
+      }
+      hwc_layer->PushBackReleaseFence(merged_fence);
+    }
+    ::close(release_fence);
+  }
   return HWC2::Error::None;
 }
 
@@ -1132,7 +1147,7 @@
     for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
       auto hwc_layer = *it;
       out_layers[i] = hwc_layer->GetId();
-      out_fences[i] = hwc_layer->PopReleaseFence();
+      out_fences[i] = hwc_layer->PopFrontReleaseFence();
     }
   } else {
     *out_num_elements = UINT32(layer_set_.size());
@@ -1303,15 +1318,15 @@
       if (swap_interval_zero_ || layer->flags.single_buffer) {
         close(layer_buffer->release_fence_fd);
       } else if (layer->composition != kCompositionGPU) {
-        hwc_layer->PushReleaseFence(layer_buffer->release_fence_fd);
+        hwc_layer->PushBackReleaseFence(layer_buffer->release_fence_fd);
       } else {
-        hwc_layer->PushReleaseFence(-1);
+        hwc_layer->PushBackReleaseFence(-1);
       }
     } else {
       // In case of flush, we don't return an error to f/w, so it will get a release fence out of
       // the hwc_layer's release fence queue. We should push a -1 to preserve release fence
       // circulation semantics.
-      hwc_layer->PushReleaseFence(-1);
+      hwc_layer->PushBackReleaseFence(-1);
     }
 
     layer_buffer->release_fence_fd = -1;
diff --git a/sdm/libs/hwc2/hwc_display_external.cpp b/sdm/libs/hwc2/hwc_display_external.cpp
index 8e00cfd..bb4ea89 100644
--- a/sdm/libs/hwc2/hwc_display_external.cpp
+++ b/sdm/libs/hwc2/hwc_display_external.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2018, 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
@@ -238,9 +238,12 @@
         DLOGW("Set frame buffer config failed. Error = %d", error);
         return -1;
       }
-
+      int release_fence = -1;
       display_null_.GetDisplayState(&state);
-      display_intf_->SetDisplayState(state);
+      display_intf_->SetDisplayState(state, &release_fence);
+      if (release_fence >= 0) {
+        ::close(release_fence);
+      }
       validated_ = false;
 
       SetVsyncEnabled(HWC2::Vsync::Enable);
@@ -252,10 +255,14 @@
     }
   } else {
     if (!display_null_.IsActive()) {
+      int release_fence = -1;
       // Preserve required attributes of HDMI display that surfaceflinger sees.
       // Restore HDMI attributes when display is reconnected.
       display_intf_->GetDisplayState(&state);
-      display_null_.SetDisplayState(state);
+      display_null_.SetDisplayState(state, &release_fence);
+      if (release_fence >= 0) {
+        ::close(release_fence);
+      }
 
       error = display_intf_->GetFrameBufferConfig(&fb_config);
       if (error != kErrorNone) {
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 605b319..4320397 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -170,14 +170,14 @@
   layer_ = new Layer();
   // Fences are deferred, so the first time this layer is presented, return -1
   // TODO(user): Verify that fences are properly obtained on suspend/resume
-  release_fences_.push(-1);
+  release_fences_.push_back(-1);
 }
 
 HWCLayer::~HWCLayer() {
   // Close any fences left for this layer
   while (!release_fences_.empty()) {
     ::close(release_fences_.front());
-    release_fences_.pop();
+    release_fences_.pop_front();
   }
   if (layer_) {
     if (layer_->input_buffer.acquire_fence_fd >= 0) {
@@ -887,14 +887,28 @@
 
   return;
 }
-void HWCLayer::PushReleaseFence(int32_t fence) {
-  release_fences_.push(fence);
+
+void HWCLayer::PushBackReleaseFence(int32_t fence) {
+  release_fences_.push_back(fence);
 }
-int32_t HWCLayer::PopReleaseFence(void) {
+
+int32_t HWCLayer::PopBackReleaseFence() {
   if (release_fences_.empty())
     return -1;
+
+  auto fence = release_fences_.back();
+  release_fences_.pop_back();
+
+  return fence;
+}
+
+int32_t HWCLayer::PopFrontReleaseFence() {
+  if (release_fences_.empty())
+    return -1;
+
   auto fence = release_fences_.front();
-  release_fences_.pop();
+  release_fences_.pop_front();
+
   return fence;
 }
 
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index bbc602e..9226744 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -32,7 +32,7 @@
 #undef HWC2_INCLUDE_STRINGIFICATION
 #undef HWC2_USE_CPP11
 #include <map>
-#include <queue>
+#include <deque>
 #include <set>
 #include "core/buffer_allocator.h"
 #include "hwc_buffer_allocator.h"
@@ -88,8 +88,9 @@
   int32_t GetLayerDataspace() { return dataspace_; }
   uint32_t GetGeometryChanges() { return geometry_changes_; }
   void ResetGeometryChanges() { geometry_changes_ = GeometryChanges::kNone; }
-  void PushReleaseFence(int32_t fence);
-  int32_t PopReleaseFence(void);
+  void PushBackReleaseFence(int32_t fence);
+  int32_t PopBackReleaseFence(void);
+  int32_t PopFrontReleaseFence(void);
   bool ValidateAndSetCSC();
   bool SupportLocalConversion(ColorPrimaries working_primaries);
   void ResetValidation() { needs_validate_ = false; }
@@ -105,7 +106,7 @@
   const hwc2_layer_t id_;
   const hwc2_display_t display_id_;
   static std::atomic<hwc2_layer_t> next_id_;
-  std::queue<int32_t> release_fences_;
+  std::deque<int32_t> release_fences_;
   HWCBufferAllocator *buffer_allocator_ = NULL;
   int32_t dataspace_ =  HAL_DATASPACE_UNKNOWN;
   LayerTransform layer_transform_ = {};