Merge "sdm: Change log level to warning"
diff --git a/Android.mk b/Android.mk
index 3471e0a..aa34895 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,10 +1,9 @@
-ifneq ($(TARGET_DISABLE_DISPLAY),true)
 sdm-libs := sdm/libs
-display-hals := include $(sdm-libs)/utils $(sdm-libs)/core libdebug
+display-hals := include $(sdm-libs)/utils $(sdm-libs)/core libdebug gpu_tonemapper
 
 ifneq ($(TARGET_IS_HEADLESS), true)
     display-hals += libcopybit liblight libmemtrack hdmi_cec \
-                    gpu_tonemapper libdrmutils
+                    libdrmutils
 endif
 
 display-hals += gralloc
@@ -18,4 +17,3 @@
     include $(call all-named-subdir-makefiles,$(display-hals))
 endif
 endif
-endif #TARGET_DISABLE_DISPLAY
diff --git a/composer/Android.mk b/composer/Android.mk
index 9278fc2..306a7dc 100644
--- a/composer/Android.mk
+++ b/composer/Android.mk
@@ -21,7 +21,7 @@
                                  liblog libfmq libhardware_legacy \
                                  libsdmcore libqservice libqdutils libqdMetaData \
                                  libdisplaydebug libsdmutils libgrallocutils libui \
-                                 libEGL libGLESv2 libGLESv3 \
+                                 libgpu_tonemapper libEGL libGLESv2 libGLESv3 \
                                  vendor.qti.hardware.display.composer@1.0 \
                                  vendor.qti.hardware.display.composer@2.0 \
                                  android.hardware.graphics.composer@2.1 \
@@ -45,12 +45,8 @@
                                  vendor.display.config@1.10 \
                                  vendor.display.config@1.11 \
                                  vendor.display.config@1.12 \
-                                 vendor.display.config@1.13
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-    LOCAL_SHARED_LIBRARIES += libgpu_tonemapper
-endif
-
+                                 vendor.display.config@1.13 \
+                                 vendor.display.config@1.14
 
 LOCAL_SRC_FILES               := QtiComposer.cpp QtiComposerClient.cpp service.cpp \
                                  QtiComposerHandleImporter.cpp \
@@ -77,7 +73,9 @@
                                  hwc_display_virtual_gpu.cpp \
                                  gl_common.cpp \
                                  gl_color_convert.cpp \
-                                 gl_color_convert_impl.cpp
+                                 gl_color_convert_impl.cpp \
+                                 gl_layer_stitch.cpp \
+                                 gl_layer_stitch_impl.cpp
 
 LOCAL_INIT_RC                 := vendor.qti.hardware.display.composer-service.rc
 LOCAL_VINTF_FRAGMENTS         := vendor.qti.hardware.display.composer-service.xml
diff --git a/composer/QtiComposerClient.cpp b/composer/QtiComposerClient.cpp
index 9b66951..253978d 100644
--- a/composer/QtiComposerClient.cpp
+++ b/composer/QtiComposerClient.cpp
@@ -134,7 +134,8 @@
   }
 
   auto ret = client->mCallback->onHotplug(display, connect);
-  ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str());
+  ALOGW_IF(!ret.isOk(), "failed to send onHotplug: %s. SF likely unavailable.",
+           ret.description().c_str());
 
   if (connect == composer_V2_1::IComposerCallback::Connection::DISCONNECTED) {
     // Trigger refresh to make sure disconnect event received/updated properly by SurfaceFlinger.
@@ -152,14 +153,16 @@
 void QtiComposerClient::onRefresh(hwc2_callback_data_t callbackData, hwc2_display_t display) {
   auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
   auto ret = client->mCallback->onRefresh(display);
-  ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str());
+  ALOGW_IF(!ret.isOk(), "failed to send onRefresh: %s. SF likely unavailable.",
+           ret.description().c_str());
 }
 
 void QtiComposerClient::onVsync(hwc2_callback_data_t callbackData, hwc2_display_t display,
                                   int64_t timestamp) {
   auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
   auto ret = client->mCallback->onVsync(display, timestamp);
-  ALOGI_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str());
+  ALOGW_IF(!ret.isOk(), "failed to send onVsync: %s. SF likely unavailable.",
+           ret.description().c_str());
 }
 
 // convert fenceFd to or from hidl_handle
@@ -1724,10 +1727,45 @@
     return false;
   }
 
-  // SetLayerPerFrameMetadataBlobs is not supported
-  auto err = Error::UNSUPPORTED;
-  mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  uint32_t numBlobs = read();
+  length--;
+  std::vector<IComposerClient::PerFrameMetadataBlob> metadata;
 
+  for (size_t i = 0; i < numBlobs; i++) {
+    IComposerClient::PerFrameMetadataKey key =
+      static_cast<IComposerClient::PerFrameMetadataKey>(readSigned());
+    uint32_t blobSize = read();
+    length -= 2;
+
+    if (length * sizeof(uint32_t) < blobSize) {
+      return false;
+    }
+
+    metadata.push_back({key, std::vector<uint8_t>()});
+    IComposerClient::PerFrameMetadataBlob& metadataBlob = metadata.back();
+    metadataBlob.blob.resize(blobSize);
+    readBlob(blobSize, metadataBlob.blob.data());
+  }
+
+  std::vector<int32_t> keys;
+  std::vector<uint32_t> sizes_of_metablob_;
+  std::vector<uint8_t> blob_of_data_;
+  keys.reserve(metadata.size());
+  sizes_of_metablob_.reserve(metadata.size());
+  for (const auto& m : metadata) {
+    keys.push_back(static_cast<int32_t>(m.key));
+    sizes_of_metablob_.push_back(m.blob.size());
+    for (uint8_t i = 0; i < m.blob.size(); i++) {
+      blob_of_data_.push_back(m.blob[i]);
+    }
+  }
+  auto err = mClient.hwc_session_->SetLayerPerFrameMetadataBlobs(mDisplay, mLayer, metadata.size(),
+                                                                 keys.data(),
+                                                                 sizes_of_metablob_.data(),
+                                                                 blob_of_data_.data());
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
   return true;
 }
 
diff --git a/composer/QtiComposerCommandBuffer.h b/composer/QtiComposerCommandBuffer.h
index b352670..5461c56 100644
--- a/composer/QtiComposerCommandBuffer.h
+++ b/composer/QtiComposerCommandBuffer.h
@@ -763,6 +763,13 @@
     return (static_cast<uint64_t>(hi) << 32) | lo;
   }
 
+  void readBlob(uint32_t size, void* blob) {
+    memcpy(blob, &mData[mDataRead], size);
+    uint32_t numElements = size / sizeof(uint32_t);
+    mDataRead += numElements;
+    mDataRead += (size - numElements * sizeof(uint32_t) != 0) ? 1 : 0;
+  }
+
   IQtiComposerClient::Color readColor() {
     uint32_t val = read();
     return IQtiComposerClient::Color{
diff --git a/composer/display_null.h b/composer/display_null.h
index 24fc00c..7222faa 100644
--- a/composer/display_null.h
+++ b/composer/display_null.h
@@ -95,6 +95,7 @@
   MAKE_NO_OP(SetCursorPosition(int, int))
   MAKE_NO_OP(SetRefreshRate(uint32_t, bool))
   MAKE_NO_OP(GetPanelBrightness(float *))
+  MAKE_NO_OP(GetPanelMaxBrightness(uint32_t *))
   MAKE_NO_OP(GetRefreshRate(uint32_t *))
   MAKE_NO_OP(SetVSyncState(bool))
   MAKE_NO_OP(SetMixerResolution(uint32_t, uint32_t))
diff --git a/composer/gl_color_convert.cpp b/composer/gl_color_convert.cpp
index 03f7377..f398059 100644
--- a/composer/gl_color_convert.cpp
+++ b/composer/gl_color_convert.cpp
@@ -35,7 +35,7 @@
 namespace sdm {
 
 GLColorConvert* GLColorConvert::GetInstance(GLRenderTarget target, bool secure) {
-  GLColorConvertImpl* color_convert =  new GLColorConvertImpl(target, secure);
+  GLColorConvertImpl* color_convert = new GLColorConvertImpl(target, secure);
   if (color_convert == nullptr) {
     DLOGE("Failed to create color convert instance for %d target %d secure", target, secure);
     return nullptr;
diff --git a/composer/gl_color_convert.h b/composer/gl_color_convert.h
index 2080a97..a4c31ce 100644
--- a/composer/gl_color_convert.h
+++ b/composer/gl_color_convert.h
@@ -31,6 +31,7 @@
 #define __GL_COLOR_CONVERT_H__
 
 #include <gralloc_priv.h>
+#include "gl_common.h"
 
 namespace sdm {
 
@@ -39,13 +40,6 @@
   kTargetYUV,
 };
 
-struct GLRect {
-  float left = 0.0f;
-  float top = 0.0f;
-  float right = 0.0f;
-  float bottom = 0.0f;
-};
-
 class GLColorConvert {
  public:
   static GLColorConvert* GetInstance(GLRenderTarget target, bool secure);
diff --git a/composer/gl_color_convert_impl.cpp b/composer/gl_color_convert_impl.cpp
index fb5d060..9aa22e1 100644
--- a/composer/gl_color_convert_impl.cpp
+++ b/composer/gl_color_convert_impl.cpp
@@ -162,7 +162,7 @@
   SetProgram(ctx_.program_id);
 
   SetSourceBuffer(src_hnd);
-  SetDestinationBuffer(dst_hnd);
+  SetDestinationBuffer(dst_hnd, dst_rect);
 
   glEnableVertexAttribArray(0);
   glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, kFullScreenVertices);
diff --git a/composer/gl_common.cpp b/composer/gl_common.cpp
index d45b5d9..aa3bc45 100644
--- a/composer/gl_common.cpp
+++ b/composer/gl_common.cpp
@@ -97,17 +97,19 @@
   }
 }
 
-void GLCommon::SetDestinationBuffer(const private_handle_t *dst_hnd) {
+void GLCommon::SetDestinationBuffer(const private_handle_t *dst_hnd, const GLRect &dst_rect) {
   DTRACE_SCOPED();
   EGLImageBuffer *dst_buffer = image_wrapper_.wrap(reinterpret_cast<const void *>(dst_hnd));
 
   if (dst_buffer) {
     GL(glBindFramebuffer(GL_FRAMEBUFFER, dst_buffer->getFramebuffer()));
-    GL(glViewport(0, 0, dst_buffer->getWidth(), dst_buffer->getHeight()));
+    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));
   }
 }
 
-int GLCommon::WaitOnInputFence(const int in_fence_fd) {
+int GLCommon::WaitOnInputFence(int in_fence_fd) {
   DTRACE_SCOPED();
   EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, in_fence_fd, EGL_NONE};
   EGLSyncKHR sync = eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID,
@@ -145,12 +147,16 @@
   return fd;
 }
 
-void GLCommon::DestroyContext(const GLContext* ctx) {
+void GLCommon::DestroyContext(GLContext* ctx) {
   DTRACE_SCOPED();
+
+  // Clear egl image buffers.
+  image_wrapper_.Deinit();
+
+  EGL(DeleteProgram(ctx->program_id));
   EGL(eglMakeCurrent(ctx->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
   EGL(eglDestroySurface(ctx->egl_display, ctx->egl_surface));
   EGL(eglDestroyContext(ctx->egl_display, ctx->egl_context));
-  EGL(DeleteProgram(ctx->program_id));
   EGL(eglTerminate(ctx->egl_display));
 }
 
diff --git a/composer/gl_common.h b/composer/gl_common.h
index 4089e87..c77988b 100644
--- a/composer/gl_common.h
+++ b/composer/gl_common.h
@@ -37,6 +37,13 @@
 
 namespace sdm {
 
+struct GLRect {
+  float left = 0.0f;
+  float top = 0.0f;
+  float right = 0.0f;
+  float bottom = 0.0f;
+};
+
 struct GLContext {
   EGLDisplay egl_display = EGL_NO_DISPLAY;
   EGLContext egl_context = EGL_NO_CONTEXT;
@@ -51,11 +58,11 @@
   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);
+  virtual void SetDestinationBuffer(const private_handle_t *dst_hnd, const GLRect &dst_rect);
   virtual void SetSourceBuffer(const private_handle_t *src_hnd);
-  virtual void DestroyContext(const GLContext *ctx);
+  virtual void DestroyContext(GLContext *ctx);
   virtual void DeleteProgram(uint32_t id);
-  virtual int WaitOnInputFence(const int in_fence_fd);
+  virtual int WaitOnInputFence(int in_fence_fd);
   virtual int CreateOutputFence();
 
  protected:
diff --git a/composer/gl_layer_stitch.cpp b/composer/gl_layer_stitch.cpp
new file mode 100644
index 0000000..4d54a2c
--- /dev/null
+++ b/composer/gl_layer_stitch.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019, 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 "gl_layer_stitch_impl.h"
+#include "gl_layer_stitch.h"
+
+#define __CLASS__ "GLLayerStitch"
+
+namespace sdm {
+
+GLLayerStitch* GLLayerStitch::GetInstance(bool secure) {
+  GLLayerStitchImpl *layer_stitch = new GLLayerStitchImpl(secure);
+  if (layer_stitch == nullptr) {
+    DLOGE("Failed to create layer stitch instance. secure: %d", secure);
+    return nullptr;
+  }
+
+  int status = layer_stitch->Init();
+  if (status != 0) {
+    DLOGE("Failed to initialize GL layer stitch instance %d", status);
+    delete layer_stitch;
+    return nullptr;
+  }
+
+  DLOGI("Created instance successfully");
+
+  return layer_stitch;
+}
+
+void GLLayerStitch::Destroy(GLLayerStitch *intf) {
+  GLLayerStitchImpl *layer_stitch = static_cast<GLLayerStitchImpl *>(intf);
+  if (layer_stitch->Deinit() != 0) {
+    DLOGE("De Init failed");
+  }
+
+  delete layer_stitch;
+}
+
+}  // namespace sdm
diff --git a/composer/gl_layer_stitch.h b/composer/gl_layer_stitch.h
new file mode 100644
index 0000000..35eb92d
--- /dev/null
+++ b/composer/gl_layer_stitch.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019, 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 __GL_LAYER_STITCH_H__
+#define __GL_LAYER_STITCH_H__
+
+#include <gralloc_priv.h>
+#include "gl_common.h"
+
+namespace sdm {
+
+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, int src_acquire_fence_fd,
+                   int dst_acquire_fence_fd, int *release_fence_fd) = 0;
+ protected:
+  virtual ~GLLayerStitch() { }
+};
+
+}  // namespace sdm
+
+#endif  // __GL_LAYER_STITCH_H__
diff --git a/composer/gl_layer_stitch_impl.cpp b/composer/gl_layer_stitch_impl.cpp
new file mode 100644
index 0000000..f8e33cd
--- /dev/null
+++ b/composer/gl_layer_stitch_impl.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2019, 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 "gl_layer_stitch_impl.h"
+
+#define __CLASS__ "GLLayerStitchImpl"
+
+namespace sdm {
+
+const float kFullScreenVertices[] = {
+  -1.0f,  3.0f,
+  -1.0f, -1.0f,
+  3.0f, -1.0f
+};
+
+const float kFullScreenTexCoords[] = {
+  0.0f, 2.0f,
+  0.0f, 0.0f,
+  2.0f, 0.0f
+};
+
+const char *kVertexShader1 = ""
+  "#version 300 es                                                       \n"
+  "precision highp float;                                                \n"
+  "layout(location = 0) in vec2 in_pos;                                  \n"
+  "layout(location = 1) in vec2 in_uv;                                   \n"
+  "                                                                      \n"
+  "out vec2 uv;                                                          \n"
+  "                                                                      \n"
+  "void main()                                                           \n"
+  "{                                                                     \n"
+  "    gl_Position = vec4(in_pos, 0.0, 1.0);                             \n"
+  "    uv = in_uv;                                                       \n"
+  "}                                                                     \n";
+
+const char *kConvertRenderRGBShader = ""
+  "precision highp float;                                                \n"
+  "                                                                      \n"
+  "layout(binding = 0) uniform sampler2D u_sTexture;                     \n"
+  "                                                                      \n"
+  "in vec2 uv;                                                           \n"
+  "out vec4 color;                                                       \n"
+  "                                                                      \n"
+  "void main()                                                           \n"
+  "{                                                                     \n"
+  "    color = texture(u_sTexture, uv);                                  \n"
+  "}                                                                     \n";
+
+int GLLayerStitchImpl::CreateContext(bool secure) {
+  ctx_.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+  EGL(eglBindAPI(EGL_OPENGL_ES_API));
+
+  // Initialize current display.
+  EGL(eglInitialize(ctx_.egl_display, nullptr, nullptr));
+
+  // Get attributes corresponing to render target.
+  // Describes Framebuffer attributes like buffer depth, color space etc;
+  EGLConfig eglConfig;
+  int numConfig = 0;
+  EGLint eglConfigAttribList[] = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+                                  EGL_RED_SIZE,     8,
+                                  EGL_GREEN_SIZE,   8,
+                                  EGL_BLUE_SIZE,    8,
+                                  EGL_ALPHA_SIZE,   8,
+                                  EGL_NONE};
+  EGL(eglChooseConfig(ctx_.egl_display, eglConfigAttribList, &eglConfig, 1, &numConfig));
+
+  // When GPU runs in protected context it can read from
+  //  - Protected sources
+  //  - UnProtected source
+  // and writes into Protected buffer.
+  // VS in UnProtected context it can read/write happen from/to Unprotected sources.
+  EGLint egl_contextAttribList[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
+                                    secure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+                                    secure ? EGL_TRUE : EGL_NONE,
+                                    EGL_NONE};
+  ctx_.egl_context = eglCreateContext(ctx_.egl_display, eglConfig, NULL, egl_contextAttribList);
+
+  // eglCreatePbufferSurface creates an off-screen pixel buffer surface and returns its handle
+  EGLint egl_surfaceAttribList[] = {EGL_WIDTH, 1,
+                                    EGL_HEIGHT, 1,
+                                    secure ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+                                    secure ? EGL_TRUE : EGL_NONE,
+                                    EGL_NONE};
+  ctx_.egl_surface = eglCreatePbufferSurface(ctx_.egl_display, eglConfig, egl_surfaceAttribList);
+
+  // eglMakeCurrent attaches rendering context to rendering surface.
+  MakeCurrent(&ctx_);
+
+  DLOGI("Created context = %p", (void *)(&ctx_.egl_context));
+
+  // Load Vertex and Fragment shaders.
+  const char *fragment_shaders[2] = { };
+  int count = 0;
+  const char *version = "#version 300 es\n";
+
+  fragment_shaders[count++] = version;
+
+  // ToDo: Add support to yuv_to_rgb shader.
+  fragment_shaders[count++] = kConvertRenderRGBShader;
+
+  ctx_.program_id = LoadProgram(1, &kVertexShader1, count, fragment_shaders);
+
+  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,
+                            int src_acquire_fence_fd, int dst_acquire_fence_fd,
+                            int *release_fence_fd) {
+  DTRACE_SCOPED();
+  // eglMakeCurrent attaches rendering context to rendering surface.
+  MakeCurrent(&ctx_);
+
+  SetProgram(ctx_.program_id);
+
+  SetSourceBuffer(src_hnd);
+  SetDestinationBuffer(dst_hnd, dst_rect);
+
+  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);
+
+  int in_fence_fd = sync_merge(__CLASS__, src_acquire_fence_fd, dst_acquire_fence_fd);
+  if (in_fence_fd >= 0) {
+    WaitOnInputFence(in_fence_fd);
+  }
+
+  // Create output fence for client to wait on.
+  *release_fence_fd = CreateOutputFence();
+
+  return 0;
+}
+
+int GLLayerStitchImpl::Init() {
+  return CreateContext(secure_);
+}
+
+int GLLayerStitchImpl::Deinit() {
+  MakeCurrent(&ctx_);
+  DestroyContext(&ctx_);
+
+  return 0;
+}
+
+GLLayerStitchImpl::~GLLayerStitchImpl() {}
+
+GLLayerStitchImpl::GLLayerStitchImpl(bool secure) {
+  secure_ = secure;
+}
+
+}  // namespace sdm
+
diff --git a/composer/gl_layer_stitch_impl.h b/composer/gl_layer_stitch_impl.h
new file mode 100644
index 0000000..f4d438d
--- /dev/null
+++ b/composer/gl_layer_stitch_impl.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2019, 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 __GL_LAYER_STITCH_IMPL_H__
+#define __GL_LAYER_STITCH_IMPL_H__
+
+#include <sync/sync.h>
+
+#include "gl_layer_stitch.h"
+#include "gl_common.h"
+
+namespace sdm {
+
+class GLLayerStitchImpl : public GLLayerStitch, public GLCommon {
+ 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,
+                   int src_acquire_fence_fd, int dst_acquire_fence_fd, int *release_fence_fd);
+  virtual int CreateContext(bool secure);
+  virtual int Init();
+  virtual int Deinit();
+ private:
+  bool secure_ = false;
+  GLContext ctx_;
+};
+
+}  // namespace sdm
+
+#endif  // __GL_LAYER_STITCH_IMPL_H__
diff --git a/composer/hwc_buffer_allocator.cpp b/composer/hwc_buffer_allocator.cpp
index f9fef97..1b033db 100644
--- a/composer/hwc_buffer_allocator.cpp
+++ b/composer/hwc_buffer_allocator.cpp
@@ -36,6 +36,7 @@
 #include "gr_utils.h"
 #include "hwc_buffer_allocator.h"
 #include "hwc_debugger.h"
+#include "hwc_layers.h"
 
 #define __CLASS__ "HWCBufferAllocator"
 
@@ -209,6 +210,7 @@
   alloc_buffer_info->aligned_height = UINT32(hnd->height);
   alloc_buffer_info->size = hnd->size;
   alloc_buffer_info->id = hnd->id;
+  alloc_buffer_info->format = HWCLayer::GetSDMFormat(hnd->format, hnd->flags);
 
   buffer_info->private_data = reinterpret_cast<void *>(hnd);
   return kErrorNone;
diff --git a/composer/hwc_buffer_sync_handler.cpp b/composer/hwc_buffer_sync_handler.cpp
index 7cab4c0..24c8336 100644
--- a/composer/hwc_buffer_sync_handler.cpp
+++ b/composer/hwc_buffer_sync_handler.cpp
@@ -49,7 +49,7 @@
   if (fd >= 0) {
     error = sync_wait(fd, timeout);
     if (error < 0) {
-      DLOGE("sync_wait() error on fd = %d, timeout = %dms. (errno = %d \"%s\")", fd, timeout, errno,
+      DLOGW("sync_wait() error on fd = %d, timeout = %dms. (errno = %d \"%s\")", fd, timeout, errno,
             strerror(errno));
       return kErrorTimeOut;
     }
diff --git a/composer/hwc_callbacks.cpp b/composer/hwc_callbacks.cpp
index 857716b..e36a60f 100644
--- a/composer/hwc_callbacks.cpp
+++ b/composer/hwc_callbacks.cpp
@@ -105,9 +105,6 @@
       return HWC2::Error::BadParameter;
   }
 
-  if (!pointer) {
-    return HWC2::Error::NoResources;
-  }
   return HWC2::Error::None;
 }
 
diff --git a/composer/hwc_display.cpp b/composer/hwc_display.cpp
index 9687858..94bce1f 100644
--- a/composer/hwc_display.cpp
+++ b/composer/hwc_display.cpp
@@ -1133,20 +1133,22 @@
   if (out_num_keys == nullptr) {
     return HWC2::Error::BadParameter;
   }
-  *out_num_keys = UINT32(PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL) + 1;
-  if (out_keys != nullptr) {
-    out_keys[0] = PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X;
-    out_keys[1] = PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y;
-    out_keys[2] = PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X;
-    out_keys[3] = PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y;
-    out_keys[4] = PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X;
-    out_keys[5] = PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y;
-    out_keys[6] = PerFrameMetadataKey::WHITE_POINT_X;
-    out_keys[7] = PerFrameMetadataKey::WHITE_POINT_Y;
-    out_keys[8] = PerFrameMetadataKey::MAX_LUMINANCE;
-    out_keys[9] = PerFrameMetadataKey::MIN_LUMINANCE;
-    out_keys[10] = PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL;
-    out_keys[11] = PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL;
+
+  DisplayConfigFixedInfo fixed_info = {};
+  display_intf_->GetConfig(&fixed_info);
+  uint32_t num_keys = 0;
+  if (fixed_info.hdr_plus_supported) {
+    num_keys = UINT32(PerFrameMetadataKey::HDR10_PLUS_SEI) + 1;
+  } else {
+    num_keys = UINT32(PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL) + 1;
+  }
+  if (out_keys == nullptr) {
+    *out_num_keys = num_keys;
+  } else {
+    uint32_t max_out_key_elements = std::min(*out_num_keys, num_keys);
+    for (int32_t i = 0; i < max_out_key_elements; i++) {
+      out_keys[i] = static_cast<PerFrameMetadataKey>(i);
+    }
   }
   return HWC2::Error::None;
 }
@@ -1282,8 +1284,16 @@
     } break;
     case kPanelDeadEvent:
     case kDisplayPowerResetEvent: {
-      SEQUENCE_WAIT_SCOPE_LOCK(HWCSession::locker_[id_]);
-      validated_ = false;
+      // Mutex scope
+      {
+        SEQUENCE_WAIT_SCOPE_LOCK(HWCSession::locker_[id_]);
+        validated_ = false;
+      }
+      // TODO(user): Following scenario need to be addressed
+      // If panel or HW is in bad state for either ESD or HWR, there is no acquired lock between
+      // this scope and call to DisplayPowerReset.
+      // Prepare or commit could operate on the display since locker_[id_] is free and most likely
+      // result in a failure since ESD/HWR has been requested during this time period.
       if (event_handler_) {
         event_handler_->DisplayPowerReset();
       } else {
@@ -1343,7 +1353,7 @@
     Layer *layer = hwc_layer->GetSDMLayer();
     LayerComposition &composition = layer->composition;
 
-    if (composition == kCompositionSDE) {
+    if (composition == kCompositionSDE || composition == kCompositionStitch) {
       layer_requests_[hwc_layer->GetId()] = HWC2::LayerRequest::ClearClientTarget;
     }
 
@@ -1494,13 +1504,29 @@
     return HWC2::Error::None;
   }
 
-  if (out_types == nullptr) {
-    // We support HDR10 and HLG
-    *out_num_types = 2;
+  uint32_t num_types = 0;
+  if (fixed_info.hdr_plus_supported) {
+    num_types = UINT32(Hdr::HDR10_PLUS) - 1;
   } else {
-    // HDR10 and HLG are supported
-    out_types[0] = HAL_HDR_HDR10;
-    out_types[1] = HAL_HDR_HLG;
+    num_types = UINT32(Hdr::HLG) - 1;
+  }
+
+  // We support HDR10, HLG and HDR10_PLUS.
+  if (out_types == nullptr) {
+    *out_num_types = num_types;
+  } else {
+    uint32_t max_out_types = std::min(*out_num_types, num_types);
+    int32_t type = static_cast<int32_t>(Hdr::DOLBY_VISION);
+    for (int32_t i = 0; i < max_out_types; i++) {
+      while (type == static_cast<int32_t>(Hdr::DOLBY_VISION) /* Skip list */) {
+        // Skip the type
+        type++;
+      }
+      if (type > (num_types + 1)) {
+        break;
+      }
+      out_types[i] = type++;
+    }
     *out_max_luminance = fixed_info.max_luminance;
     *out_max_average_luminance = fixed_info.average_luminance;
     *out_min_luminance = fixed_info.min_luminance;
diff --git a/composer/hwc_display.h b/composer/hwc_display.h
index 84a0581..6323847 100644
--- a/composer/hwc_display.h
+++ b/composer/hwc_display.h
@@ -44,6 +44,7 @@
 using android::hardware::graphics::common::V1_2::ColorMode;
 using android::hardware::graphics::common::V1_1::Dataspace;
 using android::hardware::graphics::common::V1_1::RenderIntent;
+using android::hardware::graphics::common::V1_2::Hdr;
 
 namespace sdm {
 
@@ -311,6 +312,9 @@
   virtual HWC2::Error GetPanelBrightness(float *brightness) {
     return HWC2::Error::Unsupported;
   }
+  virtual HWC2::Error GetPanelMaxBrightness(uint32_t *max_brightness_level) {
+    return HWC2::Error::Unsupported;
+  }
   virtual HWC2::Error GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs);
   virtual HWC2::Error GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
                                           int32_t *out_value);
diff --git a/composer/hwc_display_builtin.cpp b/composer/hwc_display_builtin.cpp
index 85cdda6..439170a 100644
--- a/composer/hwc_display_builtin.cpp
+++ b/composer/hwc_display_builtin.cpp
@@ -47,6 +47,13 @@
 
 namespace sdm {
 
+static void SetRect(LayerRect &src_rect, GLRect *target) {
+  target->left = src_rect.left;
+  target->top = src_rect.top;
+  target->right = src_rect.right;
+  target->bottom = src_rect.bottom;
+}
+
 int HWCDisplayBuiltIn::Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
                               HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
                               qService::QService *qservice, hwc2_display_t id, int32_t sdm_id,
@@ -96,7 +103,7 @@
     : HWCDisplay(core_intf, buffer_allocator, callbacks, event_handler, qservice, kBuiltIn, id,
                  sdm_id, DISPLAY_CLASS_BUILTIN),
       buffer_allocator_(buffer_allocator),
-      cpu_hint_(NULL) {
+      cpu_hint_(NULL), layer_stitch_task_(*this) {
 }
 
 int HWCDisplayBuiltIn::Init() {
@@ -129,6 +136,10 @@
 
   is_primary_ = display_intf_->IsPrimaryDisplay();
 
+  if (!InitLayerStitch()) {
+    DLOGW("Failed to initialize Layer Stitch context");
+  }
+
   return status;
 }
 
@@ -150,6 +161,10 @@
 
   // Fill in the remaining blanks in the layers and add them to the SDM layerstack
   BuildLayerStack();
+
+  // Add stitch layer to layer stack.
+  AppendStitchLayer();
+
   // Checks and replaces layer stack for solid fill
   SolidFillPrepare();
 
@@ -242,13 +257,52 @@
   return skip_commit;
 }
 
+HWC2::Error HWCDisplayBuiltIn::CommitStitchLayers() {
+  if (!validated_ || skip_commit_) {
+    return HWC2::Error::None;
+  }
+
+  if (disable_layer_stitch_) {
+    return HWC2::Error::None;
+  }
+
+  for (auto &layer : layer_stack_.layers) {
+    LayerComposition &composition = layer->composition;
+    if (composition != kCompositionStitch) {
+      continue;
+    }
+
+    LayerStitchStitchContext ctx = {};
+    // 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);
+    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_dst_rect, &ctx.dst_rect);
+    ctx.src_acquire_fence_fd = input_buffer.acquire_fence_fd;
+
+    layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeStitch, &ctx);
+
+    // Merge with current fence and close previous one.
+    int acquire_fence = sync_merge(__CLASS__, output_buffer.acquire_fence_fd, ctx.release_fence_fd);
+    CloseFd(&output_buffer.acquire_fence_fd);
+    CloseFd(&ctx.release_fence_fd);
+
+    output_buffer.acquire_fence_fd = acquire_fence;
+  }
+
+  return HWC2::Error::None;
+}
+
 HWC2::Error HWCDisplayBuiltIn::Present(int32_t *out_retire_fence) {
   auto status = HWC2::Error::None;
 
   DTRACE_SCOPED();
 
   if (!is_primary_ && active_secure_sessions_[kSecureDisplay]) {
-      return status;
+    return status;
   } else if (display_paused_) {
     DisplayError error = display_intf_->Flush(&layer_stack_);
     validated_ = false;
@@ -256,12 +310,26 @@
       DLOGE("Flush failed. Error = %d", error);
     }
   } else {
+    status = CommitStitchLayers();
+    if (status != HWC2::Error::None) {
+      DLOGE("Stitch failed: %d", status);
+      return status;
+    }
+
     status = CommitLayerStack();
     if (status == HWC2::Error::None) {
       HandleFrameOutput();
       SolidFillCommit();
       status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
     }
+
+    if (stitch_target_) {
+      // Close Stitch buffer acquire fence.
+      Layer *stitch_layer = stitch_target_->GetSDMLayer();
+      LayerBuffer &output_buffer = stitch_layer->input_buffer;
+      CloseFd(&output_buffer.acquire_fence_fd);
+      CloseFd(&output_buffer.release_fence_fd);
+    }
   }
 
   CloseFd(&output_buffer_.acquire_fence_fd);
@@ -943,6 +1011,15 @@
   return HWC2::Error::None;
 }
 
+HWC2::Error HWCDisplayBuiltIn::GetPanelMaxBrightness(uint32_t *max_brightness_level) {
+  DisplayError ret = display_intf_->GetPanelMaxBrightness(max_brightness_level);
+  if (ret != kErrorNone) {
+    return HWC2::Error::NoResources;
+  }
+
+  return HWC2::Error::None;
+}
+
 HWC2::Error HWCDisplayBuiltIn::SetBLScale(uint32_t level) {
   DisplayError ret = display_intf_->SetBLScale(level);
   if (ret != kErrorNone) {
@@ -989,4 +1066,142 @@
   return false;
 }
 
+int HWCDisplayBuiltIn::Deinit() {
+  // Destory color convert instance. This destroys thread and underlying GL resources.
+  if (gl_layer_stitch_) {
+    layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeDestroyInstance, nullptr);
+  }
+
+  return HWCDisplay::Deinit();
+}
+
+void HWCDisplayBuiltIn::OnTask(const LayerStitchTaskCode &task_code,
+                               SyncTask<LayerStitchTaskCode>::TaskContext *task_context) {
+  switch (task_code) {
+    case LayerStitchTaskCode::kCodeGetInstance: {
+        gl_layer_stitch_ = GLLayerStitch::GetInstance(false /* Non-secure */);
+      }
+      break;
+    case LayerStitchTaskCode::kCodeStitch: {
+        DTRACE_SCOPED();
+        LayerStitchStitchContext* ctx = reinterpret_cast<LayerStitchStitchContext*>(task_context);
+        gl_layer_stitch_->Blit(ctx->src_hnd, ctx->dst_hnd, ctx->src_rect, ctx->dst_rect,
+                               ctx->src_acquire_fence_fd, ctx->dst_acquire_fence_fd,
+                               &(ctx->release_fence_fd));
+      }
+      break;
+    case LayerStitchTaskCode::kCodeDestroyInstance: {
+        if (gl_layer_stitch_) {
+          GLLayerStitch::Destroy(gl_layer_stitch_);
+        }
+      }
+      break;
+  }
+}
+
+bool HWCDisplayBuiltIn::InitLayerStitch() {
+  if (!is_primary_) {
+    // Disable on all non-primary builtins.
+    DLOGI("Non-primary builtin.");
+    disable_layer_stitch_ = true;
+    return true;
+  }
+
+  // Disable by default.
+  int value = 1;
+  Debug::Get()->GetProperty(DISABLE_LAYER_STITCH, &value);
+  disable_layer_stitch_ = (value == 1);
+
+  if (disable_layer_stitch_) {
+    DLOGI("Layer Stitch Disabled !!!");
+    return true;
+  }
+
+  // Initialize stitch context. This will be non-secure.
+  layer_stitch_task_.PerformTask(LayerStitchTaskCode::kCodeGetInstance, nullptr);
+  if (gl_layer_stitch_ == nullptr) {
+    DLOGE("Failed to get LayerStitch Instance");
+    return false;
+  }
+
+  if (!AllocateStitchBuffer()) {
+    return true;
+  }
+
+  stitch_target_ = new HWCLayer(id_, static_cast<HWCBufferAllocator *>(buffer_allocator_));
+
+  // Populate buffer params and pvt handle.
+  InitStitchTarget();
+
+  DLOGI("Created LayerStitch instance: %p", gl_layer_stitch_);
+
+  return true;
+}
+
+bool HWCDisplayBuiltIn::AllocateStitchBuffer() {
+  // Buffer dimensions: FB width * (1.5 * height)
+
+  DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config_);
+  if (error != kErrorNone) {
+    DLOGE("Get frame buffer config failed. Error = %d", error);
+    return false;
+  }
+
+  BufferConfig &config = buffer_info_.buffer_config;
+  config.width = fb_config_.x_pixels;
+  config.height = fb_config_.y_pixels * kBufferHeightFactor;
+
+  // By default UBWC is enabled and below property is global enable/disable for all
+  // buffers allocated through gralloc , including framebuffer targets.
+  int ubwc_disabled = 0;
+  HWCDebugHandler::Get()->GetProperty(DISABLE_UBWC_PROP, &ubwc_disabled);
+  config.format = ubwc_disabled ? kFormatRGBA8888 : kFormatRGBA8888Ubwc;
+
+  config.gfx_client = true;
+
+  // Populate default params.
+  config.secure = false;
+  config.cache = false;
+  config.secure_camera = false;
+
+  error = buffer_allocator_->AllocateBuffer(&buffer_info_);
+
+  if (error != kErrorNone) {
+    DLOGE("Failed to allocate buffer. Error: %d", error);
+    return false;
+  }
+
+  return true;
+}
+
+void HWCDisplayBuiltIn::InitStitchTarget() {
+  LayerBuffer buffer = {};
+  buffer.planes[0].fd = buffer_info_.alloc_buffer_info.fd;
+  buffer.planes[0].offset = 0;
+  buffer.planes[0].stride = buffer_info_.alloc_buffer_info.stride;
+  buffer.size = buffer_info_.alloc_buffer_info.size;
+  buffer.handle_id = buffer_info_.alloc_buffer_info.id;
+  buffer.width = buffer_info_.alloc_buffer_info.aligned_width;
+  buffer.height = buffer_info_.alloc_buffer_info.aligned_height;
+  buffer.unaligned_width = fb_config_.x_pixels;
+  buffer.unaligned_height = fb_config_.y_pixels;
+  buffer.format = buffer_info_.alloc_buffer_info.format;
+
+  Layer *sdm_stitch_target = stitch_target_->GetSDMLayer();
+  sdm_stitch_target->composition = kCompositionStitchTarget;
+  sdm_stitch_target->input_buffer = buffer;
+  sdm_stitch_target->input_buffer.buffer_id = reinterpret_cast<uint64_t>(buffer_info_.private_data);
+}
+
+void HWCDisplayBuiltIn::AppendStitchLayer() {
+  if (disable_layer_stitch_) {
+    return;
+  }
+
+  // Append stitch target buffer to layer stack.
+  Layer *sdm_stitch_target = stitch_target_->GetSDMLayer();
+  sdm_stitch_target->composition = kCompositionStitchTarget;
+  layer_stack_.layers.push_back(sdm_stitch_target);
+}
+
 }  // namespace sdm
diff --git a/composer/hwc_display_builtin.h b/composer/hwc_display_builtin.h
index a3ed162..b1c0421 100644
--- a/composer/hwc_display_builtin.h
+++ b/composer/hwc_display_builtin.h
@@ -33,12 +33,37 @@
 #include <string>
 #include <vector>
 
+#include "utils/sync_task.h"
+#include "utils/constants.h"
 #include "cpuhint.h"
 #include "hwc_display.h"
+#include "hwc_layers.h"
+
+#include "gl_layer_stitch.h"
 
 namespace sdm {
 
-class HWCDisplayBuiltIn : public HWCDisplay {
+enum class LayerStitchTaskCode : int32_t {
+  kCodeGetInstance,
+  kCodeStitch,
+  kCodeDestroyInstance,
+};
+
+struct LayerStitchGetInstanceContext : public SyncTask<LayerStitchTaskCode>::TaskContext {
+  LayerBuffer *output_buffer = NULL;
+};
+
+struct LayerStitchStitchContext : public SyncTask<LayerStitchTaskCode>::TaskContext {
+  const private_handle_t* src_hnd = nullptr;
+  const private_handle_t* dst_hnd = nullptr;
+  GLRect src_rect = {};
+  GLRect dst_rect = {};
+  int src_acquire_fence_fd = -1;
+  int dst_acquire_fence_fd = -1;
+  int release_fence_fd = -1;
+};
+
+class HWCDisplayBuiltIn : public HWCDisplay, public SyncTask<LayerStitchTaskCode>::TaskHandler {
  public:
   enum {
     SET_METADATA_DYN_REFRESH_RATE,
@@ -91,6 +116,7 @@
   virtual HWC2::Error SetPendingRefresh();
   virtual HWC2::Error SetPanelBrightness(float brightness);
   virtual HWC2::Error GetPanelBrightness(float *brightness);
+  virtual HWC2::Error GetPanelMaxBrightness(uint32_t *max_brightness_level);
   virtual DisplayError TeardownConcurrentWriteback(void);
   virtual void SetFastPathComposition(bool enable) {
     fast_path_composition_ = enable && !readback_buffer_queued_;
@@ -101,6 +127,7 @@
   virtual HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
                                       int32_t dataspace, hwc_region_t damage);
   virtual bool IsSmartPanelConfig(uint32_t config_id);
+  virtual int Deinit();
 
  private:
   HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
@@ -120,6 +147,15 @@
   bool CanSkipCommit();
   DisplayError SetMixerResolution(uint32_t width, uint32_t height);
   DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+  HWC2::Error CommitStitchLayers();
+  void AppendStitchLayer();
+  bool InitLayerStitch();
+  void InitStitchTarget();
+  bool AllocateStitchBuffer();
+
+  // SyncTask methods.
+  void OnTask(const LayerStitchTaskCode &task_code,
+              SyncTask<LayerStitchTaskCode>::TaskContext *task_context);
 
   BufferAllocator *buffer_allocator_ = nullptr;
   CPUHint *cpu_hint_ = nullptr;
@@ -142,6 +178,12 @@
   bool frame_capture_buffer_queued_ = false;
   int frame_capture_status_ = -EAGAIN;
   bool is_primary_ = false;
+  bool disable_layer_stitch_ = false;
+  HWCLayer* stitch_target_ = nullptr;
+  SyncTask<LayerStitchTaskCode> layer_stitch_task_;
+  GLLayerStitch* gl_layer_stitch_ = nullptr;
+  BufferInfo buffer_info_ = {};
+  DisplayConfigVariableInfo fb_config_ = {};
 };
 
 }  // namespace sdm
diff --git a/composer/hwc_display_dummy.cpp b/composer/hwc_display_dummy.cpp
index eff0ed6..315a22c 100644
--- a/composer/hwc_display_dummy.cpp
+++ b/composer/hwc_display_dummy.cpp
@@ -59,6 +59,10 @@
   return HWC2::Error::None;
 }
 
+HWC2::Error HWCDisplayDummy::SetColorMode(ColorMode mode) {
+  return HWC2::Error::None;
+}
+
 HWCDisplayDummy::HWCDisplayDummy(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
                                  HWCCallbacks *callbacks, HWCDisplayEventHandler *event_handler,
                                  qService::QService *qservice, hwc2_display_t id,
diff --git a/composer/hwc_display_dummy.h b/composer/hwc_display_dummy.h
index bf28a03..8f78303 100644
--- a/composer/hwc_display_dummy.h
+++ b/composer/hwc_display_dummy.h
@@ -46,6 +46,7 @@
   virtual HWC2::Error Present(int32_t *out_retire_fence);
   virtual HWC2::Error GetActiveConfig(hwc2_config_t *out_config);
   virtual HWC2::Error UpdatePowerMode(HWC2::PowerMode mode);
+  virtual HWC2::Error SetColorMode(ColorMode mode);
 
  private:
   HWCDisplayDummy(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
diff --git a/composer/hwc_layers.cpp b/composer/hwc_layers.cpp
index 426c397..ee8207b 100644
--- a/composer/hwc_layers.cpp
+++ b/composer/hwc_layers.cpp
@@ -234,7 +234,7 @@
   if (!buffer) {
     if (client_requested_ == HWC2::Composition::Device ||
         client_requested_ == HWC2::Composition::Cursor) {
-      DLOGE("Invalid buffer handle: %p on layer: %d client requested comp type %d", buffer, id_,
+      DLOGW("Invalid buffer handle: %p on layer: %d client requested comp type %d", buffer, id_,
             client_requested_);
       ::close(acquire_fence);
       return HWC2::Error::BadParameter;
@@ -588,6 +588,8 @@
 HWC2::Error HWCLayer::SetLayerPerFrameMetadata(uint32_t num_elements,
                                                const PerFrameMetadataKey *keys,
                                                const float *metadata) {
+  auto old_mastering_display = layer_->input_buffer.color_metadata.masteringDisplayInfo;
+  auto old_content_light = layer_->input_buffer.color_metadata.contentLightLevel;
   auto &mastering_display = layer_->input_buffer.color_metadata.masteringDisplayInfo;
   auto &content_light = layer_->input_buffer.color_metadata.contentLightLevel;
   for (uint32_t i = 0; i < num_elements; i++) {
@@ -630,6 +632,51 @@
       case PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL:
         content_light.minPicAverageLightLevel = UINT32(metadata[i] * 10000);
         break;
+      default:
+       break;
+    }
+  }
+  if ((!SameConfig(&old_mastering_display, &mastering_display, UINT32(sizeof(MasteringDisplay)))) ||
+      (!SameConfig(&old_content_light, &content_light, UINT32(sizeof(ContentLightLevel))))) {
+    per_frame_hdr_metadata_ = true;
+    layer_->update_mask.set(kMetadataUpdate);
+    geometry_changes_ |= kDataspace;
+  }
+  return HWC2::Error::None;
+}
+
+HWC2::Error HWCLayer::SetLayerPerFrameMetadataBlobs(uint32_t num_elements,
+                                                    const PerFrameMetadataKey *keys,
+                                                    const uint32_t *sizes,
+                                                    const uint8_t* metadata) {
+  if (!keys || !sizes || !metadata) {
+    DLOGE("metadata or sizes or keys is null");
+    return HWC2::Error::BadParameter;
+  }
+
+  ColorMetaData &color_metadata = layer_->input_buffer.color_metadata;
+  for (uint32_t i = 0; i < num_elements; i++) {
+    switch (keys[i]) {
+      case PerFrameMetadataKey::HDR10_PLUS_SEI:
+        if (sizes[i] > HDR_DYNAMIC_META_DATA_SZ) {
+          DLOGE("Size of HDR10_PLUS_SEI = %d", sizes[i]);
+          return HWC2::Error::BadParameter;
+        }
+        per_frame_hdr_metadata_ = false;
+        // if dynamic metadata changes, store and set needs validate
+        if (!SameConfig(static_cast<const uint8_t*>(color_metadata.dynamicMetaDataPayload),
+                        metadata, sizes[i])) {
+          geometry_changes_ |= kDataspace;
+          color_metadata.dynamicMetaDataValid = true;
+          color_metadata.dynamicMetaDataLen = sizes[i];
+          std::memcpy(color_metadata.dynamicMetaDataPayload, metadata, sizes[i]);
+          per_frame_hdr_metadata_ = true;
+          layer_->update_mask.set(kMetadataUpdate);
+        }
+        break;
+      default:
+        DLOGW("Invalid key = %d", keys[i]);
+        return HWC2::Error::BadParameter;
     }
   }
   return HWC2::Error::None;
@@ -945,7 +992,9 @@
      use_color_metadata = true;
   }
 
-  if (use_color_metadata) {
+  // Since client has set PerFrameMetadata, dataspace will be valid
+  // so we can skip reading from ColorMetaData.
+  if (use_color_metadata && !per_frame_hdr_metadata_) {
     ColorMetaData new_metadata = {};
     if (sdm::SetCSC(handle, &new_metadata) == kErrorNone) {
       // If dataspace is KNOWN, overwrite the gralloc metadata CSC using the previously derived CSC
@@ -960,7 +1009,10 @@
           (layer_buffer->color_metadata.range != new_metadata.range)) {
         layer_->update_mask.set(kMetadataUpdate);
       }
-      if (new_metadata.dynamicMetaDataValid &&
+      DLOGV_IF(kTagClient, "Dynamic Metadata valid = %d size = %d",
+               layer_buffer->color_metadata.dynamicMetaDataValid,
+               layer_buffer->color_metadata.dynamicMetaDataLen);
+      if (layer_buffer->color_metadata.dynamicMetaDataValid &&
           !SameConfig(layer_buffer->color_metadata.dynamicMetaDataPayload,
           new_metadata.dynamicMetaDataPayload, HDR_DYNAMIC_META_DATA_SZ)) {
         layer_->update_mask.set(kMetadataUpdate);
diff --git a/composer/hwc_layers.h b/composer/hwc_layers.h
index ac6c21f..fc05433 100644
--- a/composer/hwc_layers.h
+++ b/composer/hwc_layers.h
@@ -33,7 +33,7 @@
 #include <hardware/hwcomposer2.h>
 #undef HWC2_INCLUDE_STRINGIFICATION
 #undef HWC2_USE_CPP11
-#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
 #include <vendor/qti/hardware/display/composer/2.0/IQtiComposerClient.h>
 #include <deque>
 #include <map>
@@ -42,7 +42,7 @@
 #include "hwc_buffer_allocator.h"
 
 using PerFrameMetadataKey =
-    android::hardware::graphics::composer::V2_2::IComposerClient::PerFrameMetadataKey;
+    android::hardware::graphics::composer::V2_3::IComposerClient::PerFrameMetadataKey;
 using vendor::qti::hardware::display::composer::V2_0::IQtiComposerClient;
 
 namespace sdm {
@@ -100,6 +100,8 @@
   HWC2::Error SetLayerVisibleRegion(hwc_region_t visible);
   HWC2::Error SetLayerPerFrameMetadata(uint32_t num_elements, const PerFrameMetadataKey *keys,
                                        const float *metadata);
+  HWC2::Error SetLayerPerFrameMetadataBlobs(uint32_t num_elements, const PerFrameMetadataKey *keys,
+                                            const uint32_t *sizes, const uint8_t* metadata);
   HWC2::Error SetLayerZOrder(uint32_t z);
   HWC2::Error SetLayerType(IQtiComposerClient::LayerType type);
   HWC2::Error SetLayerColorTransform(const float *matrix);
@@ -152,6 +154,7 @@
   bool color_transform_matrix_set_ = false;
   bool buffer_flipped_ = false;
   bool secure_ = false;
+  bool per_frame_hdr_metadata_ = false;  // used to track if perframe metadata and blob is set.
 
   // Composition requested by client(SF)
   HWC2::Composition client_requested_ = HWC2::Composition::Device;
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index 1edb547..b91d229 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -57,6 +57,7 @@
 Locker HWCSession::locker_[HWCCallbacks::kNumDisplays];
 bool HWCSession::pending_power_mode_[HWCCallbacks::kNumDisplays];
 Locker HWCSession::power_state_[HWCCallbacks::kNumDisplays];
+Locker HWCSession::hdr_locker_[HWCCallbacks::kNumDisplays];
 Locker HWCSession::display_config_locker_;
 static const int kSolidFillDelay = 100 * 1000;
 int HWCSession::null_display_mode_ = 0;
@@ -494,6 +495,21 @@
   return HWC2_ERROR_NONE;
 }
 
+int32_t HWCSession::GetVirtualDisplayId() {
+  HWDisplaysInfo hw_displays_info = {};
+  core_intf_->GetDisplaysStatus(&hw_displays_info);
+  for (auto &iter : hw_displays_info) {
+    auto &info = iter.second;
+    if (info.display_type != kVirtual) {
+      continue;
+    }
+
+    return info.display_id;
+  }
+
+  return -1;
+}
+
 void HWCSession::Dump(uint32_t *out_size, char *out_buffer) {
   if (!out_size) {
     return;
@@ -517,7 +533,7 @@
 }
 
 uint32_t HWCSession::GetMaxVirtualDisplayCount() {
-  return 1;
+  return map_info_virtual_.size();
 }
 
 int32_t HWCSession::GetActiveConfig(hwc2_display_t display, hwc2_config_t *out_config) {
@@ -603,6 +619,15 @@
                            keys, metadata);
 }
 
+int32_t HWCSession:: SetLayerPerFrameMetadataBlobs(hwc2_display_t display,
+                                                   hwc2_layer_t layer, uint32_t num_elements,
+                                                   const int32_t *int_keys, const uint32_t *sizes,
+                                                   const uint8_t *metadata) {
+  auto keys = reinterpret_cast<const PerFrameMetadataKey *>(int_keys);
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerPerFrameMetadataBlobs,
+                           num_elements, keys, sizes, metadata);
+}
+
 int32_t HWCSession::GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
                                         int32_t int_attribute, int32_t *out_value) {
   if (out_value == nullptr || int_attribute < HWC2_ATTRIBUTE_INVALID ||
@@ -795,6 +820,9 @@
         callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
       }
     }
+  }
+
+  if (descriptor == HWC2_CALLBACK_HOTPLUG) {
     client_connected_ = !!pointer;
     // Notfify all displays.
     NotifyClientStatus(client_connected_);
@@ -1112,46 +1140,37 @@
     }
   }
 
-  HWDisplaysInfo hw_displays_info = {};
-  DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
-  if (error != kErrorNone) {
-    DLOGE("Failed to get connected display list. Error = %d", error);
-    return HWC2::Error::BadDisplay;
-  }
-
   // Lock confined to this scope
   int status = -EINVAL;
-  for (auto &iter : hw_displays_info) {
-    auto &info = iter.second;
-    if (info.display_type != kVirtual) {
-      continue;
-    }
-
-    for (auto &map_info : map_info_virtual_) {
-      client_id = map_info.client_id;
-      {
-        SCOPE_LOCK(locker_[client_id]);
-        auto &hwc_display = hwc_display_[client_id];
-        if (hwc_display) {
-          continue;
-        }
-
-        status = virtual_display_factory_.Create(core_intf_, &buffer_allocator_, &callbacks_,
-                                                 client_id, info.display_id, width, height,
-                                                 format, set_min_lum_, set_max_lum_, &hwc_display);
-        // TODO(user): validate width and height support
-        if (status) {
-          return HWC2::Error::NoResources;
-        }
-
-        is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
-        DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d", client_id, width, height);
-
-        *out_display_id = client_id;
-        map_info.disp_type = info.display_type;
-        map_info.sdm_id = info.display_id;
-        break;
+  for (auto &map_info : map_info_virtual_) {
+    client_id = map_info.client_id;
+    {
+      SCOPE_LOCK(locker_[client_id]);
+      auto &hwc_display = hwc_display_[client_id];
+      if (hwc_display) {
+        continue;
       }
+
+      int32_t display_id = GetVirtualDisplayId();
+      status = virtual_display_factory_.Create(core_intf_, &buffer_allocator_, &callbacks_,
+                                               client_id, display_id, width, height,
+                                               format, set_min_lum_, set_max_lum_, &hwc_display);
+      // TODO(user): validate width and height support
+      if (status) {
+        return HWC2::Error::NoResources;
+      }
+
+      {
+        SCOPE_LOCK(hdr_locker_[client_id]);
+        is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
+      }
+
+      DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d", client_id, width, height);
+
+      *out_display_id = client_id;
+      map_info.disp_type = kVirtual;
+      map_info.sdm_id = display_id;
+      break;
     }
   }
 
@@ -1340,13 +1359,23 @@
           DLOGE("QService command = %d: output_parcel needed.", command);
           break;
         }
-        float brightness = -1.0f;
+
         uint32_t display = input_parcel->readUint32();
-        status = getDisplayBrightness(display, &brightness);
-        if (brightness == -1.0f) {
+        uint32_t max_brightness_level = 0;
+        status = getDisplayMaxBrightness(display, &max_brightness_level);
+        if (status || !max_brightness_level) {
+          output_parcel->writeInt32(max_brightness_level);
+          DLOGE("Failed to get max brightness %u,  status %d", max_brightness_level, status);
+          break;
+        }
+        DLOGV("Panel Max brightness is %u", max_brightness_level);
+
+        float brightness_precent = -1.0f;
+        status = getDisplayBrightness(display, &brightness_precent);
+        if (brightness_precent == -1.0f) {
           output_parcel->writeInt32(0);
         } else {
-          output_parcel->writeInt32(INT32(brightness*254 + 1));
+          output_parcel->writeInt32(INT32(brightness_precent*(max_brightness_level - 1) + 1));
         }
       }
       break;
@@ -1356,11 +1385,23 @@
           DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
           break;
         }
+
+        uint32_t max_brightness_level = 0;
+        uint32_t display = HWC_DISPLAY_PRIMARY;
+        status = getDisplayMaxBrightness(display, &max_brightness_level);
+        if (status || max_brightness_level <= 1) {
+          output_parcel->writeInt32(max_brightness_level);
+          DLOGE("Failed to get max brightness %u, status %d", max_brightness_level, status);
+          break;
+        }
+        DLOGV("Panel Max brightness is %u", max_brightness_level);
+
         int level = input_parcel->readInt32();
         if (level == 0) {
-          status = SetDisplayBrightness(HWC_DISPLAY_PRIMARY, -1.0f);
+          status = SetDisplayBrightness(display, -1.0f);
         } else {
-          status = SetDisplayBrightness(HWC_DISPLAY_PRIMARY, (level - 1)/254.0f);
+          status = SetDisplayBrightness(display,
+                    (level - 1)/(static_cast<float>(max_brightness_level - 1)));
         }
         output_parcel->writeInt32(status);
       }
@@ -2349,8 +2390,12 @@
 
     if (!status) {
       DLOGI("Created primary display type = %d, sdm id = %d, client id = %d", info.display_type,
-                                                                    info.display_id, client_id);
-      is_hdr_display_[UINT32(client_id)] = HasHDRSupport(*hwc_display);
+             info.display_id, client_id);
+      {
+         SCOPE_LOCK(hdr_locker_[client_id]);
+         is_hdr_display_[UINT32(client_id)] = HasHDRSupport(*hwc_display);
+      }
+
       map_info_primary_.disp_type = info.display_type;
       map_info_primary_.sdm_id = info.display_id;
       CreateDummyDisplay(HWC_DISPLAY_PRIMARY);
@@ -2423,7 +2468,12 @@
           DLOGE("Builtin display creation failed.");
           break;
         }
-        is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display_[client_id]);
+
+        {
+          SCOPE_LOCK(hdr_locker_[client_id]);
+          is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display_[client_id]);
+        }
+
         DLOGI("Builtin display created: sdm id = %d, client id = %d", info.display_id, client_id);
         map_info.disp_type = info.display_type;
         map_info.sdm_id = info.display_id;
@@ -2575,7 +2625,11 @@
           break;
         }
 
-        is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
+        {
+          SCOPE_LOCK(hdr_locker_[client_id]);
+          is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
+        }
+
         DLOGI("Created pluggable display successfully: sdm id = %d, client id = %d",
               info.display_id, client_id);
         CreateDummyDisplay(client_id);
@@ -2674,8 +2728,11 @@
     }
     DLOGI("Destroy display %d-%d, client id = %d", map_info->sdm_id, map_info->disp_type,
          client_id);
+    {
+      SCOPE_LOCK(hdr_locker_[client_id]);
+      is_hdr_display_[UINT32(client_id)] = false;
+    }
 
-    is_hdr_display_[UINT32(client_id)] = false;
     if (!map_info->test_pattern) {
       HWCDisplayPluggable::Destroy(hwc_display);
     } else {
@@ -2707,7 +2764,11 @@
   }
   DLOGI("Destroy display %d-%d, client id = %d", map_info->sdm_id, map_info->disp_type,
         client_id);
-  is_hdr_display_[UINT32(client_id)] = false;
+  {
+    SCOPE_LOCK(hdr_locker_[client_id]);
+    is_hdr_display_[UINT32(client_id)] = false;
+  }
+
   switch (map_info->disp_type) {
     case kBuiltIn:
       HWCDisplayBuiltIn::Destroy(hwc_display);
diff --git a/composer/hwc_session.h b/composer/hwc_session.h
index 3d13424..0bfa281 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -20,7 +20,7 @@
 #ifndef __HWC_SESSION_H__
 #define __HWC_SESSION_H__
 
-#include <vendor/display/config/1.13/IDisplayConfig.h>
+#include <vendor/display/config/1.14/IDisplayConfig.h>
 #include <vendor/qti/hardware/display/composer/2.0/IQtiComposerClient.h>
 
 #include <core/core_interface.h>
@@ -49,7 +49,7 @@
 
 namespace sdm {
 
-using vendor::display::config::V1_13::IDisplayConfig;
+using vendor::display::config::V1_14::IDisplayConfig;
 using vendor::display::config::V1_10::IDisplayCWBCallback;
 
 using ::android::hardware::Return;
@@ -249,7 +249,9 @@
                                    uint32_t num_elements, const int32_t *int_keys,
                                    const float *metadata);
   int32_t SetLayerColorTransform(hwc2_display_t display, hwc2_layer_t layer, const float *matrix);
-
+  int32_t SetLayerPerFrameMetadataBlobs(hwc2_display_t display, hwc2_layer_t layer,
+                                        uint32_t num_elements, const int32_t *int_keys,
+                                        const uint32_t *sizes, const uint8_t *metadata);
   // HWCDisplayEventHandler
   virtual void DisplayPowerReset();
 
@@ -262,6 +264,7 @@
 
   static Locker locker_[HWCCallbacks::kNumDisplays];
   static Locker power_state_[HWCCallbacks::kNumDisplays];
+  static Locker hdr_locker_[HWCCallbacks::kNumDisplays];
   static Locker display_config_locker_;
 
  private:
@@ -340,6 +343,7 @@
   int32_t SetDynamicDSIClock(int64_t disp_id, uint32_t bitrate);
   int32_t getDisplayBrightness(uint32_t display, float *brightness);
   int32_t setDisplayBrightness(uint32_t display, float brightness);
+  int32_t getDisplayMaxBrightness(uint32_t display, uint32_t *max_brightness_level);
   bool HasHDRSupport(HWCDisplay *hwc_display);
 
   // Uevent handler
@@ -406,6 +410,7 @@
                                      const hidl_handle& buffer) override;
   Return<int32_t> setQsyncMode(uint32_t disp_id, IDisplayConfig::QsyncMode mode) override;
   Return<bool> isSmartPanelConfig(uint32_t disp_id, uint32_t config_id) override;
+  Return<bool> isRotatorSupportedFormat(int hal_format, bool ubwc) override;
 
   // QClient methods
   virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -454,6 +459,7 @@
   hwc2_display_t GetActiveBuiltinDisplay();
   void HandlePendingRefresh();
   void NotifyClientStatus(bool connected);
+  int32_t GetVirtualDisplayId();
 
   CoreInterface *core_intf_ = nullptr;
   HWCDisplay *hwc_display_[HWCCallbacks::kNumDisplays] = {nullptr};
diff --git a/composer/hwc_session_services.cpp b/composer/hwc_session_services.cpp
index 638cba3..a9c340a 100644
--- a/composer/hwc_session_services.cpp
+++ b/composer/hwc_session_services.cpp
@@ -708,7 +708,7 @@
     DLOGE("Not valid display");
     return false;
   }
-  SCOPE_LOCK(locker_[disp_id]);
+  SCOPE_LOCK(hdr_locker_[disp_id]);
 
   if (is_hdr_display_.size() <= disp_id) {
     DLOGW("is_hdr_display_ is not initialized for display %d!! Reporting it as HDR not supported",
@@ -824,6 +824,27 @@
   return error;
 }
 
+int32_t HWCSession::getDisplayMaxBrightness(uint32_t display, uint32_t *max_brightness_level) {
+  if (!max_brightness_level) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+
+  if (display >= HWCCallbacks::kNumDisplays) {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+
+  int32_t error = -EINVAL;
+  HWCDisplay *hwc_display = hwc_display_[display];
+  if (hwc_display && hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN) {
+    error = INT32(hwc_display_[display]->GetPanelMaxBrightness(max_brightness_level));
+    if (error) {
+      DLOGE("Failed to get the panel max brightness, display %u error %d", display, error);
+    }
+  }
+
+  return error;
+}
+
 int32_t HWCSession::setDisplayBrightness(uint32_t display, float brightness) {
   return SetDisplayBrightness(static_cast<hwc2_display_t>(display), brightness);
 }
@@ -1027,6 +1048,7 @@
 
       if (release_fence >= 0) {
         status = sync_wait(release_fence, 1000);
+        close(release_fence);
       } else {
         DLOGE("CWB release fence could not be retrieved.");
         status = -1;
@@ -1126,4 +1148,16 @@
   return INT32(status);
 }
 
+Return<bool> HWCSession::isRotatorSupportedFormat(int hal_format, bool ubwc) {
+  if (!core_intf_) {
+    DLOGW("core_intf_ not initialized.");
+    return false;
+  }
+  int flag = ubwc ? private_handle_t::PRIV_FLAGS_UBWC_ALIGNED : 0;
+
+  LayerBufferFormat sdm_format = HWCLayer::GetSDMFormat(hal_format, flag);
+
+  return core_intf_->IsRotatorSupportedFormat(sdm_format);
+}
+
 }  // namespace sdm
diff --git a/composer/vendor.qti.hardware.display.composer-service.xml b/composer/vendor.qti.hardware.display.composer-service.xml
index 5184413..0d4ef00 100644
--- a/composer/vendor.qti.hardware.display.composer-service.xml
+++ b/composer/vendor.qti.hardware.display.composer-service.xml
@@ -48,7 +48,7 @@
     <hal format="hidl">
         <name>vendor.display.config</name>
         <transport>hwbinder</transport>
-        <version>1.13</version>
+        <version>1.14</version>
         <interface>
             <name>IDisplayConfig</name>
             <instance>default</instance>
diff --git a/config/display-product.mk b/config/display-product.mk
index 98a2d8d..5ede20e 100644
--- a/config/display-product.mk
+++ b/config/display-product.mk
@@ -29,6 +29,7 @@
     vendor.display.config@1.11.vendor \
     vendor.display.config@1.12.vendor \
     vendor.display.config@1.13.vendor \
+    vendor.display.config@1.14.vendor \
     vendor.qti.hardware.display.mapper@2.0.vendor \
     vendor.qti.hardware.display.mapper@3.0.vendor \
     modetest
@@ -46,6 +47,15 @@
 #QDCM calibration xml file for dual panel
 PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_sharp_1080p_cmd_mode_dsi_panel.xml
 PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_nt35695b_truly_fhd_command_mode_dsi_panel.xml
+#QDCM calibration xml file for td4330 panel
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_bengal_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_td4330_v2_cmd_mode_dsi_truly_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_bengal_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_td4330_v2_video_mode_dsi_truly_panel.xml
+#QDCM calibration xml file for Sharp fhd panel
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Sharp_fhd_cmd_mode_qsync_dsi_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Sharp_fhd_video_mode_qsync_dsi_panel.xml
+#QDCM calibration xml file for Sharp 2k panel
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Sharp_2k_cmd_mode_qsync_dsi_panel.xml
+PRODUCT_COPY_FILES += hardware/qcom/display/config/qdcm_calib_data_default.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_Sharp_2k_video_mode_qsync_dsi_panel.xml
 
 PRODUCT_PROPERTY_OVERRIDES += \
     persist.demo.hdmirotationlock=false \
@@ -54,26 +64,34 @@
     debug.sf.hw=0 \
     debug.egl.hw=0 \
     debug.sf.latch_unsignaled=1 \
-    debug.sf.enable_gl_backpressure=1 \
+    debug.sf.high_fps_late_app_phase_offset_ns=1000000 \
     debug.mdpcomp.logs=0 \
     vendor.gralloc.disable_ubwc=0 \
     vendor.display.disable_scaler=0 \
-    vendor.display.disable_offline_rotator=1 \
     vendor.display.disable_excl_rect=0 \
     vendor.display.comp_mask=0 \
     vendor.display.enable_posted_start_dyn=1 \
     vendor.display.enable_optimize_refresh=1 \
     vendor.display.use_smooth_motion=1
 
+# Enable offline rotator for Bengal.
+ifneq ($(TARGET_BOARD_PLATFORM),bengal)
+PRODUCT_PROPERTY_OVERRIDES += \
+    vendor.display.disable_offline_rotator=1
+else
+PRODUCT_PROPERTY_OVERRIDES += \
+    vendor.display.disable_rotator_ubwc=1
+endif
+
 ifeq ($(TARGET_BOARD_PLATFORM),kona)
 PRODUCT_PROPERTY_OVERRIDES += \
+    debug.sf.enable_gl_backpressure=1 \
     debug.sf.early_phase_offset_ns=500000 \
     debug.sf.early_app_phase_offset_ns=500000 \
     debug.sf.early_gl_phase_offset_ns=3000000 \
     debug.sf.early_gl_app_phase_offset_ns=15000000 \
     debug.sf.high_fps_early_phase_offset_ns=6100000 \
-    debug.sf.high_fps_early_gl_phase_offset_ns=9000000 \
-    debug.sf.high_fps_late_app_phase_offset_ns=1000000 \
+    debug.sf.high_fps_early_gl_phase_offset_ns=6500000 \
     debug.sf.phase_offset_threshold_for_next_vsync_ns=6100000
 endif
 
@@ -86,6 +104,7 @@
 PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.has_HDR_display=true
 PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.use_color_management=true
 PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.wcg_composition_dataspace=143261696
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.protected_contents=true
 
 ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
 # Recovery is enabled, logging is enabled
diff --git a/config/qdcm_calib_data_bengal_default.xml b/config/qdcm_calib_data_bengal_default.xml
new file mode 100644
index 0000000..c954946
--- /dev/null
+++ b/config/qdcm_calib_data_bengal_default.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2019, 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.
+-->
+<Calib_Data>
+    <Disp_Modes NumModes="1" DefaultMode="0">
+        <Mode ModeID="0" DisplayID="0" IsDefaultMode="0" IsAppMode="0" Name="native" NumOfFeatures="13" WhitePoint="0" EValue="255" BValue="100" RValue="100" DynamicRange="sdr" ColorGamut="native">
+            <Feature FeatureType="2" Disable="true" DataSize="272">00000000000000000000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</Feature>
+            <Feature FeatureType="7" Disable="true" DataSize="12300">00000000000100000600000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000001010000110100002101000031010000410100005101000061010000710100008101000091010000A1010000B1010000C1010000D1010000E1010000F101000002020000120200002202000032020000420200005202000062020000720200008202000092020000A2020000B2020000C2020000D2020000E2020000F202000003030000130300002303000033030000430300005303000063030000730300008303000093030000A3030000B3030000C3030000D3030000E3030000F303000004040000140400002404000034040000440400005404000064040000740400008404000094040000A4040000B4040000C4040000D4040000E4040000F404000005050000150500002505000035050000450500005505000065050000750500008505000095050000A5050000B5050000C5050000D5050000E5050000F505000006060000160600002606000036060000460600005606000066060000760600008606000096060000A6060000B6060000C6060000D6060000E6060000F606000007070000170700002707000037070000470700005707000067070000770700008707000097070000A7070000B7070000C7070000D7070000E7070000F707000008080000180800002808000038080000480800005808000068080000780800008808000098080000A8080000B8080000C8080000D8080000E8080000F808000009090000190900002909000039090000490900005909000069090000790900008909000099090000A9090000B9090000C9090000D9090000E9090000F90900000A0A00001A0A00002A0A00003A0A00004A0A00005A0A00006A0A00007A0A00008A0A00009A0A0000AA0A0000BA0A0000CA0A0000DA0A0000EA0A0000FA0A00000B0B00001B0B00002B0B00003B0B00004B0B00005B0B00006B0B00007B0B00008B0B00009B0B0000AB0B0000BB0B0000CB0B0000DB0B0000EB0B0000FB0B00000C0C00001C0C00002C0C00003C0C00004C0C00005C0C00006C0C00007C0C00008C0C00009C0C0000AC0C0000BC0C0000CC0C0000DC0C0000EC0C0000FC0C00000D0D00001D0D00002D0D00003D0D00004D0D00005D0D00006D0D00007D0D00008D0D00009D0D0000AD0D0000BD0D0000CD0D0000DD0D0000ED0D0000FD0D00000E0E00001E0E00002E0E00003E0E00004E0E00005E0E00006E0E00007E0E00008E0E00009E0E0000AE0E0000BE0E0000CE0E0000DE0E0000EE0E0000FE0E00000F0F00001F0F00002F0F00003F0F00004F0F00005F0F00006F0F00007F0F00008F0F00009F0F0000AF0F0000BF0F0000CF0F0000DF0F0000EF0F0000FF0F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000001010000110100002101000031010000410100005101000061010000710100008101000091010000A1010000B1010000C1010000D1010000E1010000F101000002020000120200002202000032020000420200005202000062020000720200008202000092020000A2020000B2020000C2020000D2020000E2020000F202000003030000130300002303000033030000430300005303000063030000730300008303000093030000A3030000B3030000C3030000D3030000E3030000F303000004040000140400002404000034040000440400005404000064040000740400008404000094040000A4040000B4040000C4040000D4040000E4040000F404000005050000150500002505000035050000450500005505000065050000750500008505000095050000A5050000B5050000C5050000D5050000E5050000F505000006060000160600002606000036060000460600005606000066060000760600008606000096060000A6060000B6060000C6060000D6060000E6060000F606000007070000170700002707000037070000470700005707000067070000770700008707000097070000A7070000B7070000C7070000D7070000E7070000F707000008080000180800002808000038080000480800005808000068080000780800008808000098080000A8080000B8080000C8080000D8080000E8080000F808000009090000190900002909000039090000490900005909000069090000790900008909000099090000A9090000B9090000C9090000D9090000E9090000F90900000A0A00001A0A00002A0A00003A0A00004A0A00005A0A00006A0A00007A0A00008A0A00009A0A0000AA0A0000BA0A0000CA0A0000DA0A0000EA0A0000FA0A00000B0B00001B0B00002B0B00003B0B00004B0B00005B0B00006B0B00007B0B00008B0B00009B0B0000AB0B0000BB0B0000CB0B0000DB0B0000EB0B0000FB0B00000C0C00001C0C00002C0C00003C0C00004C0C00005C0C00006C0C00007C0C00008C0C00009C0C0000AC0C0000BC0C0000CC0C0000DC0C0000EC0C0000FC0C00000D0D00001D0D00002D0D00003D0D00004D0D00005D0D00006D0D00007D0D00008D0D00009D0D0000AD0D0000BD0D0000CD0D0000DD0D0000ED0D0000FD0D00000E0E00001E0E00002E0E00003E0E00004E0E00005E0E00006E0E00007E0E00008E0E00009E0E0000AE0E0000BE0E0000CE0E0000DE0E0000EE0E0000FE0E00000F0F00001F0F00002F0F00003F0F00004F0F00005F0F00006F0F00007F0F00008F0F00009F0F0000AF0F0000BF0F0000CF0F0000DF0F0000EF0F0000FF0F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000001010000110100002101000031010000410100005101000061010000710100008101000091010000A1010000B1010000C1010000D1010000E1010000F101000002020000120200002202000032020000420200005202000062020000720200008202000092020000A2020000B2020000C2020000D2020000E2020000F202000003030000130300002303000033030000430300005303000063030000730300008303000093030000A3030000B3030000C3030000D3030000E3030000F303000004040000140400002404000034040000440400005404000064040000740400008404000094040000A4040000B4040000C4040000D4040000E4040000F404000005050000150500002505000035050000450500005505000065050000750500008505000095050000A5050000B5050000C5050000D5050000E5050000F505000006060000160600002606000036060000460600005606000066060000760600008606000096060000A6060000B6060000C6060000D6060000E6060000F606000007070000170700002707000037070000470700005707000067070000770700008707000097070000A7070000B7070000C7070000D7070000E7070000F707000008080000180800002808000038080000480800005808000068080000780800008808000098080000A8080000B8080000C8080000D8080000E8080000F808000009090000190900002909000039090000490900005909000069090000790900008909000099090000A9090000B9090000C9090000D9090000E9090000F90900000A0A00001A0A00002A0A00003A0A00004A0A00005A0A00006A0A00007A0A00008A0A00009A0A0000AA0A0000BA0A0000CA0A0000DA0A0000EA0A0000FA0A00000B0B00001B0B00002B0B00003B0B00004B0B00005B0B00006B0B00007B0B00008B0B00009B0B0000AB0B0000BB0B0000CB0B0000DB0B0000EB0B0000FB0B00000C0C00001C0C00002C0C00003C0C00004C0C00005C0C00006C0C00007C0C00008C0C00009C0C0000AC0C0000BC0C0000CC0C0000DC0C0000EC0C0000FC0C00000D0D00001D0D00002D0D00003D0D00004D0D00005D0D00006D0D00007D0D00008D0D00009D0D0000AD0D0000BD0D0000CD0D0000DD0D0000ED0D0000FD0D00000E0E00001E0E00002E0E00003E0E00004E0E00005E0E00006E0E00007E0E00008E0E00009E0E0000AE0E0000BE0E0000CE0E0000DE0E0000EE0E0000FE0E00000F0F00001F0F00002F0F00003F0F00004F0F00005F0F00006F0F00007F0F00008F0F00009F0F0000AF0F0000BF0F0000CF0F0000DF0F0000EF0F0000FF0F0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</Feature>
+            <Feature FeatureType="8" Disable="true" DataSize="12300">010000000004000006000000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000800000008100000082000000830000008400000085000000860000008700000088000000890000008A0000008B0000008C0000008D0000008E0000008F000000900000009100000092000000930000009400000095000000960000009700000098000000990000009A0000009B0000009C0000009D0000009E0000009F000000A0000000A1000000A2000000A3000000A4000000A5000000A6000000A7000000A8000000A9000000AA000000AB000000AC000000AD000000AE000000AF000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000B8000000B9000000BA000000BB000000BC000000BD000000BE000000BF000000C0000000C1000000C2000000C3000000C4000000C5000000C6000000C7000000C8000000C9000000CA000000CB000000CC000000CD000000CE000000CF000000D0000000D1000000D2000000D3000000D4000000D5000000D6000000D7000000D8000000D9000000DA000000DB000000DC000000DD000000DE000000DF000000E0000000E1000000E2000000E3000000E4000000E5000000E6000000E7000000E8000000E9000000EA000000EB000000EC000000ED000000EE000000EF000000F0000000F1000000F2000000F3000000F4000000F5000000F6000000F7000000F8000000F9000000FA000000FB000000FC000000FD000000FE000000FF000000000100000101000002010000030100000401000005010000060100000701000008010000090100000A0100000B0100000C0100000D0100000E0100000F010000100100001101000012010000130100001401000015010000160100001701000018010000190100001A0100001B0100001C0100001D0100001E0100001F010000200100002101000022010000230100002401000025010000260100002701000028010000290100002A0100002B0100002C0100002D0100002E0100002F010000300100003101000032010000330100003401000035010000360100003701000038010000390100003A0100003B0100003C0100003D0100003E0100003F010000400100004101000042010000430100004401000045010000460100004701000048010000490100004A0100004B0100004C0100004D0100004E0100004F010000500100005101000052010000530100005401000055010000560100005701000058010000590100005A0100005B0100005C0100005D0100005E0100005F010000600100006101000062010000630100006401000065010000660100006701000068010000690100006A0100006B0100006C0100006D0100006E0100006F010000700100007101000072010000730100007401000075010000760100007701000078010000790100007A0100007B0100007C0100007D0100007E0100007F010000800100008101000082010000830100008401000085010000860100008701000088010000890100008A0100008B0100008C0100008D0100008E0100008F010000900100009101000092010000930100009401000095010000960100009701000098010000990100009A0100009B0100009C0100009D0100009E0100009F010000A0010000A1010000A2010000A3010000A4010000A5010000A6010000A7010000A8010000A9010000AA010000AB010000AC010000AD010000AE010000AF010000B0010000B1010000B2010000B3010000B4010000B5010000B6010000B7010000B8010000B9010000BA010000BB010000BC010000BD010000BE010000BF010000C0010000C1010000C2010000C3010000C4010000C5010000C6010000C7010000C8010000C9010000CA010000CB010000CC010000CD010000CE010000CF010000D0010000D1010000D2010000D3010000D4010000D5010000D6010000D7010000D8010000D9010000DA010000DB010000DC010000DD010000DE010000DF010000E0010000E1010000E2010000E3010000E4010000E5010000E6010000E7010000E8010000E9010000EA010000EB010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F4010000F5010000F6010000F7010000F8010000F9010000FA010000FB010000FC010000FD010000FE010000FF010000000200000102000002020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000E0200000F020000100200001102000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F020000200200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002C0200002D0200002E0200002F020000300200003102000032020000330200003402000035020000360200003702000038020000390200003A0200003B0200003C0200003D0200003E0200003F020000400200004102000042020000430200004402000045020000460200004702000048020000490200004A0200004B0200004C0200004D0200004E0200004F020000500200005102000052020000530200005402000055020000560200005702000058020000590200005A0200005B0200005C0200005D0200005E0200005F020000600200006102000062020000630200006402000065020000660200006702000068020000690200006A0200006B0200006C0200006D0200006E0200006F020000700200007102000072020000730200007402000075020000760200007702000078020000790200007A0200007B0200007C0200007D0200007E0200007F020000800200008102000082020000830200008402000085020000860200008702000088020000890200008A0200008B0200008C0200008D0200008E0200008F020000900200009102000092020000930200009402000095020000960200009702000098020000990200009A0200009B0200009C0200009D0200009E0200009F020000A0020000A1020000A2020000A3020000A4020000A5020000A6020000A7020000A8020000A9020000AA020000AB020000AC020000AD020000AE020000AF020000B0020000B1020000B2020000B3020000B4020000B5020000B6020000B7020000B8020000B9020000BA020000BB020000BC020000BD020000BE020000BF020000C0020000C1020000C2020000C3020000C4020000C5020000C6020000C7020000C8020000C9020000CA020000CB020000CC020000CD020000CE020000CF020000D0020000D1020000D2020000D3020000D4020000D5020000D6020000D7020000D8020000D9020000DA020000DB020000DC020000DD020000DE020000DF020000E0020000E1020000E2020000E3020000E4020000E5020000E6020000E7020000E8020000E9020000EA020000EB020000EC020000ED020000EE020000EF020000F0020000F1020000F2020000F3020000F4020000F5020000F6020000F7020000F8020000F9020000FA020000FB020000FC020000FD020000FE020000FF020000000300000103000002030000030300000403000005030000060300000703000008030000090300000A0300000B0300000C0300000D0300000E0300000F030000100300001103000012030000130300001403000015030000160300001703000018030000190300001A0300001B0300001C0300001D0300001E0300001F030000200300002103000022030000230300002403000025030000260300002703000028030000290300002A0300002B0300002C0300002D0300002E0300002F030000300300003103000032030000330300003403000035030000360300003703000038030000390300003A0300003B0300003C0300003D0300003E0300003F030000400300004103000042030000430300004403000045030000460300004703000048030000490300004A0300004B0300004C0300004D0300004E0300004F030000500300005103000052030000530300005403000055030000560300005703000058030000590300005A0300005B0300005C0300005D0300005E0300005F030000600300006103000062030000630300006403000065030000660300006703000068030000690300006A0300006B0300006C0300006D0300006E0300006F030000700300007103000072030000730300007403000075030000760300007703000078030000790300007A0300007B0300007C0300007D0300007E0300007F030000800300008103000082030000830300008403000085030000860300008703000088030000890300008A0300008B0300008C0300008D0300008E0300008F030000900300009103000092030000930300009403000095030000960300009703000098030000990300009A0300009B0300009C0300009D0300009E0300009F030000A0030000A1030000A2030000A3030000A4030000A5030000A6030000A7030000A8030000A9030000AA030000AB030000AC030000AD030000AE030000AF030000B0030000B1030000B2030000B3030000B4030000B5030000B6030000B7030000B8030000B9030000BA030000BB030000BC030000BD030000BE030000BF030000C0030000C1030000C2030000C3030000C4030000C5030000C6030000C7030000C8030000C9030000CA030000CB030000CC030000CD030000CE030000CF030000D0030000D1030000D2030000D3030000D4030000D5030000D6030000D7030000D8030000D9030000DA030000DB030000DC030000DD030000DE030000DF030000E0030000E1030000E2030000E3030000E4030000E5030000E6030000E7030000E8030000E9030000EA030000EB030000EC030000ED030000EE030000EF030000F0030000F1030000F2030000F3030000F4030000F5030000F6030000F7030000F8030000F9030000FA030000FB030000FC030000FD030000FE030000FF030000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000800000008100000082000000830000008400000085000000860000008700000088000000890000008A0000008B0000008C0000008D0000008E0000008F000000900000009100000092000000930000009400000095000000960000009700000098000000990000009A0000009B0000009C0000009D0000009E0000009F000000A0000000A1000000A2000000A3000000A4000000A5000000A6000000A7000000A8000000A9000000AA000000AB000000AC000000AD000000AE000000AF000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000B8000000B9000000BA000000BB000000BC000000BD000000BE000000BF000000C0000000C1000000C2000000C3000000C4000000C5000000C6000000C7000000C8000000C9000000CA000000CB000000CC000000CD000000CE000000CF000000D0000000D1000000D2000000D3000000D4000000D5000000D6000000D7000000D8000000D9000000DA000000DB000000DC000000DD000000DE000000DF000000E0000000E1000000E2000000E3000000E4000000E5000000E6000000E7000000E8000000E9000000EA000000EB000000EC000000ED000000EE000000EF000000F0000000F1000000F2000000F3000000F4000000F5000000F6000000F7000000F8000000F9000000FA000000FB000000FC000000FD000000FE000000FF000000000100000101000002010000030100000401000005010000060100000701000008010000090100000A0100000B0100000C0100000D0100000E0100000F010000100100001101000012010000130100001401000015010000160100001701000018010000190100001A0100001B0100001C0100001D0100001E0100001F010000200100002101000022010000230100002401000025010000260100002701000028010000290100002A0100002B0100002C0100002D0100002E0100002F010000300100003101000032010000330100003401000035010000360100003701000038010000390100003A0100003B0100003C0100003D0100003E0100003F010000400100004101000042010000430100004401000045010000460100004701000048010000490100004A0100004B0100004C0100004D0100004E0100004F010000500100005101000052010000530100005401000055010000560100005701000058010000590100005A0100005B0100005C0100005D0100005E0100005F010000600100006101000062010000630100006401000065010000660100006701000068010000690100006A0100006B0100006C0100006D0100006E0100006F010000700100007101000072010000730100007401000075010000760100007701000078010000790100007A0100007B0100007C0100007D0100007E0100007F010000800100008101000082010000830100008401000085010000860100008701000088010000890100008A0100008B0100008C0100008D0100008E0100008F010000900100009101000092010000930100009401000095010000960100009701000098010000990100009A0100009B0100009C0100009D0100009E0100009F010000A0010000A1010000A2010000A3010000A4010000A5010000A6010000A7010000A8010000A9010000AA010000AB010000AC010000AD010000AE010000AF010000B0010000B1010000B2010000B3010000B4010000B5010000B6010000B7010000B8010000B9010000BA010000BB010000BC010000BD010000BE010000BF010000C0010000C1010000C2010000C3010000C4010000C5010000C6010000C7010000C8010000C9010000CA010000CB010000CC010000CD010000CE010000CF010000D0010000D1010000D2010000D3010000D4010000D5010000D6010000D7010000D8010000D9010000DA010000DB010000DC010000DD010000DE010000DF010000E0010000E1010000E2010000E3010000E4010000E5010000E6010000E7010000E8010000E9010000EA010000EB010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F4010000F5010000F6010000F7010000F8010000F9010000FA010000FB010000FC010000FD010000FE010000FF010000000200000102000002020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000E0200000F020000100200001102000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F020000200200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002C0200002D0200002E0200002F020000300200003102000032020000330200003402000035020000360200003702000038020000390200003A0200003B0200003C0200003D0200003E0200003F020000400200004102000042020000430200004402000045020000460200004702000048020000490200004A0200004B0200004C0200004D0200004E0200004F020000500200005102000052020000530200005402000055020000560200005702000058020000590200005A0200005B0200005C0200005D0200005E0200005F020000600200006102000062020000630200006402000065020000660200006702000068020000690200006A0200006B0200006C0200006D0200006E0200006F020000700200007102000072020000730200007402000075020000760200007702000078020000790200007A0200007B0200007C0200007D0200007E0200007F020000800200008102000082020000830200008402000085020000860200008702000088020000890200008A0200008B0200008C0200008D0200008E0200008F020000900200009102000092020000930200009402000095020000960200009702000098020000990200009A0200009B0200009C0200009D0200009E0200009F020000A0020000A1020000A2020000A3020000A4020000A5020000A6020000A7020000A8020000A9020000AA020000AB020000AC020000AD020000AE020000AF020000B0020000B1020000B2020000B3020000B4020000B5020000B6020000B7020000B8020000B9020000BA020000BB020000BC020000BD020000BE020000BF020000C0020000C1020000C2020000C3020000C4020000C5020000C6020000C7020000C8020000C9020000CA020000CB020000CC020000CD020000CE020000CF020000D0020000D1020000D2020000D3020000D4020000D5020000D6020000D7020000D8020000D9020000DA020000DB020000DC020000DD020000DE020000DF020000E0020000E1020000E2020000E3020000E4020000E5020000E6020000E7020000E8020000E9020000EA020000EB020000EC020000ED020000EE020000EF020000F0020000F1020000F2020000F3020000F4020000F5020000F6020000F7020000F8020000F9020000FA020000FB020000FC020000FD020000FE020000FF020000000300000103000002030000030300000403000005030000060300000703000008030000090300000A0300000B0300000C0300000D0300000E0300000F030000100300001103000012030000130300001403000015030000160300001703000018030000190300001A0300001B0300001C0300001D0300001E0300001F030000200300002103000022030000230300002403000025030000260300002703000028030000290300002A0300002B0300002C0300002D0300002E0300002F030000300300003103000032030000330300003403000035030000360300003703000038030000390300003A0300003B0300003C0300003D0300003E0300003F030000400300004103000042030000430300004403000045030000460300004703000048030000490300004A0300004B0300004C0300004D0300004E0300004F030000500300005103000052030000530300005403000055030000560300005703000058030000590300005A0300005B0300005C0300005D0300005E0300005F030000600300006103000062030000630300006403000065030000660300006703000068030000690300006A0300006B0300006C0300006D0300006E0300006F030000700300007103000072030000730300007403000075030000760300007703000078030000790300007A0300007B0300007C0300007D0300007E0300007F030000800300008103000082030000830300008403000085030000860300008703000088030000890300008A0300008B0300008C0300008D0300008E0300008F030000900300009103000092030000930300009403000095030000960300009703000098030000990300009A0300009B0300009C0300009D0300009E0300009F030000A0030000A1030000A2030000A3030000A4030000A5030000A6030000A7030000A8030000A9030000AA030000AB030000AC030000AD030000AE030000AF030000B0030000B1030000B2030000B3030000B4030000B5030000B6030000B7030000B8030000B9030000BA030000BB030000BC030000BD030000BE030000BF030000C0030000C1030000C2030000C3030000C4030000C5030000C6030000C7030000C8030000C9030000CA030000CB030000CC030000CD030000CE030000CF030000D0030000D1030000D2030000D3030000D4030000D5030000D6030000D7030000D8030000D9030000DA030000DB030000DC030000DD030000DE030000DF030000E0030000E1030000E2030000E3030000E4030000E5030000E6030000E7030000E8030000E9030000EA030000EB030000EC030000ED030000EE030000EF030000F0030000F1030000F2030000F3030000F4030000F5030000F6030000F7030000F8030000F9030000FA030000FB030000FC030000FD030000FE030000FF030000000000000100000002000000030000000400000005000000060000000700000008000000090000000A0000000B0000000C0000000D0000000E0000000F000000100000001100000012000000130000001400000015000000160000001700000018000000190000001A0000001B0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C0000003D0000003E0000003F000000400000004100000042000000430000004400000045000000460000004700000048000000490000004A0000004B0000004C0000004D0000004E0000004F000000500000005100000052000000530000005400000055000000560000005700000058000000590000005A0000005B0000005C0000005D0000005E0000005F000000600000006100000062000000630000006400000065000000660000006700000068000000690000006A0000006B0000006C0000006D0000006E0000006F000000700000007100000072000000730000007400000075000000760000007700000078000000790000007A0000007B0000007C0000007D0000007E0000007F000000800000008100000082000000830000008400000085000000860000008700000088000000890000008A0000008B0000008C0000008D0000008E0000008F000000900000009100000092000000930000009400000095000000960000009700000098000000990000009A0000009B0000009C0000009D0000009E0000009F000000A0000000A1000000A2000000A3000000A4000000A5000000A6000000A7000000A8000000A9000000AA000000AB000000AC000000AD000000AE000000AF000000B0000000B1000000B2000000B3000000B4000000B5000000B6000000B7000000B8000000B9000000BA000000BB000000BC000000BD000000BE000000BF000000C0000000C1000000C2000000C3000000C4000000C5000000C6000000C7000000C8000000C9000000CA000000CB000000CC000000CD000000CE000000CF000000D0000000D1000000D2000000D3000000D4000000D5000000D6000000D7000000D8000000D9000000DA000000DB000000DC000000DD000000DE000000DF000000E0000000E1000000E2000000E3000000E4000000E5000000E6000000E7000000E8000000E9000000EA000000EB000000EC000000ED000000EE000000EF000000F0000000F1000000F2000000F3000000F4000000F5000000F6000000F7000000F8000000F9000000FA000000FB000000FC000000FD000000FE000000FF000000000100000101000002010000030100000401000005010000060100000701000008010000090100000A0100000B0100000C0100000D0100000E0100000F010000100100001101000012010000130100001401000015010000160100001701000018010000190100001A0100001B0100001C0100001D0100001E0100001F010000200100002101000022010000230100002401000025010000260100002701000028010000290100002A0100002B0100002C0100002D0100002E0100002F010000300100003101000032010000330100003401000035010000360100003701000038010000390100003A0100003B0100003C0100003D0100003E0100003F010000400100004101000042010000430100004401000045010000460100004701000048010000490100004A0100004B0100004C0100004D0100004E0100004F010000500100005101000052010000530100005401000055010000560100005701000058010000590100005A0100005B0100005C0100005D0100005E0100005F010000600100006101000062010000630100006401000065010000660100006701000068010000690100006A0100006B0100006C0100006D0100006E0100006F010000700100007101000072010000730100007401000075010000760100007701000078010000790100007A0100007B0100007C0100007D0100007E0100007F010000800100008101000082010000830100008401000085010000860100008701000088010000890100008A0100008B0100008C0100008D0100008E0100008F010000900100009101000092010000930100009401000095010000960100009701000098010000990100009A0100009B0100009C0100009D0100009E0100009F010000A0010000A1010000A2010000A3010000A4010000A5010000A6010000A7010000A8010000A9010000AA010000AB010000AC010000AD010000AE010000AF010000B0010000B1010000B2010000B3010000B4010000B5010000B6010000B7010000B8010000B9010000BA010000BB010000BC010000BD010000BE010000BF010000C0010000C1010000C2010000C3010000C4010000C5010000C6010000C7010000C8010000C9010000CA010000CB010000CC010000CD010000CE010000CF010000D0010000D1010000D2010000D3010000D4010000D5010000D6010000D7010000D8010000D9010000DA010000DB010000DC010000DD010000DE010000DF010000E0010000E1010000E2010000E3010000E4010000E5010000E6010000E7010000E8010000E9010000EA010000EB010000EC010000ED010000EE010000EF010000F0010000F1010000F2010000F3010000F4010000F5010000F6010000F7010000F8010000F9010000FA010000FB010000FC010000FD010000FE010000FF010000000200000102000002020000030200000402000005020000060200000702000008020000090200000A0200000B0200000C0200000D0200000E0200000F020000100200001102000012020000130200001402000015020000160200001702000018020000190200001A0200001B0200001C0200001D0200001E0200001F020000200200002102000022020000230200002402000025020000260200002702000028020000290200002A0200002B0200002C0200002D0200002E0200002F020000300200003102000032020000330200003402000035020000360200003702000038020000390200003A0200003B0200003C0200003D0200003E0200003F020000400200004102000042020000430200004402000045020000460200004702000048020000490200004A0200004B0200004C0200004D0200004E0200004F020000500200005102000052020000530200005402000055020000560200005702000058020000590200005A0200005B0200005C0200005D0200005E0200005F020000600200006102000062020000630200006402000065020000660200006702000068020000690200006A0200006B0200006C0200006D0200006E0200006F020000700200007102000072020000730200007402000075020000760200007702000078020000790200007A0200007B0200007C0200007D0200007E0200007F020000800200008102000082020000830200008402000085020000860200008702000088020000890200008A0200008B0200008C0200008D0200008E0200008F020000900200009102000092020000930200009402000095020000960200009702000098020000990200009A0200009B0200009C0200009D0200009E0200009F020000A0020000A1020000A2020000A3020000A4020000A5020000A6020000A7020000A8020000A9020000AA020000AB020000AC020000AD020000AE020000AF020000B0020000B1020000B2020000B3020000B4020000B5020000B6020000B7020000B8020000B9020000BA020000BB020000BC020000BD020000BE020000BF020000C0020000C1020000C2020000C3020000C4020000C5020000C6020000C7020000C8020000C9020000CA020000CB020000CC020000CD020000CE020000CF020000D0020000D1020000D2020000D3020000D4020000D5020000D6020000D7020000D8020000D9020000DA020000DB020000DC020000DD020000DE020000DF020000E0020000E1020000E2020000E3020000E4020000E5020000E6020000E7020000E8020000E9020000EA020000EB020000EC020000ED020000EE020000EF020000F0020000F1020000F2020000F3020000F4020000F5020000F6020000F7020000F8020000F9020000FA020000FB020000FC020000FD020000FE020000FF020000000300000103000002030000030300000403000005030000060300000703000008030000090300000A0300000B0300000C0300000D0300000E0300000F030000100300001103000012030000130300001403000015030000160300001703000018030000190300001A0300001B0300001C0300001D0300001E0300001F030000200300002103000022030000230300002403000025030000260300002703000028030000290300002A0300002B0300002C0300002D0300002E0300002F030000300300003103000032030000330300003403000035030000360300003703000038030000390300003A0300003B0300003C0300003D0300003E0300003F030000400300004103000042030000430300004403000045030000460300004703000048030000490300004A0300004B0300004C0300004D0300004E0300004F030000500300005103000052030000530300005403000055030000560300005703000058030000590300005A0300005B0300005C0300005D0300005E0300005F030000600300006103000062030000630300006403000065030000660300006703000068030000690300006A0300006B0300006C0300006D0300006E0300006F030000700300007103000072030000730300007403000075030000760300007703000078030000790300007A0300007B0300007C0300007D0300007E0300007F030000800300008103000082030000830300008403000085030000860300008703000088030000890300008A0300008B0300008C0300008D0300008E0300008F030000900300009103000092030000930300009403000095030000960300009703000098030000990300009A0300009B0300009C0300009D0300009E0300009F030000A0030000A1030000A2030000A3030000A4030000A5030000A6030000A7030000A8030000A9030000AA030000AB030000AC030000AD030000AE030000AF030000B0030000B1030000B2030000B3030000B4030000B5030000B6030000B7030000B8030000B9030000BA030000BB030000BC030000BD030000BE030000BF030000C0030000C1030000C2030000C3030000C4030000C5030000C6030000C7030000C8030000C9030000CA030000CB030000CC030000CD030000CE030000CF030000D0030000D1030000D2030000D3030000D4030000D5030000D6030000D7030000D8030000D9030000DA030000DB030000DC030000DD030000DE030000DF030000E0030000E1030000E2030000E3030000E4030000E5030000E6030000E7030000E8030000E9030000EA030000EB030000EC030000ED030000EE030000EF030000F0030000F1030000F2030000F3030000F4030000F5030000F6030000F7030000F8030000F9030000FA030000FB030000FC030000FD030000FE030000FF030000</Feature>
+            <Feature FeatureType="14" Disable="false" DataSize="9560">00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F00000021000000210000000300000003000000000000002D00000000000000010000000000C842000000000000803F0000C842000000000000803F0100000000000000000000000000000000000000000000000F0000002100000021000000030000000300000000000000FF000000C3000000010000000000C842000000000000803F0000C842000000000000803F0200000000000000000000000000000000000000000000000F0000002100000021000000030000000300000000000000870000004B000000010000000000C842000000000000803F0000C842000000000000803F0000000000000000640000000A0000000100000064000000000000000100000021000000210000000300000003000000000000000000000080010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</Feature>
+            <Feature FeatureType="20" Disable="true" DataSize="88">0000000008000000080000000800000000000000100000000F000000070000000D00000005000000030000000B00000001000000090000000C000000040000000E000000060000000000000008000000020000000A000000</Feature>
+            <Feature FeatureType="22" Disable="true" DataSize="0"/>
+        </Mode>
+    </Disp_Modes>
+    <Luts NumLuts="1">
+        <Lut Type="0" NumPackets="41">ECFFFFFF0000803F936F163FDA1AB13DEDFFFFFF0000803F87501D3FB9530A3EEEFFFFFF0000803FAAEE213FD1912C3EEFFFFFFF0000803F8CBC283F8C82603EF0FFFFFF0000803F473C2D3FD1E9813EF1FFFFFF0000803F5C02343FFE0E9D3EF2FFFFFF0000803F6E6E383FE04DAF3EF3FFFFFF0000803F31093F3F3C16CB3EF4FFFFFF0000803F3960433F73BDDD3EF5FFFFFF0000803F91D5493F6519FA3EF6FFFFFF0000803F840E4E3F957E063FF7FFFFFF0000803F1B62543FCEDF143FF8FFFFFF0000803F828C583F90871E3FF9FFFFFF0000803FF2B65E3F1A182D3FFAFFFFFF0000803FE7C4623FABCE363FFBFFFFFF0000803FD7BE683F8E5A453FFCFFFFFF0000803F41B66C3FD6194F3FFDFFFFFF0000803F1E8A723F8AAC5D3FFEFFFFFF0000803F516B763F6475673FFFFFFFFF0000803F8A227C3FB41E763F000000000000803F0000803F0000803F01000000836B723F6189773F0000803F02000000BF0C6A3F484E723F0000803F03000000CD945E3F191E6B3F0000803F04000000B988573FEFAB663F0000803F0500000084D44D3F5E81603F0000803F0600000045D9473FEBAA5C3F0000803F07000000CA883F3F2651573F0000803F080000005C593A3FADFB533F0000803F09000000802D333F05514F3F0000803F0A00000083C02E3FC3624C3F0000803F0B0000005986283FE04C483F0000803F0C0000008C9D243F18B3453F0000803F0D000000431C1F3F8909423F0000803F0E000000ABB21B3FE4C03F3F0000803F0F0000003DD4163FC07A3C3F0000803F1000000009C0133FE4683A3F0000803F110000008A740F3FF27B373F0000803F1200000039B80C3FCB9D353F0000803F130000005DDE083FBAF9323F0000803F140000009467063F3448313F0000803F</Lut>
+    </Luts>
+</Calib_Data>
diff --git a/gpu_tonemapper/Android.mk b/gpu_tonemapper/Android.mk
index ec59eef..fe98897 100644
--- a/gpu_tonemapper/Android.mk
+++ b/gpu_tonemapper/Android.mk
@@ -1,7 +1,6 @@
 LOCAL_PATH := $(call my-dir)
 include $(LOCAL_PATH)/../common.mk
 
-ifneq ($(TARGET_IS_HEADLESS), true)
 include $(CLEAR_VARS)
 LOCAL_COPY_HEADERS_TO     := $(common_header_export_path)
 LOCAL_COPY_HEADERS        := TonemapFactory.h Tonemapper.h
@@ -28,4 +27,3 @@
                              Tonemapper.cpp
 
 include $(BUILD_SHARED_LIBRARY)
-endif
diff --git a/gpu_tonemapper/EGLImageWrapper.cpp b/gpu_tonemapper/EGLImageWrapper.cpp
index 19bf093..560fd5a 100644
--- a/gpu_tonemapper/EGLImageWrapper.cpp
+++ b/gpu_tonemapper/EGLImageWrapper.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -32,36 +32,6 @@
 
 static string pidString = std::to_string(getpid());
 
-#ifndef TARGET_ION_ABI_VERSION
-//-----------------------------------------------------------------------------
-static void free_ion_cookie(int ion_fd, int cookie)
-//-----------------------------------------------------------------------------
-{
-  if (ion_fd && !ioctl(ion_fd, ION_IOC_FREE, &cookie)) {
-  } else {
-      ALOGE("ION_IOC_FREE failed: ion_fd = %d, cookie = %d", ion_fd, cookie);
-  }
-}
-
-//-----------------------------------------------------------------------------
-static int get_ion_cookie(int ion_fd, int fd)
-//-----------------------------------------------------------------------------
-{
-  int cookie = fd;
-
-  struct ion_fd_data fdData;
-  memset(&fdData, 0, sizeof(fdData));
-  fdData.fd = fd;
-
-  if (ion_fd && !ioctl(ion_fd, ION_IOC_IMPORT, &fdData)) {
-       cookie = fdData.handle;
-  } else {
-       ALOGE("ION_IOC_IMPORT failed: ion_fd = %d, fd = %d", ion_fd, fd);
-  }
-
-  return cookie;
-}
-#else
 //-----------------------------------------------------------------------------
 static string get_ion_buff_str(int buff_fd)
 //-----------------------------------------------------------------------------
@@ -80,7 +50,6 @@
 
   return retStr;
 }
-#endif
 
 //-----------------------------------------------------------------------------
 void EGLImageWrapper::DeleteEGLImageCallback::operator()(int& buffInt, EGLImageBuffer*& eglImage)
@@ -90,9 +59,6 @@
     delete eglImage;
   }
 
-#ifndef TARGET_ION_ABI_VERSION
-  free_ion_cookie(ion_fd, buffInt /* cookie */);
-#else
   if (!mapClearPending) {
     for (auto it = buffStrbuffIntMapPtr->begin(); it != buffStrbuffIntMapPtr->end(); it++) {
       if (it->second == buffInt /* counter */) {
@@ -101,7 +67,6 @@
       }
     }
   }
-#endif
 }
 
 //-----------------------------------------------------------------------------
@@ -111,17 +76,19 @@
   eglImageBufferCache = new android::LruCache<int, EGLImageBuffer*>(32);
   callback = new DeleteEGLImageCallback(&buffStrbuffIntMap);
   eglImageBufferCache->setOnEntryRemovedListener(callback);
-
-#ifndef TARGET_ION_ABI_VERSION
-  ion_fd = open("/dev/ion", O_RDONLY);
-  callback->ion_fd = ion_fd;
-#endif
 }
 
 //-----------------------------------------------------------------------------
 EGLImageWrapper::~EGLImageWrapper()
 //-----------------------------------------------------------------------------
 {
+  Deinit();
+}
+
+//-----------------------------------------------------------------------------
+void EGLImageWrapper::Deinit()
+//-----------------------------------------------------------------------------
+{
   if (eglImageBufferCache != 0) {
     if (callback != 0) {
       callback->mapClearPending = true;
@@ -137,12 +104,6 @@
     callback = 0;
   }
 
-#ifndef TARGET_ION_ABI_VERSION
-  if (ion_fd > 0) {
-    close(ion_fd);
-    ion_fd = -1;
-  }
-#endif
 }
 
 //-----------------------------------------------------------------------------
@@ -180,17 +141,6 @@
 {
   const private_handle_t *src = static_cast<const private_handle_t *>(pvt_handle);
 
-#ifndef TARGET_ION_ABI_VERSION
-  int ion_cookie = get_ion_cookie(ion_fd, src->fd);
-  EGLImageBuffer* eglImage = nullptr;
-  eglImage = eglImageBufferCache->get(ion_cookie);
-  if (eglImage == 0) {
-    eglImage = L_wrap(src);
-    eglImageBufferCache->put(ion_cookie, eglImage);
-  } else {
-    free_ion_cookie(ion_fd, ion_cookie);
-  }
-#else
   string buffStr = get_ion_buff_str(src->fd);
   EGLImageBuffer* eglImage = nullptr;
   if (!buffStr.empty()) {
@@ -206,7 +156,6 @@
   } else {
     ALOGE("Could not provide an eglImage for fd = %d, EGLImageWrapper = %p", src->fd, this);
   }
-#endif
 
   return eglImage;
 }
diff --git a/gpu_tonemapper/EGLImageWrapper.h b/gpu_tonemapper/EGLImageWrapper.h
index ce1b344..a0a7522 100644
--- a/gpu_tonemapper/EGLImageWrapper.h
+++ b/gpu_tonemapper/EGLImageWrapper.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright 2015 The Android Open Source Project
@@ -21,9 +21,6 @@
 #define __TONEMAPPER_EGLIMAGEWRAPPER_H__
 
 #include <utils/LruCache.h>
-#ifndef TARGET_HEADLESS
-#include <linux/msm_ion.h>
-#endif
 #include <string>
 #include <map>
 #include "EGLImageBuffer.h"
@@ -39,24 +36,18 @@
      void operator()(int& buffInt, EGLImageBuffer*& eglImage);
      map<string, int>* buffStrbuffIntMapPtr = nullptr;
      bool mapClearPending = false;
-   #ifndef TARGET_ION_ABI_VERSION
-     int ion_fd = -1;
-   #endif
   };
 
   android::LruCache<int, EGLImageBuffer *>* eglImageBufferCache;
   map<string, int> buffStrbuffIntMap = {};
   DeleteEGLImageCallback* callback = 0;
- #ifndef TARGET_ION_ABI_VERSION
-   int ion_fd = -1;
- #else
-   uint64_t buffInt = 0;
- #endif
+  uint64_t buffInt = 0;
 
  public:
   EGLImageWrapper();
   ~EGLImageWrapper();
   EGLImageBuffer* wrap(const void *pvt_handle);
+  void Deinit();
 };
 
 #endif  // __TONEMAPPER_EGLIMAGEWRAPPER_H__
diff --git a/gralloc/QtiMapperExtensions.cpp b/gralloc/QtiMapperExtensions.cpp
index cace7ba..33cd23d 100644
--- a/gralloc/QtiMapperExtensions.cpp
+++ b/gralloc/QtiMapperExtensions.cpp
@@ -344,7 +344,7 @@
                                                   getFormatLayout_cb hidl_cb) {
   ALOGD_IF(DEBUG, "%s: Input parameters - wxh: %dx%d usage: 0x%" PRIu64 " format: %d", __FUNCTION__,
            width, height, usage, format);
-  auto err = Error::BAD_BUFFER;
+  auto err = Error::NONE;
   hidl_vec<PlaneLayout> plane_info;
   unsigned int alignedw = 0, alignedh = 0;
   int plane_count = 0;
@@ -353,34 +353,41 @@
   BufferInfo info(width, height, custom_format, usage);
   gralloc::GetAlignedWidthAndHeight(info, &alignedw, &alignedh);
   size = gralloc::GetSize(info, alignedw, alignedh);
+  gralloc::PlaneLayoutInfo plane_layout[8] = {};
   ALOGD_IF(DEBUG, "%s: Aligned width and height - wxh: %ux%u custom_format = %d", __FUNCTION__,
            alignedw, alignedh, custom_format);
   if (gralloc::IsYuvFormat(custom_format)) {
-    gralloc::PlaneLayoutInfo yuv_plane_info[8] = {};
     gralloc::GetYUVPlaneInfo(info, custom_format, alignedw, alignedh, flags, &plane_count,
-                             yuv_plane_info);
-    ALOGD_IF(DEBUG, "%s: Number of plane - %d, custom_format - %d", __FUNCTION__, plane_count,
-             custom_format);
-    plane_info.resize(plane_count);
-    for (int i = 0; i < plane_count; i++) {
-      plane_info[i].component = yuv_plane_info[i].component;
-      plane_info[i].h_subsampling = yuv_plane_info[i].h_subsampling;
-      plane_info[i].v_subsampling = yuv_plane_info[i].v_subsampling;
-      plane_info[i].offset = yuv_plane_info[i].offset;
-      plane_info[i].pixel_increment = yuv_plane_info[i].step;
-      plane_info[i].stride = yuv_plane_info[i].stride;
-      plane_info[i].stride_bytes = yuv_plane_info[i].stride_bytes;
-      plane_info[i].scanlines = yuv_plane_info[i].scanlines;
-      plane_info[i].size = yuv_plane_info[i].size;
-      ALOGD_IF(DEBUG, "%s: plane info: component - %d", __FUNCTION__, plane_info[i].component);
-      ALOGD_IF(DEBUG, "h_subsampling - %u, v_subsampling - %u, offset - %u, pixel_increment - %d",
-               plane_info[i].h_subsampling, plane_info[i].v_subsampling, plane_info[i].offset,
-               plane_info[i].pixel_increment);
-      ALOGD_IF(DEBUG, "stride_pixel - %d, stride_bytes - %d, scanlines - %d, size - %u",
-               plane_info[i].stride, plane_info[i].stride_bytes, plane_info[i].scanlines,
-               plane_info[i].size);
-    }
-    err = Error::NONE;
+                             plane_layout);
+  } else if (gralloc::IsUncompressedRGBFormat(custom_format) ||
+             gralloc::IsCompressedRGBFormat(custom_format)) {
+    gralloc::GetRGBPlaneInfo(info, custom_format, alignedw, alignedh, flags, &plane_count,
+                             plane_layout);
+  } else {
+    err = Error::BAD_BUFFER;
+    hidl_cb(err, size, plane_info);
+    return Void();
+  }
+  ALOGD_IF(DEBUG, "%s: Number of plane - %d, custom_format - %d", __FUNCTION__, plane_count,
+           custom_format);
+  plane_info.resize(plane_count);
+  for (int i = 0; i < plane_count; i++) {
+    plane_info[i].component = plane_layout[i].component;
+    plane_info[i].h_subsampling = plane_layout[i].h_subsampling;
+    plane_info[i].v_subsampling = plane_layout[i].v_subsampling;
+    plane_info[i].offset = plane_layout[i].offset;
+    plane_info[i].pixel_increment = plane_layout[i].step;
+    plane_info[i].stride = plane_layout[i].stride;
+    plane_info[i].stride_bytes = plane_layout[i].stride_bytes;
+    plane_info[i].scanlines = plane_layout[i].scanlines;
+    plane_info[i].size = plane_layout[i].size;
+    ALOGD_IF(DEBUG, "%s: plane info: component - %d", __FUNCTION__, plane_info[i].component);
+    ALOGD_IF(DEBUG, "h_subsampling - %u, v_subsampling - %u, offset - %u, pixel_increment - %d",
+             plane_info[i].h_subsampling, plane_info[i].v_subsampling, plane_info[i].offset,
+             plane_info[i].pixel_increment);
+    ALOGD_IF(DEBUG, "stride_pixel - %d, stride_bytes - %d, scanlines - %d, size - %u",
+             plane_info[i].stride, plane_info[i].stride_bytes, plane_info[i].scanlines,
+             plane_info[i].size);
   }
   hidl_cb(err, size, plane_info);
   return Void();
diff --git a/gralloc/gr_allocator.cpp b/gralloc/gr_allocator.cpp
index ef350b6..5b7efaa 100644
--- a/gralloc/gr_allocator.cpp
+++ b/gralloc/gr_allocator.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2019, 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
@@ -32,6 +32,10 @@
 #include <algorithm>
 #include <vector>
 
+#ifndef QMAA
+#include <linux/msm_ion.h>
+#endif
+
 #include "gr_allocator.h"
 #include "gr_utils.h"
 #include "gralloc_priv.h"
diff --git a/gralloc/gr_ion_alloc.cpp b/gralloc/gr_ion_alloc.cpp
index c9a74ce..68d3083 100644
--- a/gralloc/gr_ion_alloc.cpp
+++ b/gralloc/gr_ion_alloc.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2019, 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
@@ -31,15 +31,9 @@
 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
 #include <sys/ioctl.h>
 #include <sys/mman.h>
-#include <linux/ion.h>
-#ifndef QMAA
-#include <linux/msm_ion.h>
-#endif
 
-#if TARGET_ION_ABI_VERSION >= 2
 #include <linux/dma-buf.h>
 #include <ion/ion.h>
-#endif
 #include <stdlib.h>
 #include <fcntl.h>
 #include <log/log.h>
@@ -68,8 +62,6 @@
   return true;
 }
 
-#if TARGET_ION_ABI_VERSION >= 2  // Use libion APIs for new ion
-
 int IonAlloc::OpenIonDevice() {
   return ion_open();
 }
@@ -162,169 +154,6 @@
   return 0;
 }
 
-#else
-#ifndef TARGET_ION_ABI_VERSION  // Use old ion apis directly
-
-int IonAlloc::OpenIonDevice() {
-  return open(kIonDevice, O_RDONLY);
-}
-
-void IonAlloc::CloseIonDevice() {
-  if (ion_dev_fd_ > FD_INIT) {
-    close(ion_dev_fd_);
-  }
-
-  ion_dev_fd_ = FD_INIT;
-}
-
-int IonAlloc::AllocBuffer(AllocData *data) {
-  ATRACE_CALL();
-  int err = 0;
-  struct ion_handle_data handle_data;
-  struct ion_fd_data fd_data;
-  struct ion_allocation_data ion_alloc_data;
-
-  ion_alloc_data.len = data->size;
-  ion_alloc_data.align = data->align;
-  ion_alloc_data.heap_id_mask = data->heap_id;
-  ion_alloc_data.flags = data->flags;
-  ion_alloc_data.flags |= data->uncached ? 0 : ION_FLAG_CACHED;
-  std::string tag_name{};
-  if (ATRACE_ENABLED()) {
-    tag_name = "ION_IOC_ALLOC size: " + std::to_string(data->size);
-  }
-
-  ATRACE_BEGIN(tag_name.c_str());
-  if (ioctl(ion_dev_fd_, INT(ION_IOC_ALLOC), &ion_alloc_data)) {
-    err = -errno;
-    ALOGE("ION_IOC_ALLOC failed with error - %s", strerror(errno));
-    return err;
-  }
-  ATRACE_END();
-
-  fd_data.handle = ion_alloc_data.handle;
-  handle_data.handle = ion_alloc_data.handle;
-  ATRACE_BEGIN("ION_IOC_MAP");
-  if (ioctl(ion_dev_fd_, INT(ION_IOC_MAP), &fd_data)) {
-    err = -errno;
-    ALOGE("%s: ION_IOC_MAP failed with error - %s", __FUNCTION__, strerror(errno));
-    ioctl(ion_dev_fd_, INT(ION_IOC_FREE), &handle_data);
-    return err;
-  }
-  ATRACE_END();
-
-  data->fd = fd_data.fd;
-  data->ion_handle = handle_data.handle;
-  ALOGD_IF(DEBUG, "ion: Allocated buffer size:%zu fd:%d handle:0x%x", ion_alloc_data.len, data->fd,
-           data->ion_handle);
-
-  return 0;
-}
-
-int IonAlloc::FreeBuffer(void *base, unsigned int size, unsigned int offset, int fd,
-                         int ion_handle) {
-  ATRACE_CALL();
-  int err = 0;
-  ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d handle:0x%x", base, size, fd,
-           ion_handle);
-
-  if (base) {
-    err = UnmapBuffer(base, size, offset);
-  }
-
-  if (ion_handle > 0) {
-    struct ion_handle_data handle_data;
-    handle_data.handle = ion_handle;
-    ioctl(ion_dev_fd_, INT(ION_IOC_FREE), &handle_data);
-  }
-  close(fd);
-  return err;
-}
-
-int IonAlloc::ImportBuffer(int fd) {
-  struct ion_fd_data fd_data;
-  int err = 0;
-  fd_data.fd = fd;
-  if (ioctl(ion_dev_fd_, INT(ION_IOC_IMPORT), &fd_data)) {
-    err = -errno;
-    ALOGE("%s: ION_IOC_IMPORT failed with error - %s", __FUNCTION__, strerror(errno));
-    return err;
-  }
-  return fd_data.handle;
-}
-
-int IonAlloc::CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op,
-                          int /*fd*/) {
-  if (op == CACHE_READ_DONE)  {
-    return 0;
-  }
-
-#ifndef QMAA
-  ATRACE_CALL();
-  ATRACE_INT("operation id", op);
-  struct ion_flush_data flush_data;
-  int err = 0;
-
-  flush_data.handle = handle;
-  flush_data.vaddr = base;
-  // offset and length are unsigned int
-  flush_data.offset = offset;
-  flush_data.length = size;
-
-  struct ion_custom_data d;
-  switch (op) {
-    case CACHE_CLEAN:
-      d.cmd = ION_IOC_CLEAN_CACHES;
-      break;
-    case CACHE_INVALIDATE:
-      d.cmd = ION_IOC_INV_CACHES;
-      break;
-    case CACHE_CLEAN_AND_INVALIDATE:
-    default:
-      d.cmd = ION_IOC_CLEAN_INV_CACHES;
-  }
-
-  d.arg = (unsigned long)(&flush_data);  // NOLINT
-  if (ioctl(ion_dev_fd_, INT(ION_IOC_CUSTOM), &d)) {
-    err = -errno;
-    ALOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s", __FUNCTION__, strerror(errno));
-    return err;
-  }
-#endif
-  return 0;
-}
-
-#else  // This ion version is not supported
-
-int IonAlloc::OpenIonDevice() {
-  return -EINVAL;
-}
-
-void IonAlloc::CloseIonDevice() {
-}
-
-int IonAlloc::AllocBuffer(AllocData * /*data*/) {
-  return -EINVAL;
-}
-
-int IonAlloc::FreeBuffer(void * /*base*/, unsigned int /*size*/, unsigned int /*offset*/,
-                         int /*fd*/, int /*ion_handle*/) {
-  return -EINVAL;
-}
-
-int IonAlloc::ImportBuffer(int /*fd*/) {
-  return -EINVAL;
-}
-
-int IonAlloc::CleanBuffer(void * /*base*/, unsigned int /*size*/, unsigned int /*offset*/,
-                          int /*handle*/, int /*op*/, int /*fd*/) {
-  return -EINVAL;
-}
-
-#endif
-#endif  // TARGET_ION_ABI_VERSION
-
-
 int IonAlloc::MapBuffer(void **base, unsigned int size, unsigned int offset, int fd) {
   ATRACE_CALL();
   int err = 0;
diff --git a/gralloc/gr_ion_alloc.h b/gralloc/gr_ion_alloc.h
index 13474f5..e84a510 100644
--- a/gralloc/gr_ion_alloc.h
+++ b/gralloc/gr_ion_alloc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2019, 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
@@ -30,10 +30,6 @@
 #ifndef __GR_ION_ALLOC_H__
 #define __GR_ION_ALLOC_H__
 
-#ifndef QMAA
-#include <linux/msm_ion.h>
-#endif
-
 #define FD_INIT -1
 
 namespace gralloc {
@@ -74,10 +70,6 @@
   int CleanBuffer(void *base, unsigned int size, unsigned int offset, int handle, int op, int fd);
 
  private:
-#ifndef TARGET_ION_ABI_VERSION
-  const char *kIonDevice = "/dev/ion";
-#endif
-
   int OpenIonDevice();
   void CloseIonDevice();
 
diff --git a/gralloc/gr_utils.cpp b/gralloc/gr_utils.cpp
index 49dcfb4..16e41b1 100644
--- a/gralloc/gr_utils.cpp
+++ b/gralloc/gr_utils.cpp
@@ -853,6 +853,28 @@
   return size;
 }
 
+unsigned int GetRgbMetaSize(int format, uint32_t width, uint32_t height, uint64_t usage) {
+  unsigned int meta_size = 0;
+  if (!IsUBwcEnabled(format, usage)) {
+    return meta_size;
+  }
+  uint32_t bpp = GetBppForUncompressedRGB(format);
+  switch (format) {
+    case HAL_PIXEL_FORMAT_BGR_565:
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+    case HAL_PIXEL_FORMAT_RGBA_1010102:
+    case HAL_PIXEL_FORMAT_RGBX_1010102:
+    case HAL_PIXEL_FORMAT_RGBA_FP16:
+      meta_size = GetRgbUBwcMetaBufferSize(width, height, bpp);
+      break;
+    default:
+      ALOGE("%s:Unsupported RGB format: 0x%x", __FUNCTION__, format);
+      break;
+  }
+  return meta_size;
+}
+
 int GetRgbDataAddress(private_handle_t *hnd, void **rgb_data) {
   int err = 0;
 
@@ -866,23 +888,8 @@
     *rgb_data = reinterpret_cast<void *>(hnd->base);
     return err;
   }
+  unsigned int meta_size = GetRgbMetaSize(hnd->format, hnd->width, hnd->height, hnd->usage);
 
-  unsigned int meta_size = 0;
-  uint32_t bpp = GetBppForUncompressedRGB(hnd->format);
-  switch (hnd->format) {
-    case HAL_PIXEL_FORMAT_BGR_565:
-    case HAL_PIXEL_FORMAT_RGBA_8888:
-    case HAL_PIXEL_FORMAT_RGBX_8888:
-    case HAL_PIXEL_FORMAT_RGBA_1010102:
-    case HAL_PIXEL_FORMAT_RGBX_1010102:
-    case HAL_PIXEL_FORMAT_RGBA_FP16:
-      meta_size = GetRgbUBwcMetaBufferSize(hnd->width, hnd->height, bpp);
-      break;
-    default:
-      ALOGE("%s:Unsupported RGB format: 0x%x", __FUNCTION__, hnd->format);
-      err = -EINVAL;
-      break;
-  }
   *rgb_data = reinterpret_cast<void *>(hnd->base + meta_size);
 
   return err;
@@ -1652,4 +1659,40 @@
   }
 }
 
+bool HasAlphaComponent(int32_t format) {
+  switch (format) {
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+    case HAL_PIXEL_FORMAT_RGBA_5551:
+    case HAL_PIXEL_FORMAT_RGBA_4444:
+    case HAL_PIXEL_FORMAT_RGBA_1010102:
+    case HAL_PIXEL_FORMAT_ARGB_2101010:
+    case HAL_PIXEL_FORMAT_BGRA_1010102:
+    case HAL_PIXEL_FORMAT_ABGR_2101010:
+    case HAL_PIXEL_FORMAT_RGBA_FP16:
+      return true;
+    default:
+      return false;
+  }
+}
+
+void GetRGBPlaneInfo(const BufferInfo &info, int32_t format, int32_t width, int32_t height,
+                     int32_t /* flags */, int *plane_count, PlaneLayoutInfo *plane_info) {
+  uint64_t usage = info.usage;
+  *plane_count = 1;
+  plane_info->component =
+      (PlaneComponent)(PLANE_COMPONENT_R | PLANE_COMPONENT_G | PLANE_COMPONENT_B);
+  if (HasAlphaComponent(format)) {
+    plane_info->component = (PlaneComponent)(plane_info->component | PLANE_COMPONENT_A);
+  }
+  plane_info->size = GetSize(info, width, height);
+  plane_info->step = GetBpp(format);
+  plane_info->offset = GetRgbMetaSize(format, width, height, usage);
+  plane_info->h_subsampling = 0;
+  plane_info->v_subsampling = 0;
+  plane_info->stride = width;
+  plane_info->stride_bytes = width * plane_info->step;
+  plane_info->scanlines = height;
+}
+
 }  // namespace gralloc
diff --git a/gralloc/gr_utils.h b/gralloc/gr_utils.h
index bc5a670..6dbe889 100644
--- a/gralloc/gr_utils.h
+++ b/gralloc/gr_utils.h
@@ -145,6 +145,9 @@
 int GetYUVPlaneInfo(const private_handle_t *hnd, struct android_ycbcr ycbcr[2]);
 int GetYUVPlaneInfo(const BufferInfo &info, int32_t format, int32_t width, int32_t height,
                     int32_t flags, int *plane_count, PlaneLayoutInfo plane_info[8]);
+void GetRGBPlaneInfo(const BufferInfo &info, int32_t format, int32_t width, int32_t height,
+                     int32_t flags, int *plane_count, PlaneLayoutInfo *plane_info);
+unsigned int GetRgbMetaSize(int format, uint32_t width, uint32_t height, uint64_t usage);
 void GetYuvSubSamplingFactor(int32_t format, int *h_subsampling, int *v_subsampling);
 void CopyPlaneLayoutInfotoAndroidYcbcr(uint64_t base, int plane_count, PlaneLayoutInfo *plane_info,
                                        struct android_ycbcr *ycbcr);
@@ -180,6 +183,7 @@
 int GetCustomFormatFlags(int format, uint64_t usage, int *custom_format, uint64_t *priv_flags);
 int GetBufferType(int inputFormat);
 bool IsGPUFlagSupported(uint64_t usage);
+bool HasAlphaComponent(int32_t format);
 }  // namespace gralloc
 
 #endif  // __GR_UTILS_H__
diff --git a/include/display_properties.h b/include/display_properties.h
index 163f7ca..5c647b5 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -105,6 +105,7 @@
 #define DISABLE_DEFER_POWER_STATE            DISPLAY_PROP("disable_defer_power_state")
 #define ENABLE_OPTIMIZE_REFRESH              DISPLAY_PROP("enable_optimize_refresh")
 #define DISABLE_PARALLEL_CACHE               DISPLAY_PROP("disable_parallel_cache")
+#define DISABLE_LAYER_STITCH                 DISPLAY_PROP("disable_layer_stitch")
 // Disable 3d tonemap support for UI layers
 #define DISABLE_UI_3D_TONEMAP                DISPLAY_PROP("disable_ui_3d_tonemap")
 #define QDCM_DISABLE_FACTORY_MODE_PROP       DISPLAY_PROP("qdcm.disable_factory_mode")
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 4f8edb3..41543d0 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -152,6 +152,12 @@
    */
   PLANE_SET_MULTIRECT_MODE,
   /*
+   * Op: Sets sspp layout on this plane.
+   * Arg: uint32_t - Plane ID
+   *      uint32_t - SSPP Layout Index
+   */
+  PLANE_SET_SSPP_LAYOUT,
+  /*
    * Op: Sets rotator output frame buffer ID for plane.
    * Arg: uint32_t - Plane ID
    *      uint32_t - Framebuffer ID
@@ -519,6 +525,8 @@
   uint32_t rotation_limit_index = 0;
   uint32_t line_width_constraints_count = 0;
   std::vector< std::pair <uint32_t, uint32_t> > line_width_limits;
+  uint32_t num_mnocports;
+  uint32_t mnoc_bus_width;
 };
 
 enum struct DRMPlaneType {
@@ -580,6 +588,9 @@
   DUAL_LM_MERGE,
   DUAL_LM_MERGE_DSC,
   DUAL_LM_DSCMERGE,
+  QUAD_LM_MERGE,
+  QUAD_LM_DSCMERGE,
+  QUAD_LM_MERGE_DSC,
   PPSPLIT,
 };
 
@@ -811,6 +822,12 @@
   SERIAL = 2,
 };
 
+enum struct DRMSSPPLayoutIndex {
+  NONE = 0,
+  LEFT = 1,
+  RIGHT = 2,
+};
+
 enum struct DRMCWbCaptureMode {
   MIXER_OUT = 0,
   DSPP_OUT = 1,
diff --git a/sde-drm/drm_atomic_req.cpp b/sde-drm/drm_atomic_req.cpp
index a33bb8d..8f38133 100644
--- a/sde-drm/drm_atomic_req.cpp
+++ b/sde-drm/drm_atomic_req.cpp
@@ -83,7 +83,8 @@
     case DRMOps::PLANE_SET_EXCL_RECT:
     case DRMOps::PLANE_SET_INVERSE_PMA:
     case DRMOps::PLANE_SET_DGM_CSC_CONFIG:
-    case DRMOps::PLANE_SET_POST_PROC: {
+    case DRMOps::PLANE_SET_POST_PROC:
+    case DRMOps::PLANE_SET_SSPP_LAYOUT: {
       drm_mgr_->GetPlaneMgr()->Perform(opcode, obj_id, drm_atomic_req_, args);
     } break;
     case DRMOps::CRTC_SET_POST_PROC:
diff --git a/sde-drm/drm_connector.cpp b/sde-drm/drm_connector.cpp
index 9ae5d0a..aeb9d7c 100644
--- a/sde-drm/drm_connector.cpp
+++ b/sde-drm/drm_connector.cpp
@@ -159,6 +159,9 @@
   if (topology == "sde_dualpipemerge") return DRMTopology::DUAL_LM_MERGE;
   if (topology == "sde_dualpipemerge_dsc") return DRMTopology::DUAL_LM_MERGE_DSC;
   if (topology == "sde_dualpipe_dscmerge") return DRMTopology::DUAL_LM_DSCMERGE;
+  if (topology == "sde_quadpipemerge") return DRMTopology::QUAD_LM_MERGE;
+  if (topology == "sde_quadpipe_dscmerge") return DRMTopology::QUAD_LM_DSCMERGE;
+  if (topology == "sde_quadpipe_3dmerge_dsc") return DRMTopology::QUAD_LM_MERGE_DSC;
   if (topology == "sde_ppsplit") return DRMTopology::PPSPLIT;
   return DRMTopology::UNKNOWN;
 }
diff --git a/sde-drm/drm_crtc.cpp b/sde-drm/drm_crtc.cpp
index ef1e692..f8890d1 100644
--- a/sde-drm/drm_crtc.cpp
+++ b/sde-drm/drm_crtc.cpp
@@ -349,6 +349,8 @@
   string solidfill_stages = "dim_layer_v1_max_layers=";
   string has_hdr = "has_hdr=";
   string min_prefill_lines = "min_prefill_lines=";
+  string num_mnocports = "num_mnoc_ports=";
+  string mnoc_bus_width = "axi_bus_width=";
 
   crtc_info_.max_solidfill_stages = 0;  // default _
   string dest_scaler_count = "dest_scaler_count=";
@@ -439,6 +441,10 @@
       crtc_info_.min_prefill_lines = std::stoi(string(line, min_prefill_lines.length()));
     } else if (line.find(sec_ui_blendstage) != string::npos) {
       crtc_info_.secure_disp_blend_stage = std::stoi(string(line, (sec_ui_blendstage).length()));
+    } else if (line.find(num_mnocports) != string::npos) {
+      crtc_info_.num_mnocports = std::stoi(string(line, num_mnocports.length()));
+    } else if (line.find(mnoc_bus_width) != string::npos) {
+      crtc_info_.mnoc_bus_width = std::stoi(string(line, mnoc_bus_width.length()));
     } else if (line.find(linewidth_constraints) != string::npos) {
       crtc_info_.line_width_constraints_count =
                             std::stoi(string(line, (linewidth_constraints).length()));
diff --git a/sde-drm/drm_dpps_mgr_imp.cpp b/sde-drm/drm_dpps_mgr_imp.cpp
index 68ed4a5..99a690b 100644
--- a/sde-drm/drm_dpps_mgr_imp.cpp
+++ b/sde-drm/drm_dpps_mgr_imp.cpp
@@ -203,6 +203,7 @@
 }
 
 void DRMDppsManagerImp::Init(int fd, drmModeRes* res) {
+  std::lock_guard<std::mutex> guard(api_lock_);
   int ret = 0;
 
   if (fd < 0 || !res) {
@@ -315,6 +316,7 @@
 }
 
 void DRMDppsManagerImp::CacheDppsFeature(uint32_t obj_id, va_list args) {
+  std::lock_guard<std::mutex> guard(api_lock_);
   uint32_t feature_id = va_arg(args, uint32_t);
   uint64_t value = va_arg(args, uint64_t);
   struct DRMDppsPropInfo* info;
@@ -341,6 +343,7 @@
 }
 
 void DRMDppsManagerImp::CommitDppsFeatures(drmModeAtomicReq *req, const DRMDisplayToken &tok) {
+  std::lock_guard<std::mutex> guard(api_lock_);
   int ret = 0;
 
   if (!req)
@@ -398,6 +401,7 @@
 
 void DRMDppsManagerImp::GetDppsFeatureInfo(DRMDppsFeatureInfo *info)
 {
+  std::lock_guard<std::mutex> guard(api_lock_);
   int ret = 0;
   struct DRMDppsPropInfo* prop_info;
 
diff --git a/sde-drm/drm_dpps_mgr_imp.h b/sde-drm/drm_dpps_mgr_imp.h
index eefb213..a264e01 100644
--- a/sde-drm/drm_dpps_mgr_imp.h
+++ b/sde-drm/drm_dpps_mgr_imp.h
@@ -33,6 +33,7 @@
 #include "drm_interface.h"
 #include "drm_property.h"
 #include "drm_dpps_mgr_intf.h"
+#include <mutex>
 
 namespace sde_drm {
 
@@ -73,6 +74,7 @@
   int drm_fd_ = -1;
   std::vector<std::pair<uint32_t, drm_msm_ltm_buffers_ctrl>> ltm_buffers_ctrl_map_;
   std::vector<std::pair<uint32_t, DRMDppsLtmBuffers>> ltm_buffers_map_;
+  std::mutex api_lock_;
 };
 
 class DRMDppsManagerDummyImp : public DRMDppsManagerIntf {
diff --git a/sde-drm/drm_plane.cpp b/sde-drm/drm_plane.cpp
index 2939df2..459ba67 100644
--- a/sde-drm/drm_plane.cpp
+++ b/sde-drm/drm_plane.cpp
@@ -969,6 +969,18 @@
       }
     } break;
 
+    case DRMOps::PLANE_SET_SSPP_LAYOUT: {
+      if (!prop_mgr_.IsPropertyAvailable(DRMProperty::SDE_SSPP_LAYOUT)) {
+        DRM_LOGD("SSPP_LAYOUT property isn't exposed");
+        break;
+      }
+      DRMSSPPLayoutIndex layout_index = (DRMSSPPLayoutIndex) va_arg(args, uint32_t);
+      prop_id = prop_mgr_.GetPropertyId(DRMProperty::SDE_SSPP_LAYOUT);
+      AddProperty(req, obj_id, prop_id, (uint32_t)layout_index , true /* cache */,
+                  tmp_prop_val_map_);
+      DRM_LOGD("Plane %d: Setting SSPP Layout to %d", obj_id, layout_index);
+    } break;
+
     default:
       DRM_LOGE("Invalid opcode %d for DRM Plane %d", code, obj_id);
   }
diff --git a/sde-drm/drm_property.cpp b/sde-drm/drm_property.cpp
index c144aad..5dadd2b 100644
--- a/sde-drm/drm_property.cpp
+++ b/sde-drm/drm_property.cpp
@@ -162,6 +162,7 @@
   if (name == "frame_trigger_mode") { return DRMProperty::FRAME_TRIGGER; }
   if (name == "Colorspace") { return DRMProperty::COLORSPACE; }
   if (name == "supported_colorspaces") { return DRMProperty::SUPPORTED_COLORSPACES; }
+  if (name == "sspp_layout") { return DRMProperty::SDE_SSPP_LAYOUT; }
 
   return DRMProperty::INVALID;
 }
diff --git a/sde-drm/drm_property.h b/sde-drm/drm_property.h
index dcda7aa..9ec8a83 100644
--- a/sde-drm/drm_property.h
+++ b/sde-drm/drm_property.h
@@ -167,6 +167,7 @@
   FRAME_TRIGGER,
   COLORSPACE,
   SUPPORTED_COLORSPACES,
+  SDE_SSPP_LAYOUT,
 
   // Insert above
   MAX
diff --git a/sdm/include/core/core_interface.h b/sdm/include/core/core_interface.h
index 90b496d..072b677 100644
--- a/sdm/include/core/core_interface.h
+++ b/sdm/include/core/core_interface.h
@@ -258,6 +258,14 @@
   */
   virtual DisplayError GetMaxDisplaysSupported(DisplayType type, int32_t *max_displays) = 0;
 
+  /*! @brief Method which returns true if the given format is supported by rotator otherwise false
+
+    @param[in] \link LayerBufferFormat \endlink
+
+    @return returns true if the given format is supported by rotator otherwise false
+  */
+  virtual bool IsRotatorSupportedFormat(LayerBufferFormat format) = 0;
+
  protected:
   virtual ~CoreInterface() { }
 };
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index ee2b731..c1dc190 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -670,6 +670,14 @@
   */
   virtual DisplayError GetPanelBrightness(float *brightness) = 0;
 
+  /*! @brief Method to get the max brightness level of the display
+
+    @param[out] max_brightness level
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetPanelMaxBrightness(uint32_t *max_brightness_level) = 0;
+
   /*! @brief Method to set layer mixer resolution.
 
     @param[in] width layer mixer width
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index 8a03bfc..ec3b38e 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -80,6 +80,9 @@
                             //!< This composition type is used only if GPUTarget layer is provided
                             //!< in a composition cycle.
 
+  kCompositionStitch,       //!< This layer will be drawn onto the target buffer by GPU. No blend
+                            //!< required.
+
   kCompositionSDE,          //!< This layer will be composed by SDE. It must not be composed by
                             //!< GPU or Blit.
 
@@ -104,6 +107,9 @@
                             //!< Only one layer shall be marked as target buffer by the caller.
                             //!< GPU target layer shall be placed after all application layers
                             //!< in the layer stack.
+
+  kCompositionStitchTarget,  //!< This layer will hold result of composition for layers marked fo
+                             //!< Blit composition.
 };
 
 enum LayerUpdate {
@@ -341,6 +347,9 @@
                                                    //!< fit into this rectangle. The origin is the
                                                    //!< top-left corner of the screen.
 
+  LayerRect stitch_dst_rect = {};                  //!< The target position where the frame will be
+                                                   //!< rendered onto internal FrameBuffer.
+
   std::vector<LayerRect> visible_regions = {};     //!< Visible rectangular areas in screen space.
                                                    //!< The visible region includes areas overlapped
                                                    //!< by a translucent layer.
diff --git a/sdm/include/private/extension_interface.h b/sdm/include/private/extension_interface.h
index b889cab..6545c41 100644
--- a/sdm/include/private/extension_interface.h
+++ b/sdm/include/private/extension_interface.h
@@ -63,6 +63,7 @@
 
   virtual DisplayError CreateStrategyExtn(int32_t display_id, DisplayType type,
                                           BufferAllocator *buffer_allocator,
+                                          BufferSyncHandler *buffer_sync_handler,
                                           const HWResourceInfo &hw_resource_info,
                                           const HWPanelInfo &hw_panel_info,
                                           const HWMixerAttributes &mixer_attributes,
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 42822a0..8997cc6 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -145,9 +145,18 @@
   kDualLMMerge,
   kDualLMMergeDSC,
   kDualLMDSCMerge,
+  kQuadLMMerge,
+  kQuadLMDSCMerge,
+  kQuadLMMergeDSC,
   kPPSplit,
 };
 
+enum HWMixerSplit {
+  kNoSplit,
+  kDualSplit,
+  kQuadSplit,
+};
+
 enum HwHdrEotf {
   kHdrEOTFInvalid = 0,
   kHdrEOTFSDR = 0x1,
@@ -333,6 +342,8 @@
   uint32_t line_width_constraints_count = 0;
   vector< pair <uint32_t, uint32_t> > line_width_limits;
   vector< pair <uint32_t, uint32_t> > line_width_constraints;
+  uint32_t num_mnocports = 2;
+  uint32_t mnoc_bus_width = 32;
 };
 
 struct HWSplitInfo {
@@ -656,9 +667,10 @@
 };
 
 struct HWLayersInfo {
-  LayerStack *stack = NULL;        // Input layer stack. Set by the caller.
-  uint32_t app_layer_count = 0;    // Total number of app layers. Must not be 0.
-  uint32_t gpu_target_index = 0;   // GPU target layer index. 0 if not present.
+  LayerStack *stack = NULL;          // Input layer stack. Set by the caller.
+  uint32_t app_layer_count = 0;      // Total number of app layers. Must not be 0.
+  uint32_t gpu_target_index = 0;     // GPU target layer index. 0 if not present.
+  uint32_t stitch_target_index = 0;  // Blit target layer index. 0 if not present.
   std::vector<ColorPrimaries> wide_color_primaries = {};  // list of wide color primaries
 
   std::vector<Layer> hw_layers = {};  // Layers which need to be programmed on the HW
@@ -760,12 +772,14 @@
 struct HWMixerAttributes {
   uint32_t width = 0;                                  // Layer mixer width
   uint32_t height = 0;                                 // Layer mixer height
-  uint32_t split_left = 0;
+  uint32_t split_left = 0;                             // Left portion of layer mixer
+  HWMixerSplit split_type = kNoSplit;                  // Mixer topology
   LayerBufferFormat output_format = kFormatRGB101010;  // Layer mixer output format
 
   bool operator !=(const HWMixerAttributes &mixer_attributes) {
     return ((width != mixer_attributes.width) ||
             (height != mixer_attributes.height) ||
+            (split_type != mixer_attributes.split_type) ||
             (output_format != mixer_attributes.output_format) ||
             (split_left != mixer_attributes.split_left));
   }
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index 56db4ce..4baef57 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -73,6 +73,7 @@
   virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
                                              const DisplayDetailEnhancerData &de_data) = 0;
   virtual DisplayError Perform(int cmd, ...) = 0;
+  virtual bool IsRotatorSupportedFormat(LayerBufferFormat format) = 0;
   virtual ~ResourceInterface() { }
 };
 
diff --git a/sdm/include/utils/constants.h b/sdm/include/utils/constants.h
index 691e88c..83f198b 100644
--- a/sdm/include/utils/constants.h
+++ b/sdm/include/utils/constants.h
@@ -84,6 +84,7 @@
                                                              0.0, 1.0, 0.0, 0.0,
                                                              0.0, 0.0, 1.0, 0.0,
                                                              0.0, 0.0, 0.0, 1.0 };
+  const float kBufferHeightFactor = 1.5f;
 
   typedef void * Handle;
 
diff --git a/sdm/include/utils/fence.h b/sdm/include/utils/fence.h
new file mode 100644
index 0000000..94bb01b
--- /dev/null
+++ b/sdm/include/utils/fence.h
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2019, 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 __FENCE_H__
+#define __FENCE_H__
+
+#include <core/buffer_sync_handler.h>
+#include <unistd.h>
+#include <utility>
+#include <memory>
+#include <string>
+
+namespace sdm {
+
+using std::shared_ptr;
+using std::string;
+
+class Fence {
+ public:
+  ~Fence();
+
+  static void Set(BufferSyncHandler *buffer_sync_handler);
+
+  // Ownership of the file descriptor is transferred to this method.
+  // Client must not close the file descriptor anymore regardless of the object creation status.
+  // nullptr will be retured for invalid fd i.e. -1.
+  static shared_ptr<Fence> Create(int fd);
+
+  // Ownership of returned fd lies with caller. Caller must explicitly close the fd.
+  static int Dup(const shared_ptr<Fence> &fence);
+
+  static shared_ptr<Fence> Merge(const shared_ptr<Fence> &fence1, const shared_ptr<Fence> &fence2);
+  static DisplayError Wait(const shared_ptr<Fence> &fence);
+  static DisplayError Wait(const shared_ptr<Fence> &fence, int timeout);
+  static string GetStr(const shared_ptr<Fence> &fence);
+
+ private:
+  explicit Fence(int fd);
+  Fence(const Fence &fence) = delete;
+  Fence& operator=(const Fence &fence) = delete;
+  Fence(Fence &&fence) = delete;
+  Fence& operator=(Fence &&fence) = delete;
+  static int Get(const shared_ptr<Fence> &fence);
+
+  static BufferSyncHandler *buffer_sync_handler_;
+  int fd_ = -1;
+};
+
+}  // namespace sdm
+
+#endif  // __FENCE_H__
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 6ee5032..2500bd5 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -63,6 +63,7 @@
   hw_res_info_ = hw_res_info;
   buffer_allocator_ = buffer_allocator;
   extension_intf_ = extension_intf;
+  sync_handler_ = buffer_sync_handler;
 
   return error;
 }
@@ -96,8 +97,9 @@
   }
 
   Strategy *&strategy = display_comp_ctx->strategy;
-  strategy = new Strategy(extension_intf_, buffer_allocator_, display_id, type, hw_res_info_,
-                          hw_panel_info, mixer_attributes, display_attributes, fb_config);
+  strategy = new Strategy(extension_intf_, buffer_allocator_, sync_handler_, display_id, type,
+                          hw_res_info_, hw_panel_info, mixer_attributes, display_attributes,
+                          fb_config);
   if (!strategy) {
     DLOGE("Unable to create strategy");
     delete display_comp_ctx;
@@ -348,8 +350,6 @@
     return error;
   }
 
-  error = resource_intf_->Stop(display_resource_ctx, hw_layers);
-
   return error;
 }
 
@@ -411,6 +411,12 @@
   DisplayCompositionContext *display_comp_ctx =
                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
 
+  Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+  error = resource_intf_->Stop(display_resource_ctx, hw_layers);
+  if (error != kErrorNone) {
+    DLOGE("Resource stop failed for display = %d", display_comp_ctx->display_type);
+  }
+
   error = resource_intf_->PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
   if (error != kErrorNone) {
     return error;
@@ -684,4 +690,12 @@
   return res_wait_needed;
 }
 
+bool CompManager::IsRotatorSupportedFormat(LayerBufferFormat format) {
+  if (resource_intf_) {
+    return resource_intf_->IsRotatorSupportedFormat(format);
+  }
+
+  return false;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 8a6b665..6846eda 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -89,6 +89,7 @@
   DisplayError CheckEnforceSplit(Handle comp_handle, uint32_t new_refresh_rate);
   DppsControlInterface* GetDppsControlIntf() { return dpps_ctrl_intf_; }
   bool CheckResourceState(Handle display_ctx);
+  bool IsRotatorSupportedFormat(LayerBufferFormat format);
 
  private:
   static const int kMaxThermalLevel = 3;
@@ -131,6 +132,7 @@
   uint32_t max_sde_ext_layers_ = 0;
   uint32_t max_sde_builtin_layers_ = 2;
   DppsControlInterface *dpps_ctrl_intf_ = NULL;
+  BufferSyncHandler *sync_handler_ = NULL;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/core_impl.cpp b/sdm/libs/core/core_impl.cpp
index 8aaac7c..9b0eaec 100644
--- a/sdm/libs/core/core_impl.cpp
+++ b/sdm/libs/core/core_impl.cpp
@@ -254,5 +254,10 @@
   return hw_info_intf_->GetMaxDisplaysSupported(type, max_displays);
 }
 
+bool CoreImpl::IsRotatorSupportedFormat(LayerBufferFormat format) {
+  SCOPE_LOCK(locker_);
+  return comp_mgr_.IsRotatorSupportedFormat(format);
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/core_impl.h b/sdm/libs/core/core_impl.h
index 94e61d7..4af2311 100644
--- a/sdm/libs/core/core_impl.h
+++ b/sdm/libs/core/core_impl.h
@@ -62,6 +62,7 @@
   virtual DisplayError GetFirstDisplayInterfaceType(HWDisplayInterfaceInfo *hw_disp_info);
   virtual DisplayError GetDisplaysStatus(HWDisplaysInfo *hw_displays_info);
   virtual DisplayError GetMaxDisplaysSupported(DisplayType type, int32_t *max_displays);
+  virtual bool IsRotatorSupportedFormat(LayerBufferFormat format);
 
  protected:
   Locker locker_;
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 3087280..b355749 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -216,24 +216,27 @@
     }
     if (layer->composition == kCompositionGPUTarget) {
       hw_layers_info.gpu_target_index = hw_layers_info.app_layer_count;
+    } else if (layer->composition == kCompositionStitchTarget) {
+      hw_layers_info.stitch_target_index = hw_layers_info.gpu_target_index + 1;
       break;
+    } else {
+      hw_layers_info.app_layer_count++;
     }
-    hw_layers_info.app_layer_count++;
     if (IsWideColor(layer->input_buffer.color_metadata.colorPrimaries)) {
       hw_layers_info.wide_color_primaries.push_back(
           layer->input_buffer.color_metadata.colorPrimaries);
     }
     if (layer->flags.is_game) {
-        hw_layers_info.game_present = true;
+      hw_layers_info.game_present = true;
     }
   }
 
-  DLOGD_IF(kTagDisplay,
-           "LayerStack layer_count: %d, app_layer_count: %d, "
-           "gpu_target_index: %d, game_present: %d, display: %d-%d",
-           layers.size(), hw_layers_info.app_layer_count,
-           hw_layers_info.gpu_target_index, hw_layers_info.game_present,
-           display_id_, display_type_);
+  hw_layers_info.stitch_target_index = hw_layers_info.gpu_target_index + 1;
+  DLOGD_IF(kTagDisplay, "LayerStack layer_count: %d, app_layer_count: %d, "
+                        "gpu_target_index: %d, stitch_index: %d game_present: %d, display: %d-%d",
+                        layers.size(), hw_layers_info.app_layer_count,
+                        hw_layers_info.gpu_target_index, hw_layers_info.stitch_target_index,
+                        hw_layers_info.game_present, display_id_, display_type_);
 
   if (!hw_layers_info.app_layer_count) {
     DLOGW("Layer count is zero");
@@ -435,6 +438,7 @@
     return error;
   }
 
+  comp_manager_->SetSafeMode(false);
 
   DLOGI_IF(kTagDisplay, "Exiting commit for display: %d-%d", display_id_, display_type_);
 
@@ -628,6 +632,11 @@
     active_ = active;
     state_ = state;
     comp_manager_->SetDisplayState(display_comp_ctx_, state, release_fence ? *release_fence : -1);
+    // If previously requested doze state is still pending reset it on any new display state request
+    // and handle the new request.
+    if (state_ != kStateDoze) {
+      pending_doze_ = false;
+    }
   }
 
   // Handle vsync pending on resume, Since the power on commit is synchronous we pass -1 as retire
@@ -898,11 +907,13 @@
 
 const char * DisplayBase::GetName(const LayerComposition &composition) {
   switch (composition) {
-  case kCompositionGPU:         return "GPU";
-  case kCompositionSDE:         return "SDE";
-  case kCompositionCursor:      return "CURSOR";
-  case kCompositionGPUTarget:   return "GPU_TARGET";
-  default:                      return "UNKNOWN";
+  case kCompositionGPU:           return "GPU";
+  case kCompositionSDE:           return "SDE";
+  case kCompositionCursor:        return "CURSOR";
+  case kCompositionStitch:        return "STITCH";
+  case kCompositionGPUTarget:     return "GPU_TARGET";
+  case kCompositionStitchTarget:  return "STITCH_TARGET";
+  default:                        return "UNKNOWN";
   }
 }
 
@@ -980,6 +991,10 @@
     return kErrorNotSupported;
   }
 
+  if (color_mode.empty()) {
+    return kErrorParameters;
+  }
+
   DisplayError error = kErrorNone;
   std::string dynamic_range = kSdr, str_render_intent;
   if (IsSupportColorModeAttribute(color_mode)) {
@@ -1963,6 +1978,11 @@
 PrimariesTransfer DisplayBase::GetBlendSpaceFromColorMode() {
   PrimariesTransfer pt = {};
   auto current_color_attr_ = color_mode_attr_map_.find(current_color_mode_);
+  if (current_color_attr_ == color_mode_attr_map_.end()) {
+    DLOGE("The attritbutes is not present in color mode: %s", current_color_mode_.c_str());
+    return pt;
+  }
+
   AttrVal attr = current_color_attr_->second;
   std::string color_gamut = kNative, dynamic_range = kSdr, pic_quality = kStandard;
   std::string transfer = {};
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 1151ce6..00d1799 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -120,6 +120,9 @@
   virtual DisplayError GetPanelBrightness(float *brightness) {
     return kErrorNotSupported;
   }
+  virtual DisplayError GetPanelMaxBrightness(uint32_t *max_brightness_level) {
+    return kErrorNotSupported;
+  }
   virtual DisplayError SetVSyncState(bool enable);
   virtual void SetIdleTimeoutMs(uint32_t active_ms) {}
   virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index 3a5a8a1..076e2ef 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -523,6 +523,20 @@
   return kErrorNone;
 }
 
+DisplayError DisplayBuiltIn::GetPanelMaxBrightness(uint32_t *max_brightness_level) {
+  lock_guard<recursive_mutex> obj(brightness_lock_);
+
+  if (!max_brightness_level) {
+    DLOGE("Invalid input pointer is null");
+    return kErrorParameters;
+  }
+
+  *max_brightness_level = static_cast<uint32_t>(hw_panel_info_.panel_max_brightness);
+
+  DLOGI_IF(kTagDisplay, "Get panel max_brightness_level %u", *max_brightness_level);
+  return kErrorNone;
+}
+
 DisplayError DisplayBuiltIn::ControlPartialUpdate(bool enable, uint32_t *pending) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   if (!pending) {
@@ -535,6 +549,12 @@
     return kErrorNotSupported;
   }
 
+  if (dpps_info_.disable_pu_ && enable) {
+    // Nothing to be done.
+    DLOGI("partial update is disabled by DPPS for display id = %d", display_id_);
+    return kErrorNotSupported;
+  }
+
   *pending = 0;
   if (enable == partial_update_control_) {
     DLOGI("Same state transition is requested.");
@@ -596,6 +616,7 @@
         break;
       }
       enable = *(reinterpret_cast<bool *>(payload));
+      dpps_info_.disable_pu_ = !enable;
       ControlPartialUpdate(enable, &pending);
       event_handler_->HandleEvent(kInvalidateDisplay);
       event_handler_->Refresh();
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index b59752e..8494091 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -39,6 +39,7 @@
   void Init(DppsPropIntf *intf, const std::string &panel_name);
   void Deinit();
   void DppsNotifyOps(enum DppsNotifyOps op, void *payload, size_t size);
+  bool disable_pu_ = false;
 
  private:
   const char *kDppsLib_ = "libdpps.so";
@@ -71,6 +72,7 @@
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate);
   virtual DisplayError SetPanelBrightness(float brightness);
   virtual DisplayError GetPanelBrightness(float *brightness);
+  virtual DisplayError GetPanelMaxBrightness(uint32_t *max_brightness_level);
   virtual DisplayError GetRefreshRate(uint32_t *refresh_rate);
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event, LayerStack *layer_stack);
   virtual DisplayError SetDisplayDppsAdROI(void *payload);
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 8929fc9..761a016 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -105,6 +105,7 @@
 using sde_drm::DRMSecurityLevel;
 using sde_drm::DRMCscType;
 using sde_drm::DRMMultiRectMode;
+using sde_drm::DRMSSPPLayoutIndex;
 
 namespace sdm {
 
@@ -617,7 +618,8 @@
   display_attributes_[index].is_device_split =
       (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE ||
        topology == DRMTopology::DUAL_LM_MERGE_DSC || topology == DRMTopology::DUAL_LM_DSC ||
-       topology == DRMTopology::DUAL_LM_DSCMERGE);
+       topology == DRMTopology::DUAL_LM_DSCMERGE || topology == DRMTopology::QUAD_LM_MERGE ||
+       topology == DRMTopology::QUAD_LM_DSCMERGE || topology == DRMTopology::QUAD_LM_MERGE_DSC);
   display_attributes_[index].clock_khz = mode.clock;
 
   // If driver doesn't return panel width/height information, default to 320 dpi
@@ -632,14 +634,15 @@
   SetTopology(topology, &display_attributes_[index].topology);
 
   DLOGI("Display attributes[%d]: WxH: %dx%d, DPI: %fx%f, FPS: %d, LM_SPLIT: %d, V_BACK_PORCH: %d," \
-        " V_FRONT_PORCH: %d, V_PULSE_WIDTH: %d, V_TOTAL: %d, H_TOTAL: %d, CLK: %dKHZ, TOPOLOGY: %d",
-        index, display_attributes_[index].x_pixels, display_attributes_[index].y_pixels,
-        display_attributes_[index].x_dpi, display_attributes_[index].y_dpi,
-        display_attributes_[index].fps, display_attributes_[index].is_device_split,
-        display_attributes_[index].v_back_porch, display_attributes_[index].v_front_porch,
-        display_attributes_[index].v_pulse_width, display_attributes_[index].v_total,
-        display_attributes_[index].h_total, display_attributes_[index].clock_khz,
-        display_attributes_[index].topology);
+        " V_FRONT_PORCH: %d, V_PULSE_WIDTH: %d, V_TOTAL: %d, H_TOTAL: %d, CLK: %dKHZ," \
+        " TOPOLOGY: %d, HW_SPLIT: %d", index, display_attributes_[index].x_pixels,
+        display_attributes_[index].y_pixels, display_attributes_[index].x_dpi,
+        display_attributes_[index].y_dpi, display_attributes_[index].fps,
+        display_attributes_[index].is_device_split, display_attributes_[index].v_back_porch,
+        display_attributes_[index].v_front_porch, display_attributes_[index].v_pulse_width,
+        display_attributes_[index].v_total, display_attributes_[index].h_total,
+        display_attributes_[index].clock_khz, display_attributes_[index].topology,
+        mixer_attributes_.split_type);
 
   return kErrorNone;
 }
@@ -1155,8 +1158,34 @@
 
           DRMRect dst = {};
           SetRect(pipe_info->dst_roi, &dst);
+          LayerRect right_mixer = {FLOAT(mixer_attributes_.split_left), 0,
+                                   FLOAT(mixer_attributes_.width), FLOAT(mixer_attributes_.height)};
+          LayerRect dst_roi = pipe_info->dst_roi;
+
+          // For larget displays ie; 2 * 2k * 2k * 90 fps 4 LM's get programmed.
+          // Each pair of LM's drive independent displays.
+          // Layout Index indicates the panel onto which pipe gets staged.
+          DRMSSPPLayoutIndex layout_index = DRMSSPPLayoutIndex::NONE;
+          if (mixer_attributes_.split_type == kQuadSplit) {
+            layout_index = DRMSSPPLayoutIndex::LEFT;
+            if (IsValid(Intersection(dst_roi, right_mixer))) {
+              dst_roi = Reposition(dst_roi, -INT(mixer_attributes_.split_left), 0);
+              layout_index = DRMSSPPLayoutIndex::RIGHT;
+              DLOGV_IF(kTagDriverConfig, "Layer index = %d sspp layout = RIGHT", i);
+              DLOGV_IF(kTagDriverConfig, "Right dst_roi l = %f t = %f r = %f b = %f",
+                       dst_roi.left, dst_roi.top, dst_roi.right, dst_roi.bottom);
+            } else {
+              DLOGV_IF(kTagDriverConfig, "Layer index = %d sspp layout = LEFT", i);
+              DLOGV_IF(kTagDriverConfig, "Left dst_roi l = %f t = %f r = %f b = %f",
+                       dst_roi.left, dst_roi.top, dst_roi.right, dst_roi.bottom);
+            }
+          }
+          SetRect(dst_roi, &dst);
           drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst);
 
+          // Update Layout index.
+          drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SSPP_LAYOUT, pipe_id, layout_index);
+
           DRMRect excl = {};
           SetRect(pipe_info->excl_rect, &excl);
           drm_atomic_intf_->Perform(DRMOps::PLANE_SET_EXCL_RECT, pipe_id, excl);
@@ -1218,15 +1247,16 @@
     SetSolidfillStages();
     SetQOSData(qos_data);
     drm_atomic_intf_->Perform(DRMOps::CRTC_SET_SECURITY_LEVEL, token_.crtc_id, crtc_security_level);
-    if (hw_layers->hw_avr_info.update) {
-      sde_drm::DRMQsyncMode mode = sde_drm::DRMQsyncMode::NONE;
-      if (hw_layers->hw_avr_info.mode == kContinuousMode) {
-        mode = sde_drm::DRMQsyncMode::CONTINUOUS;
-      } else if (hw_layers->hw_avr_info.mode == kOneShotMode) {
-        mode = sde_drm::DRMQsyncMode::ONESHOT;
-      }
-      drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_QSYNC_MODE, token_.conn_id, mode);
+  }
+
+  if (hw_layers->hw_avr_info.update) {
+    sde_drm::DRMQsyncMode mode = sde_drm::DRMQsyncMode::NONE;
+    if (hw_layers->hw_avr_info.mode == kContinuousMode) {
+      mode = sde_drm::DRMQsyncMode::CONTINUOUS;
+    } else if (hw_layers->hw_avr_info.mode == kOneShotMode) {
+      mode = sde_drm::DRMQsyncMode::ONESHOT;
     }
+    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_QSYNC_MODE, token_.conn_id, mode);
   }
 
   drm_atomic_intf_->Perform(DRMOps::DPPS_COMMIT_FEATURE, 0 /* argument is not used */);
@@ -1868,8 +1898,15 @@
 
   mixer_attributes_ = mixer_attributes;
   mixer_attributes_.split_left = mixer_attributes_.width;
+  mixer_attributes_.split_type = kNoSplit;
   if (display_attributes_[index].is_device_split) {
     mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio);
+    mixer_attributes_.split_type = kDualSplit;
+    if (display_attributes_[index].topology == kQuadLMMerge ||
+        display_attributes_[index].topology == kQuadLMDSCMerge ||
+        display_attributes_[index].topology == kQuadLMMergeDSC) {
+      mixer_attributes_.split_type = kQuadSplit;
+    }
   }
 
   return kErrorNone;
@@ -1955,7 +1992,18 @@
   mixer_attributes_.split_left = display_attributes_[index].is_device_split
                                      ? hw_panel_info_.split_info.left_split
                                      : mixer_attributes_.width;
-  DLOGI("Mixer WxH %dx%d for %s", mixer_attributes_.width, mixer_attributes_.height, device_name_);
+  mixer_attributes_.split_type = kNoSplit;
+  if (display_attributes_[index].is_device_split) {
+    mixer_attributes_.split_type = kDualSplit;
+    if (display_attributes_[index].topology == kQuadLMMerge ||
+        display_attributes_[index].topology == kQuadLMDSCMerge ||
+        display_attributes_[index].topology == kQuadLMMergeDSC) {
+      mixer_attributes_.split_type = kQuadSplit;
+    }
+  }
+
+  DLOGI("Mixer WxH %dx%d-%d for %s", mixer_attributes_.width, mixer_attributes_.height,
+        mixer_attributes_.split_type, device_name_);
   update_mode_ = true;
 }
 
@@ -1994,6 +2042,9 @@
     case DRMTopology::DUAL_LM_MERGE:      *hw_topology = kDualLMMerge;     break;
     case DRMTopology::DUAL_LM_MERGE_DSC:  *hw_topology = kDualLMMergeDSC;  break;
     case DRMTopology::DUAL_LM_DSCMERGE:   *hw_topology = kDualLMDSCMerge;  break;
+    case DRMTopology::QUAD_LM_MERGE:      *hw_topology = kQuadLMMerge;     break;
+    case DRMTopology::QUAD_LM_DSCMERGE:   *hw_topology = kQuadLMDSCMerge;  break;
+    case DRMTopology::QUAD_LM_MERGE_DSC:  *hw_topology = kQuadLMMergeDSC;  break;
     case DRMTopology::PPSPLIT:            *hw_topology = kPPSplit;         break;
     default:                              *hw_topology = kUnknown;         break;
   }
diff --git a/sdm/libs/core/drm/hw_events_drm.cpp b/sdm/libs/core/drm/hw_events_drm.cpp
index 25bad21..16a7249 100644
--- a/sdm/libs/core/drm/hw_events_drm.cpp
+++ b/sdm/libs/core/drm/hw_events_drm.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2017-2019, 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
@@ -332,6 +332,11 @@
   prctl(PR_SET_NAME, event_thread_name_.c_str(), 0, 0, 0);
   setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent);
 
+  // Real Time task with lowest priority.
+  struct sched_param param = {0};
+  param.sched_priority = sched_get_priority_min(SCHED_FIFO);
+  sched_setscheduler(0, SCHED_FIFO, &param);
+
   while (!exit_threads_) {
     int error = Sys::poll_(poll_fds_.data(), UINT32(poll_fds_.size()), -1);
     if (error <= 0) {
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index eaa065c..44fddcb 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -336,6 +336,9 @@
     width_constraints.push_back(std::make_pair(kPipeScalingLimit, info.scaling_limit_index));
     width_constraints.push_back(std::make_pair(kPipeRotationLimit, info.rotation_limit_index));
   }
+  // In case driver doesn't report bus width default to 256 bit bus.
+  hw_resource->num_mnocports = info.num_mnocports ? info.num_mnocports : 2;
+  hw_resource->mnoc_bus_width = info.mnoc_bus_width ? info.mnoc_bus_width : 32;
 }
 
 void HWInfoDRM::GetHWPlanesInfo(HWResourceInfo *hw_resource) {
diff --git a/sdm/libs/core/fb/hw_info.cpp b/sdm/libs/core/fb/hw_info.cpp
index b076aad..fef95fd 100644
--- a/sdm/libs/core/fb/hw_info.cpp
+++ b/sdm/libs/core/fb/hw_info.cpp
@@ -126,7 +126,7 @@
               if (!strncmp(tokens[j], "fmts_supported", strlen("fmts_supported"))) {
                 char *tokens_fmt[max_count] = { NULL };
                 // uint32_t token_fmt_count = 0;
-                if (tokens_fmt == NULL) {}
+                if (&tokens_fmt[0] == NULL) {}
               }
             }
             hw_resource_->hw_pipes.push_back(pipe_caps);
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index 7686caa..a66a003 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -195,8 +195,6 @@
                                                  const HWDisplayAttributes &display_attributes,
                                                  const HWPanelInfo &hw_panel_info,
                                                  const HWMixerAttributes &mixer_attributes) {
-  SCOPE_LOCK(locker_);
-
   DisplayResourceContext *display_resource_ctx =
                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
 
@@ -207,14 +205,10 @@
 }
 
 DisplayError ResourceDefault::Start(Handle display_ctx) {
-  locker_.Lock();
-
   return kErrorNone;
 }
 
 DisplayError ResourceDefault::Stop(Handle display_ctx, HWLayers *hw_layers) {
-  locker_.Unlock();
-
   return kErrorNone;
 }
 
@@ -323,19 +317,14 @@
 }
 
 DisplayError ResourceDefault::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
-  SCOPE_LOCK(locker_);
-
   return kErrorNone;
 }
 
 DisplayError ResourceDefault::Commit(Handle display_ctx, HWLayers *hw_layers) {
-  SCOPE_LOCK(locker_);
-
   return kErrorNone;
 }
 
 DisplayError ResourceDefault::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
-  SCOPE_LOCK(locker_);
   DisplayResourceContext *display_resource_ctx =
                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
   HWBlockType hw_block_type = display_resource_ctx->hw_block_type;
@@ -363,8 +352,6 @@
 }
 
 void ResourceDefault::Purge(Handle display_ctx) {
-  SCOPE_LOCK(locker_);
-
   DisplayResourceContext *display_resource_ctx =
                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
   HWBlockType hw_block_type = display_resource_ctx->hw_block_type;
@@ -378,8 +365,6 @@
 }
 
 DisplayError ResourceDefault::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
-  SCOPE_LOCK(locker_);
-
   return kErrorNone;
 }
 
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
index ead2ae6..6a2c90c 100644
--- a/sdm/libs/core/resource_default.h
+++ b/sdm/libs/core/resource_default.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2019, 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:
@@ -67,6 +67,7 @@
                                              const DisplayDetailEnhancerData &de_data);
   virtual DisplayError Perform(int cmd, ...) { return kErrorNone; }
   DisplayError SetDisplayState(int32_t display_id, DisplayState state) { return kErrorNone; }
+  virtual bool IsRotatorSupportedFormat(LayerBufferFormat format) { return false; }
 
  private:
   enum PipeOwner {
@@ -143,7 +144,6 @@
   DisplayError CalculateDecimation(float downscale, uint8_t *decimation);
   DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info);
 
-  Locker locker_;
   HWResourceInfo hw_res_info_;
   HWBlockContext hw_block_ctx_[kHWBlockMax];
   std::vector<SourcePipe> src_pipes_;
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index 7c3f033..c6e0448 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -33,7 +33,9 @@
 
 namespace sdm {
 
-Strategy::Strategy(ExtensionInterface *extension_intf, BufferAllocator *buffer_allocator,
+Strategy::Strategy(ExtensionInterface *extension_intf,
+                   BufferAllocator *buffer_allocator,
+                   BufferSyncHandler *buffer_sync_handler,
                    int32_t display_id, DisplayType type, const HWResourceInfo &hw_resource_info,
                    const HWPanelInfo &hw_panel_info, const HWMixerAttributes &mixer_attributes,
                    const HWDisplayAttributes &display_attributes,
@@ -46,14 +48,15 @@
     mixer_attributes_(mixer_attributes),
     display_attributes_(display_attributes),
     fb_config_(fb_config),
-    buffer_allocator_(buffer_allocator) {}
+    buffer_allocator_(buffer_allocator),
+    sync_handler_(buffer_sync_handler) {}
 
 DisplayError Strategy::Init() {
   DisplayError error = kErrorNone;
 
   if (extension_intf_) {
     error = extension_intf_->CreateStrategyExtn(display_id_, display_type_, buffer_allocator_,
-                                                hw_resource_info_, hw_panel_info_,
+                                                sync_handler_, hw_resource_info_, hw_panel_info_,
                                                 mixer_attributes_, fb_config_, &strategy_intf_);
     if (error != kErrorNone) {
       DLOGE("Failed to create strategy");
diff --git a/sdm/libs/core/strategy.h b/sdm/libs/core/strategy.h
index f4dbcfe..ecc6810 100644
--- a/sdm/libs/core/strategy.h
+++ b/sdm/libs/core/strategy.h
@@ -35,6 +35,7 @@
 class Strategy {
  public:
   Strategy(ExtensionInterface *extension_intf, BufferAllocator *buffer_allocator,
+           BufferSyncHandler *buffer_sync_handler,
            int32_t display_id, DisplayType type, const HWResourceInfo &hw_resource_info,
            const HWPanelInfo &hw_panel_info, const HWMixerAttributes &mixer_attributes,
            const HWDisplayAttributes &display_attributes,
@@ -75,6 +76,7 @@
   bool extn_start_success_ = false;
   bool disable_gpu_comp_ = false;
   BufferAllocator *buffer_allocator_ = NULL;
+  BufferSyncHandler *sync_handler_ = NULL;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/utils/Android.mk b/sdm/libs/utils/Android.mk
index f4b09c6..c474193 100644
--- a/sdm/libs/utils/Android.mk
+++ b/sdm/libs/utils/Android.mk
@@ -12,6 +12,7 @@
 LOCAL_SRC_FILES               := debug.cpp \
                                  rect.cpp \
                                  sys.cpp \
+                                 fence.cpp \
                                  formats.cpp \
                                  utils.cpp
 
@@ -30,6 +31,7 @@
                                  $(SDM_HEADER_PATH)/utils/sys.h \
                                  $(SDM_HEADER_PATH)/utils/sync_task.h \
                                  $(SDM_HEADER_PATH)/utils/utils.h \
+                                 $(SDM_HEADER_PATH)/utils/fence.h \
                                  $(SDM_HEADER_PATH)/utils/factory.h
 
 include $(BUILD_COPY_HEADERS)
diff --git a/sdm/libs/utils/fence.cpp b/sdm/libs/utils/fence.cpp
new file mode 100644
index 0000000..3cf26e4
--- /dev/null
+++ b/sdm/libs/utils/fence.cpp
@@ -0,0 +1,110 @@
+/*
+* Copyright (c) 2019, 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 <utils/fence.h>
+#include <string>
+
+#define __CLASS__ "Fence"
+
+namespace sdm {
+
+BufferSyncHandler* Fence::buffer_sync_handler_ = nullptr;
+
+Fence::Fence(int fd) : fd_(fd) {
+}
+
+Fence::~Fence() {
+  close(fd_);
+}
+
+void Fence::Set(BufferSyncHandler *buffer_sync_handler) {
+  buffer_sync_handler_ = buffer_sync_handler;
+}
+
+shared_ptr<Fence> Fence::Create(int fd) {
+  // Do not create Fence object for invalid fd, so that nullptr can be used for invalid fences.
+  if (fd < 0) {
+    return nullptr;
+  }
+
+  shared_ptr<Fence> fence(new Fence(fd));
+  if (!fence) {
+    close(fd);
+  }
+
+  return fence;
+}
+
+int Fence::Dup(const shared_ptr<Fence> &fence) {
+  if (!fence) {
+    return -1;
+  }
+
+  return dup(fence->fd_);
+}
+
+shared_ptr<Fence> Fence::Merge(const shared_ptr<Fence> &fence1, const shared_ptr<Fence> &fence2) {
+  if (!buffer_sync_handler_) {
+    return nullptr;
+  }
+
+  int fd1 = fence1 ? fence1->fd_ : -1;
+  int fd2 = fence2 ? fence2->fd_ : -1;
+  int merged = -1;
+
+  buffer_sync_handler_->SyncMerge(fd1, fd2, &merged);
+
+  return Create(merged);
+}
+
+DisplayError Fence::Wait(const shared_ptr<Fence> &fence) {
+  if (!buffer_sync_handler_) {
+    return kErrorUndefined;
+  }
+
+  return buffer_sync_handler_->SyncWait(Fence::Get(fence));
+}
+
+DisplayError Fence::Wait(const shared_ptr<Fence> &fence, int timeout) {
+  if (!buffer_sync_handler_) {
+    return kErrorUndefined;
+  }
+
+  return buffer_sync_handler_->SyncWait(Fence::Get(fence), timeout);
+}
+
+string Fence::GetStr(const shared_ptr<Fence> &fence) {
+  return std::to_string(Fence::Get(fence));
+}
+
+int Fence::Get(const shared_ptr<Fence> &fence) {
+  return (fence ? fence->fd_ : -1);
+}
+
+}  // namespace sdm