Merge "sdm: set QSYNC_MODE DRM property whenever update is needed"
diff --git a/composer/Android.mk b/composer/Android.mk
index 9278fc2..79a2d9c 100644
--- a/composer/Android.mk
+++ b/composer/Android.mk
@@ -77,7 +77,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.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..c350d47 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,
diff --git a/composer/gl_common.h b/composer/gl_common.h
index 4089e87..79af479 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 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_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..b7b6515 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,141 @@
   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.");
+    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_layers.cpp b/composer/hwc_layers.cpp
index 426c397..101c3f0 100644
--- a/composer/hwc_layers.cpp
+++ b/composer/hwc_layers.cpp
@@ -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;
@@ -916,6 +963,11 @@
 }
 
 void HWCLayer::ValidateAndSetCSC(const private_handle_t *handle) {
+  if (per_frame_hdr_metadata_) {
+    // Since client has set PerFrameMetadata, dataspace will be valid
+    // so we can skip reading from ColorMetaData.
+    return;
+  }
   LayerBuffer *layer_buffer = &layer_->input_buffer;
   bool use_color_metadata = true;
   ColorMetaData csc = {};
@@ -960,7 +1012,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..2c2fc7e 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;
@@ -603,6 +604,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 ||
@@ -1144,7 +1154,11 @@
           return HWC2::Error::NoResources;
         }
 
-        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 virtual display id:% " PRIu64 " with res: %dx%d", client_id, width, height);
 
         *out_display_id = client_id;
@@ -1340,13 +1354,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 +1380,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 +2385,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 +2463,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 +2620,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 +2723,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 +2759,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..8e2e25c 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -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
diff --git a/composer/hwc_session_services.cpp b/composer/hwc_session_services.cpp
index 638cba3..1881c26 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);
 }
diff --git a/config/display-product.mk b/config/display-product.mk
index cde510e..5381430 100644
--- a/config/display-product.mk
+++ b/config/display-product.mk
@@ -46,6 +46,9 @@
 #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
 
 PRODUCT_PROPERTY_OVERRIDES += \
     persist.demo.hdmirotationlock=false \
@@ -72,7 +75,7 @@
     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_early_gl_phase_offset_ns=6500000 \
     debug.sf.high_fps_late_app_phase_offset_ns=1000000 \
     debug.sf.phase_offset_threshold_for_next_vsync_ns=6100000
 endif
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/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..e41c8ab 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
@@ -580,6 +586,9 @@
   DUAL_LM_MERGE,
   DUAL_LM_MERGE_DSC,
   DUAL_LM_DSCMERGE,
+  QUAD_LM_MERGE,
+  QUAD_LM_DSCMERGE,
+  QUAD_LM_MERGE_DSC,
   PPSPLIT,
 };
 
@@ -811,6 +820,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_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/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..d9abd6c 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,
@@ -656,9 +665,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 +770,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/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/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 6ee5032..1bd6862 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;
 }
 
@@ -419,11 +419,14 @@
   display_comp_ctx->idle_fallback = false;
   display_comp_ctx->first_cycle_ = false;
 
+  Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+  error = resource_intf_->Stop(display_resource_ctx, hw_layers);
+
   DLOGV_IF(kTagCompManager, "Registered displays [%s], display %d-%d",
            StringDisplayList(registered_displays_), display_comp_ctx->display_id,
            display_comp_ctx->display_type);
 
-  return kErrorNone;
+  return error;
 }
 
 void CompManager::Purge(Handle display_ctx) {
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 8a6b665..15b6437 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -131,6 +131,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/display_base.cpp b/sdm/libs/core/display_base.cpp
index 7eb64be..6985f7a 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");
@@ -898,11 +901,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";
   }
 }
 
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 b567a80..7228049 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 08909f4..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);
@@ -1869,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;
@@ -1956,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;
 }
 
@@ -1995,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/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..d51008b 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:
@@ -143,7 +143,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