Merge "config: remove lights HIDL Hal packages from display-product.mk"
diff --git a/composer/gl_color_convert_impl.cpp b/composer/gl_color_convert_impl.cpp
index 60c7a40..1658a9d 100644
--- a/composer/gl_color_convert_impl.cpp
+++ b/composer/gl_color_convert_impl.cpp
@@ -27,6 +27,8 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <vector>
+
 #include "gl_color_convert_impl.h"
 
 #define __CLASS__ "GLColorConvertImpl"
@@ -165,7 +167,8 @@
   SetProgram(ctx_.program_id);
 
   SetSourceBuffer(src_hnd);
-  SetDestinationBuffer(dst_hnd, dst_rect);
+  SetDestinationBuffer(dst_hnd);
+  SetViewport(dst_rect);
 
   glEnableVertexAttribArray(0);
   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenVertices);
@@ -173,10 +176,8 @@
   glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenTexCoords);
   glDrawArrays(GL_TRIANGLES, 0, 3);
 
-  shared_ptr<Fence> in_fence = Fence::Merge(src_acquire_fence, dst_acquire_fence);
-  if (in_fence) {
-    WaitOnInputFence(in_fence);
-  }
+  std::vector<shared_ptr<Fence>> in_fence = {Fence::Merge(src_acquire_fence, dst_acquire_fence)};
+  WaitOnInputFence(in_fence);
 
   // Create output fence for client to wait on.
   CreateOutputFence(release_fence);
diff --git a/composer/gl_common.cpp b/composer/gl_common.cpp
index 4d4744d..8245e5f 100644
--- a/composer/gl_common.cpp
+++ b/composer/gl_common.cpp
@@ -27,6 +27,9 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <vector>
+#include <string>
+
 #include "gl_common.h"
 
 #define __CLASS__ "GLCommon"
@@ -97,21 +100,29 @@
   }
 }
 
-void GLCommon::SetDestinationBuffer(const private_handle_t *dst_hnd, const GLRect &dst_rect) {
+void GLCommon::SetDestinationBuffer(const private_handle_t *dst_hnd, bool force_set) {
   DTRACE_SCOPED();
+  if (!force_set && (dst_hnd_ == dst_hnd)) {
+    return;
+  }
   EGLImageBuffer *dst_buffer = image_wrapper_.wrap(reinterpret_cast<const void *>(dst_hnd));
 
   if (dst_buffer) {
     GL(glBindFramebuffer(GL_FRAMEBUFFER, dst_buffer->getFramebuffer()));
-    float width = dst_rect.right - dst_rect.left;
-    float height = dst_rect.bottom - dst_rect.top;
-    GL(glViewport(dst_rect.left, dst_rect.top, width, height));
   }
+
+  // Same buffer gets reprogrammed. Avoid repeated setting.
+  dst_hnd_ = dst_hnd;
 }
 
-int GLCommon::WaitOnInputFence(const shared_ptr<Fence> &in_fence) {
+int GLCommon::WaitOnInputFence(const std::vector<shared_ptr<Fence>> &in_fences) {
   DTRACE_SCOPED();
 
+  shared_ptr<Fence> in_fence = Fence::Merge(in_fences, true /* ignore signaled*/);
+  if (in_fence == nullptr) {
+   return 0;
+  }
+
   int fd = Fence::Dup(in_fence);
   EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd, EGL_NONE};
   EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID,
@@ -182,5 +193,12 @@
   }
 }
 
+void GLCommon::SetViewport(const GLRect &dst_rect) {
+  DTRACE_SCOPED();
+  float width = dst_rect.right - dst_rect.left;
+  float height = dst_rect.bottom - dst_rect.top;
+  GL(glViewport(dst_rect.left, dst_rect.top, width, height));
+}
+
 }  // namespace sdm
 
diff --git a/composer/gl_common.h b/composer/gl_common.h
index 31961e6..bfeaade 100644
--- a/composer/gl_common.h
+++ b/composer/gl_common.h
@@ -30,7 +30,10 @@
 #ifndef __GL_COMMON_H__
 #define __GL_COMMON_H__
 
+#include <sync/sync.h>
 #include <utils/debug.h>
+#include <vector>
+#include <string>
 
 #include "glengine.h"
 #include "EGLImageWrapper.h"
@@ -58,20 +61,22 @@
   virtual void DumpShaderLog(int shader);
   virtual void MakeCurrent(const GLContext *ctx);
   virtual void SetProgram(uint32_t id);
-  virtual void SetDestinationBuffer(const private_handle_t *dst_hnd, const GLRect &dst_rect);
+  virtual void SetDestinationBuffer(const private_handle_t *dst_hnd, bool force_set = true);
   virtual void SetSourceBuffer(const private_handle_t *src_hnd);
   virtual void DestroyContext(GLContext *ctx);
   virtual void DeleteProgram(uint32_t id);
-  virtual int WaitOnInputFence(const shared_ptr<Fence> &in_fence);
+  virtual int WaitOnInputFence(const std::vector<shared_ptr<Fence>> &in_fences);
   virtual int CreateOutputFence(shared_ptr<Fence> *out_fence);
   virtual void ClearCache();
   virtual void SetRealTimePriority();
+  virtual void SetViewport(const GLRect &dst_rect);
 
  protected:
   virtual ~GLCommon() { }
 
  private:
   EGLImageWrapper image_wrapper_;
+  const private_handle_t *dst_hnd_ = nullptr;
 };
 
 }  // namespace sdm
diff --git a/composer/gl_layer_stitch.h b/composer/gl_layer_stitch.h
index e21e5da..9a86820 100644
--- a/composer/gl_layer_stitch.h
+++ b/composer/gl_layer_stitch.h
@@ -31,19 +31,26 @@
 #define __GL_LAYER_STITCH_H__
 
 #include <gralloc_priv.h>
+#include <vector>
+
 #include "gl_common.h"
 
 namespace sdm {
+struct StitchParams {
+  const private_handle_t *src_hnd = nullptr;
+  const private_handle_t *dst_hnd = nullptr;
+  GLRect src_rect;
+  GLRect dst_rect;
+  GLRect scissor_rect;
+  shared_ptr<Fence> src_acquire_fence = nullptr;
+  shared_ptr<Fence> dst_acquire_fence = nullptr;
+};
 
 class GLLayerStitch {
  public:
   static GLLayerStitch* GetInstance(bool secure);
   static void Destroy(GLLayerStitch *intf);
-
-  virtual int Blit(const private_handle_t *src_hnd, const private_handle_t *dst_hnd,
-                   const GLRect &src_rect, const GLRect &dst_rect, const GLRect &scissor_rect,
-                   const shared_ptr<Fence> &src_acquire_fence,
-                   const shared_ptr<Fence> &dst_acquire_fence,
+  virtual int Blit(const std::vector<StitchParams> &stitch_params,
                    shared_ptr<Fence> *release_fence) = 0;
  protected:
   virtual ~GLLayerStitch() { }
diff --git a/composer/gl_layer_stitch_impl.cpp b/composer/gl_layer_stitch_impl.cpp
index b0d6171..f3b18dc 100644
--- a/composer/gl_layer_stitch_impl.cpp
+++ b/composer/gl_layer_stitch_impl.cpp
@@ -27,6 +27,8 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <vector>
+
 #include "gl_layer_stitch_impl.h"
 
 #define __CLASS__ "GLLayerStitchImpl"
@@ -72,6 +74,10 @@
   "    color = texture(u_sTexture, uv);                                  \n"
   "}                                                                     \n";
 
+static bool IsValid(const GLRect &rect) {
+  return ((rect.right - rect.left) && (rect.bottom - rect.top));
+}
+
 int GLLayerStitchImpl::CreateContext(bool secure) {
   ctx_.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   EGL(eglBindAPI(EGL_OPENGL_ES_API));
@@ -128,42 +134,59 @@
   ctx_.program_id = LoadProgram(1, &kVertexShader1, count, fragment_shaders);
 
   SetRealTimePriority();
+  InitContext();
 
   return 0;
 }
 
-int GLLayerStitchImpl::Blit(const private_handle_t *src_hnd, const private_handle_t *dst_hnd,
-                            const GLRect &src_rect, const GLRect &dst_rect,
-                            const GLRect &scissor_rect,
-                            const shared_ptr<Fence> &src_acquire_fence,
-                            const shared_ptr<Fence> &dst_acquire_fence,
+int GLLayerStitchImpl::Blit(const std::vector<StitchParams> &stitch_params,
                             shared_ptr<Fence> *release_fence) {
   DTRACE_SCOPED();
-  // eglMakeCurrent attaches rendering context to rendering surface.
-  MakeCurrent(&ctx_);
 
-  SetProgram(ctx_.program_id);
+  std::vector<shared_ptr<Fence>> acquire_fences;
+  std::vector<shared_ptr<Fence>> release_fences;
+  bool can_batch = !NeedsGLScissor(stitch_params);
+  for (auto &info : stitch_params) {
+    SetSourceBuffer(info.src_hnd);
+    SetDestinationBuffer(info.dst_hnd, false);
+    SetViewport(info.dst_rect);
+    ClearWithTransparency(info.scissor_rect);
+    glDrawArrays(GL_TRIANGLES, 0, 3);
 
-  ClearWithTransparency(scissor_rect);
+    acquire_fences.push_back(info.src_acquire_fence);
 
-  SetSourceBuffer(src_hnd);
-  SetDestinationBuffer(dst_hnd, dst_rect);
+    if (!can_batch) {
+      // Trigger flush and cache release fence.
+      WaitOnInputFence(acquire_fences);
+      shared_ptr<Fence> temp_release_fence = nullptr;
+      CreateOutputFence(&temp_release_fence);
+      release_fences.push_back(temp_release_fence);
+      acquire_fences = {};
+    }
+  }
 
-  glEnableVertexAttribArray(0);
-  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenVertices);
-  glEnableVertexAttribArray(1);
-  glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenTexCoords);
-  glDrawArrays(GL_TRIANGLES, 0, 3);
-
-  // Dst. is always guaranteed to be signaled.
-  WaitOnInputFence(src_acquire_fence);
-
-  // Create output fence for client to wait on.
-  CreateOutputFence(release_fence);
+  if (can_batch) {
+    // Create output fence for client to wait on.
+    WaitOnInputFence(acquire_fences);
+    CreateOutputFence(release_fence);
+  } else {
+    // Merge all fd's and return one.
+    *release_fence = Fence::Merge(release_fences, false);
+  }
 
   return 0;
 }
 
+int GLLayerStitchImpl::NeedsGLScissor(const std::vector<StitchParams> &stitch_params) {
+  for (auto &info : stitch_params) {
+    if (IsValid(info.scissor_rect)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 int GLLayerStitchImpl::Init() {
   return CreateContext(secure_);
 }
@@ -176,12 +199,31 @@
 }
 
 void GLLayerStitchImpl::ClearWithTransparency(const GLRect &scissor_rect) {
+  if (!IsValid(scissor_rect)) {
+    // Disable scissor.
+    GL(glDisable(GL_SCISSOR_TEST));
+    return;
+  }
+
   DTRACE_SCOPED();
-  GL(glScissor(scissor_rect.left, scissor_rect.top, scissor_rect.right - scissor_rect.left,
-               scissor_rect.bottom - scissor_rect.top));
+  // Enable scissor test.
   GL(glEnable(GL_SCISSOR_TEST));
   GL(glClearColor(0, 0, 0, 0));
   GL(glClear(GL_COLOR_BUFFER_BIT));
+  GL(glScissor(scissor_rect.left, scissor_rect.top, scissor_rect.right - scissor_rect.left,
+               scissor_rect.bottom - scissor_rect.top));
+}
+
+void GLLayerStitchImpl::InitContext() {
+  // eglMakeCurrent attaches rendering context to rendering surface.
+  MakeCurrent(&ctx_);
+  SetProgram(ctx_.program_id);
+  SetRealTimePriority();
+  // Set vertices.
+  glEnableVertexAttribArray(0);
+  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenVertices);
+  glEnableVertexAttribArray(1);
+  glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenTexCoords);
 }
 
 GLLayerStitchImpl::~GLLayerStitchImpl() {}
diff --git a/composer/gl_layer_stitch_impl.h b/composer/gl_layer_stitch_impl.h
index 9bef544..d438d77 100644
--- a/composer/gl_layer_stitch_impl.h
+++ b/composer/gl_layer_stitch_impl.h
@@ -32,6 +32,8 @@
 
 #include <sync/sync.h>
 
+#include <vector>
+
 #include "gl_layer_stitch.h"
 #include "gl_common.h"
 
@@ -41,11 +43,7 @@
  public:
   explicit GLLayerStitchImpl(bool secure);
   virtual ~GLLayerStitchImpl();
-  virtual int Blit(const private_handle_t *src_hnd, const private_handle_t *dst_hnd,
-                   const GLRect &src_rect, const GLRect &dst_rect, const GLRect &scissor_rect,
-                   const shared_ptr<Fence> &src_acquire_fence,
-                   const shared_ptr<Fence> &dst_acquire_fence,
-                   shared_ptr<Fence> *release_fence);
+  virtual int Blit(const std::vector<StitchParams> &stitch_params, shared_ptr<Fence> *release_fence);
   virtual int CreateContext(bool secure);
   virtual int Init();
   virtual int Deinit();
@@ -53,7 +51,9 @@
   bool secure_ = false;
   GLContext ctx_;
 
+  void InitContext();
   void ClearWithTransparency(const GLRect &scissor_rect);
+  int NeedsGLScissor(const std::vector<StitchParams> &stitch_params);
 };
 
 }  // namespace sdm
diff --git a/composer/hwc_display_builtin.cpp b/composer/hwc_display_builtin.cpp
index 95b94a7..9a26cea 100644
--- a/composer/hwc_display_builtin.cpp
+++ b/composer/hwc_display_builtin.cpp
@@ -300,30 +300,37 @@
     return HWC2::Error::None;
   }
 
+  LayerStitchContext ctx = {};
   for (auto &layer : layer_stack_.layers) {
     LayerComposition &composition = layer->composition;
     if (composition != kCompositionStitch) {
       continue;
     }
 
-    LayerStitchContext ctx = {};
+    StitchParams params = {};
     // Stitch target doesn't have an input fence.
     // Render all layers at specified destination.
     LayerBuffer &input_buffer = layer->input_buffer;
-    ctx.src_hnd = reinterpret_cast<const private_handle_t *>(input_buffer.buffer_id);
+    params.src_hnd = reinterpret_cast<const private_handle_t *>(input_buffer.buffer_id);
     Layer *stitch_layer = stitch_target_->GetSDMLayer();
     LayerBuffer &output_buffer = stitch_layer->input_buffer;
-    ctx.dst_hnd = reinterpret_cast<const private_handle_t *>(output_buffer.buffer_id);
-    SetRect(layer->stitch_info.dst_rect, &ctx.dst_rect);
-    SetRect(layer->stitch_info.slice_rect, &ctx.scissor_rect);
-    ctx.src_acquire_fence = input_buffer.acquire_fence;
+    params.dst_hnd = reinterpret_cast<const private_handle_t *>(output_buffer.buffer_id);
+    SetRect(layer->stitch_info.dst_rect, &params.dst_rect);
+    SetRect(layer->stitch_info.slice_rect, &params.scissor_rect);
+    params.src_acquire_fence = input_buffer.acquire_fence;
 
-    layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeStitch, &ctx);
-
-    // Merge with current fence.
-    output_buffer.acquire_fence = Fence::Merge(output_buffer.acquire_fence, ctx.release_fence);
+    ctx.stitch_params.push_back(params);
   }
 
+  if (!ctx.stitch_params.size()) {
+    // No layers marked for stitch.
+    return HWC2::Error::None;
+  }
+
+  layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeStitch, &ctx);
+  // Set release fence.
+  output_buffer_.acquire_fence = ctx.release_fence;
+
   return HWC2::Error::None;
 }
 
@@ -1306,9 +1313,7 @@
     case LayerStitchTaskCode::kCodeStitch: {
         DTRACE_SCOPED();
         LayerStitchContext* ctx = reinterpret_cast<LayerStitchContext*>(task_context);
-        gl_layer_stitch_->Blit(ctx->src_hnd, ctx->dst_hnd, ctx->src_rect, ctx->dst_rect,
-                               ctx->scissor_rect, ctx->src_acquire_fence,
-                               ctx->dst_acquire_fence, &(ctx->release_fence));
+        gl_layer_stitch_->Blit(ctx->stitch_params, &(ctx->release_fence));
       }
       break;
     case LayerStitchTaskCode::kCodeDestroyInstance: {
diff --git a/composer/hwc_display_builtin.h b/composer/hwc_display_builtin.h
index f41c1a5..a0da3fd 100644
--- a/composer/hwc_display_builtin.h
+++ b/composer/hwc_display_builtin.h
@@ -56,11 +56,7 @@
 };
 
 struct LayerStitchContext : public SyncTask<LayerStitchTaskCode>::TaskContext {
-  const private_handle_t* src_hnd = nullptr;
-  const private_handle_t* dst_hnd = nullptr;
-  GLRect src_rect = {};
-  GLRect dst_rect = {};
-  GLRect scissor_rect = {};
+  vector<StitchParams> stitch_params;
   shared_ptr<Fence> src_acquire_fence = nullptr;
   shared_ptr<Fence> dst_acquire_fence = nullptr;
   shared_ptr<Fence> release_fence = nullptr;
diff --git a/composer/hwc_display_pluggable.cpp b/composer/hwc_display_pluggable.cpp
index 61169de..a0a1198 100644
--- a/composer/hwc_display_pluggable.cpp
+++ b/composer/hwc_display_pluggable.cpp
@@ -134,9 +134,11 @@
   }
 
   // Apply current Color Mode and Render Intent.
-  if (color_mode_->ApplyCurrentColorModeWithRenderIntent(
-      static_cast<bool>(layer_stack_.flags.hdr_present)) != HWC2::Error::None) {
-    // Fallback to GPU Composition, if Color Mode can't be applied.
+  status = color_mode_->ApplyCurrentColorModeWithRenderIntent(
+                                                 static_cast<bool>(layer_stack_.flags.hdr_present));
+  if (status != HWC2::Error::None || has_color_tranform_) {
+    // Fallback to GPU Composition if Color Mode can't be applied or if a color tranform needs to be
+    // applied.
     MarkLayersForClientComposition();
   }
 
@@ -328,4 +330,22 @@
   return HWC2::Error::None;
 }
 
+HWC2::Error HWCDisplayPluggable::SetColorTransform(const float *matrix,
+                                                   android_color_transform_t hint) {
+  if (HAL_COLOR_TRANSFORM_IDENTITY == hint) {
+    has_color_tranform_ = false;
+    // From 2.1 IComposerClient.hal:
+    // If the device is not capable of either using the hint or the matrix to apply the desired
+    // color transform, it must force all layers to client composition during VALIDATE_DISPLAY.
+  } else {
+    // Also, interpret HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX hint as non-identity matrix.
+    has_color_tranform_ = true;
+  }
+
+  callbacks_->Refresh(id_);
+  validated_ = false;
+
+  return HWC2::Error::None;
+}
+
 }  // namespace sdm
diff --git a/composer/hwc_display_pluggable.h b/composer/hwc_display_pluggable.h
index b61b24e..8855f0e 100644
--- a/composer/hwc_display_pluggable.h
+++ b/composer/hwc_display_pluggable.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2020, 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
@@ -54,6 +54,7 @@
                                        RenderIntent *out_intents);
   virtual HWC2::Error SetColorMode(ColorMode mode);
   virtual HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
+  virtual HWC2::Error SetColorTransform(const float *matrix, android_color_transform_t hint);
   virtual HWC2::Error UpdatePowerMode(HWC2::PowerMode mode);
 
  private:
@@ -68,6 +69,7 @@
   DisplayNullExternal display_null_;
   int underscan_width_ = 0;
   int underscan_height_ = 0;
+  bool has_color_tranform_ = false;
 };
 
 }  // namespace sdm
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index 661ff03..3a9893f 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -61,6 +61,7 @@
 Locker HWCSession::power_state_[HWCCallbacks::kNumDisplays];
 Locker HWCSession::hdr_locker_[HWCCallbacks::kNumDisplays];
 Locker HWCSession::display_config_locker_;
+Locker HWCSession::system_locker_;
 static const int kSolidFillDelay = 100 * 1000;
 int HWCSession::null_display_mode_ = 0;
 static const uint32_t kBrightnessScaleMax = 100;
@@ -738,6 +739,7 @@
   auto status = HWC2::Error::BadDisplay;
   DTRACE_SCOPED();
 
+  SCOPE_LOCK(system_locker_);
   if (display >= HWCCallbacks::kNumDisplays) {
     DLOGW("Invalid Display : display = %" PRIu64, display);
     return HWC2_ERROR_BAD_DISPLAY;
@@ -2843,6 +2845,7 @@
   DLOGI("Notify hotplug display disconnected: client id = %d", UINT32(client_id));
   callbacks_.Hotplug(client_id, HWC2::Connection::Disconnected);
 
+  SCOPE_LOCK(system_locker_);
   {
     SEQUENCE_WAIT_SCOPE_LOCK(locker_[client_id]);
     auto &hwc_display = hwc_display_[client_id];
@@ -3168,7 +3171,7 @@
   }
 
   if (display != HWC_DISPLAY_PRIMARY) {
-    return HWC2_ERROR_BAD_DISPLAY;
+    return HWC2_ERROR_UNSUPPORTED;
   }
 
   HWCDisplay *hwc_display = hwc_display_[display];
@@ -3195,7 +3198,7 @@
   }
 
   if (display != HWC_DISPLAY_PRIMARY) {
-    return HWC2_ERROR_BAD_DISPLAY;
+    return HWC2_ERROR_UNSUPPORTED;
   }
 
   int external_dpy_index = GetDisplayIndex(qdutils::DISPLAY_EXTERNAL);
@@ -3220,7 +3223,7 @@
   }
 
   if (display != HWC_DISPLAY_PRIMARY) {
-    return HWC2_ERROR_BAD_DISPLAY;
+    return HWC2_ERROR_UNSUPPORTED;
   }
 
   return CallDisplayFunction(display, &HWCDisplay::GetReadbackBufferFence, release_fence);
@@ -3457,6 +3460,7 @@
     }
     SCOPE_LOCK(locker_[i]);
     hwc_display_[i]->NotifyClientStatus(connected);
+    hwc_display_[i]->SetVsyncEnabled(HWC2::Vsync::Disable);
   }
 }
 
diff --git a/composer/hwc_session.h b/composer/hwc_session.h
index 0ba7000..6327685 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -297,6 +297,7 @@
   static Locker power_state_[HWCCallbacks::kNumDisplays];
   static Locker hdr_locker_[HWCCallbacks::kNumDisplays];
   static Locker display_config_locker_;
+  static Locker system_locker_;
 
  private:
   class CWB {
diff --git a/gralloc/gr_adreno_info.cpp b/gralloc/gr_adreno_info.cpp
index 2b82dc6..63b03d7 100644
--- a/gralloc/gr_adreno_info.cpp
+++ b/gralloc/gr_adreno_info.cpp
@@ -77,6 +77,12 @@
   } else {
     ALOGE(" Failed to load libadreno_utils.so");
   }
+  char property[PROPERTY_VALUE_MAX];
+  property_get(DISABLE_UBWC_PROP, property, "0");
+  if (!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+      !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+     gfx_ubwc_disable_ = true;
+  }
 }
 
 AdrenoMemInfo::~AdrenoMemInfo() {
@@ -86,7 +92,6 @@
 }
 
 void AdrenoMemInfo::AdrenoSetProperties(gralloc::GrallocProperties props) {
-  gfx_ubwc_disable_ = props.ubwc_disable;
   gfx_ahardware_buffer_disable_ = props.ahardware_buffer_disable;
 }
 
diff --git a/gralloc/gr_buf_mgr.cpp b/gralloc/gr_buf_mgr.cpp
index cfb0a9f..1774ae9 100644
--- a/gralloc/gr_buf_mgr.cpp
+++ b/gralloc/gr_buf_mgr.cpp
@@ -32,7 +32,7 @@
 #include <string>
 #include <utility>
 #include <vector>
-
+#include <fstream>
 #include "gr_adreno_info.h"
 #include "gr_buf_descriptor.h"
 #include "gr_priv_handle.h"
@@ -701,6 +701,11 @@
   hnd->base_metadata = 0;
   hnd->gpuaddr = 0;
   RegisterHandleLocked(hnd, ion_handle, ion_handle_meta);
+  allocated_ += hnd->size;
+  if (allocated_ >=  kAllocThreshold) {
+    kAllocThreshold += kMemoryOffset;
+    BuffersDump();
+  }
   return Error::NONE;
 }
 
@@ -760,6 +765,9 @@
     if (buf->DecRef()) {
       handles_map_.erase(hnd);
       // Unmap, close ion handle and close fd
+      if (allocated_ > 0) {
+        allocated_ -= hnd->size;
+      }
       FreeBuffer(buf);
     }
   }
@@ -980,6 +988,46 @@
   return Error::NONE;
 }
 
+void BufferManager:: BuffersDump() {
+  char timeStamp[32];
+  char hms[32];
+  uint64_t millis;
+  struct timeval tv;
+  struct tm ptm;
+
+  gettimeofday(&tv, NULL);
+  localtime_r(&tv.tv_sec, &ptm);
+  strftime (hms, sizeof (hms), "%H:%M:%S", &ptm);
+  millis = tv.tv_usec / 1000;
+  snprintf(timeStamp, sizeof(timeStamp), "Timestamp: %s.%03" PRIu64, hms, millis);
+
+  std::fstream fs;
+  fs.open(file_dump_.kDumpFile, std::ios::app);
+  if (!fs) {
+    return;
+  }
+  fs << "============================" << std::endl;
+  fs << timeStamp << std::endl;
+  fs << "Total layers = " << handles_map_.size() << std::endl;
+  uint64_t totalAllocationSize = 0;
+  for (auto it : handles_map_) {
+    auto buf = it.second;
+    auto hnd = buf->handle;
+    auto metadata = reinterpret_cast<MetaData_t *>(hnd->base_metadata);
+    fs  << std::setw(80) << "Client:" << (metadata ? metadata->name: "No name");
+    fs  << std::setw(20) << "WxH:" << std::setw(4) << hnd->width << " x "
+        << std::setw(4) << hnd->height;
+    fs  << std::setw(20) << "Size: " << std::setw(9) << hnd->size <<  std::endl;
+    totalAllocationSize += hnd->size;
+  }
+  fs << "Total allocation  = " << totalAllocationSize/1024 << "KiB" << std::endl;
+  file_dump_.position = fs.tellp();
+  if (file_dump_.position > (20 * 1024 * 1024)) {
+    file_dump_.position = 0;
+  }
+  fs.close();
+}
+
 Error BufferManager::Dump(std::ostringstream *os) {
   std::lock_guard<std::mutex> buffer_lock(buffer_lock_);
   for (auto it : handles_map_) {
diff --git a/gralloc/gr_buf_mgr.h b/gralloc/gr_buf_mgr.h
index 998982f..dc3c297 100644
--- a/gralloc/gr_buf_mgr.h
+++ b/gralloc/gr_buf_mgr.h
@@ -46,6 +46,7 @@
   Error LockBuffer(const private_handle_t *hnd, uint64_t usage);
   Error UnlockBuffer(const private_handle_t *hnd);
   Error Dump(std::ostringstream *os);
+  void BuffersDump();
   Error ValidateBufferSize(private_handle_t const *hnd, BufferInfo info);
   Error IsBufferImported(const private_handle_t *hnd);
   static BufferManager *GetInstance();
@@ -97,6 +98,13 @@
   std::mutex buffer_lock_;
   std::unordered_map<const private_handle_t *, std::shared_ptr<Buffer>> handles_map_ = {};
   std::atomic<uint64_t> next_id_;
+  uint64_t allocated_ = 0;
+  uint64_t kAllocThreshold = (uint64_t)2*1024*1024*1024;
+  uint64_t kMemoryOffset = 50*1024*1024;
+  struct {
+    const char *kDumpFile = "/data/misc/wmtrace/bufferdump.txt";
+    uint64_t position = 0;
+  } file_dump_;
 };
 
 }  // namespace gralloc
diff --git a/gralloc/gr_utils.cpp b/gralloc/gr_utils.cpp
index 22211dc..7a1d363 100644
--- a/gralloc/gr_utils.cpp
+++ b/gralloc/gr_utils.cpp
@@ -1341,8 +1341,8 @@
       gr_format = HAL_PIXEL_FORMAT_RGBA_8888;
     } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
       // If no other usage flags are detected, default the
-      // flexible YUV format to YCbCr_420_SP
-      gr_format = HAL_PIXEL_FORMAT_YCbCr_420_SP;
+      // flexible YUV format to YCrCb_420_SP
+      gr_format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
     }
   }
 
diff --git a/sdm/include/utils/fence.h b/sdm/include/utils/fence.h
index 2b183e7..4ce8308 100644
--- a/sdm/include/utils/fence.h
+++ b/sdm/include/utils/fence.h
@@ -78,6 +78,9 @@
 
   static shared_ptr<Fence> Merge(const shared_ptr<Fence> &fence1, const shared_ptr<Fence> &fence2);
 
+  static shared_ptr<Fence> Merge(const std::vector<shared_ptr<Fence>> &fences,
+                                 bool ignore_signaled);
+
   // Wait on null fence will return success.
   static DisplayError Wait(const shared_ptr<Fence> &fence);
   static DisplayError Wait(const shared_ptr<Fence> &fence, int timeout);
diff --git a/sdm/libs/utils/fence.cpp b/sdm/libs/utils/fence.cpp
index 24ad1c0..7080d36 100644
--- a/sdm/libs/utils/fence.cpp
+++ b/sdm/libs/utils/fence.cpp
@@ -97,6 +97,21 @@
   return Create(merged, name);
 }
 
+shared_ptr<Fence> Fence::Merge(const std::vector<shared_ptr<Fence>> &fences, bool ignore_signaled) {
+  ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
+
+  shared_ptr<Fence> merged_fence = nullptr;
+  for (auto &fence : fences) {
+    if (ignore_signaled && (Fence::Wait(fence, 0) == kErrorNone)) {
+      continue;
+    }
+
+    merged_fence = Fence::Merge(fence, merged_fence);
+  }
+
+  return merged_fence;
+}
+
 DisplayError Fence::Wait(const shared_ptr<Fence> &fence) {
   ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);