Merge "hwc: Use 1 pipe if rotator downscale reduces dimensions"
diff --git a/displayengine/include/core/buffer_allocator.h b/displayengine/include/core/buffer_allocator.h
new file mode 100644
index 0000000..4081c54
--- /dev/null
+++ b/displayengine/include/core/buffer_allocator.h
@@ -0,0 +1,130 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+/*! @file buffer_allocator.h
+  @brief Interface file for platform specific buffer allocator.
+
+  @details Buffer manager in display engine uses this interface to allocate buffer for internal
+  usage.
+*/
+
+#ifndef __BUFFER_ALLOCATOR_H__
+#define __BUFFER_ALLOCATOR_H__
+
+#include <core/layer_buffer.h>
+
+namespace sde {
+  /*! @brief Input configuration set by the client for buffer allocation.
+
+    @sa BufferInfo::BufferConfig
+  */
+
+struct BufferConfig {
+  uint32_t width;            //!< Specifies buffer width for buffer allocation.
+  uint32_t height;           //!< Specifies buffer height for buffer allocation.
+  LayerBufferFormat format;  //!< Specifies buffer format for buffer allocation.
+  uint32_t buffer_count;     //!< Specifies number of buffers to be allocated.
+  bool secure;               //!< Specifies buffer to be allocated from secure region.
+  bool cache;                //!< Specifies whether the buffer needs to be cache.
+
+  BufferConfig() : width(0), height(0), format(kFormatInvalid), buffer_count(0), secure(false),
+                  cache(false) { }
+};
+
+/*! @brief Holds the information about the allocated buffer.
+
+  @sa BufferAllocator::AllocateBuffer
+  @sa BufferAllocator::FreeBuffer
+*/
+struct AllocatedBufferInfo {
+  int fd;                    //!< Specifies the fd of the allocated buffer.
+  uint32_t stride;           //!< Specifies aligned buffer width of the allocated buffer.
+  uint32_t size;             //!< Specifies the size of the allocated buffer.
+
+  AllocatedBufferInfo() : fd(-1), stride(0), size(0) { }
+};
+
+/*! @brief Holds the information about the input/output configuration of an output buffer.
+
+  @sa BufferAllocator::AllocateBuffer
+  @sa BufferAllocator::FreeBuffer
+*/
+struct BufferInfo {
+  BufferConfig buffer_config;             //!< Specifies configuration of a buffer to be allocated.
+  AllocatedBufferInfo alloc_buffer_info;  //!< Specifies buffer information of allocated buffer.
+
+  void *private_data;                      //!< Pointer to private data.
+
+  BufferInfo() : private_data(NULL) { }
+};
+
+/*! @brief Buffer allocator implemented by the client
+
+  @details This class declares prototype for BufferAllocator methods which must be
+  implemented by the client. Buffer manager in display engine will use these methods to
+  allocate/deallocate buffers for display engine.
+
+  @sa CompManager::Init
+  @sa ResManager::Init
+*/
+class BufferAllocator {
+ public:
+  /*! @brief Method to allocate ouput buffer for the given input configuration.
+
+    @details This method allocates memory based on input configuration.
+
+    @param[in] buffer_info \link BufferInfo \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa BufferManager
+  */
+  virtual DisplayError AllocateBuffer(BufferInfo *buffer_info) = 0;
+
+
+  /*! @brief Method to deallocate the ouput buffer.
+
+    @details This method deallocates the memory allocated using AllocateBuffer method.
+
+    @param[in] buffer_info \link BufferInfo \endlink
+
+    @return \link DisplayError \endlink
+
+    @sa BufferManager
+  */
+  virtual DisplayError FreeBuffer(BufferInfo *buffer_info) = 0;
+
+ protected:
+  virtual ~BufferAllocator() { }
+};
+
+}  // namespace sde
+
+#endif  // __BUFFER_ALLOCATOR_H__
+
diff --git a/displayengine/include/core/buffer_sync_handler.h b/displayengine/include/core/buffer_sync_handler.h
new file mode 100644
index 0000000..d0d062e
--- /dev/null
+++ b/displayengine/include/core/buffer_sync_handler.h
@@ -0,0 +1,90 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+/*! @file buffer_sync_handler.h
+  @brief Interface file for platform specific buffer allocator.
+
+  @details Buffer manager in display engine uses this interface to wait for buffer sync fd to be
+  signaled/merge the two buffer sync fds into one
+*/
+
+#ifndef __BUFFER_SYNC_HANDLER_H__
+#define __BUFFER_SYNC_HANDLER_H__
+
+namespace sde {
+
+/*! @brief Buffer sync handler implemented by the client
+
+  @details This class declares prototype for BufferSyncHandler methods which must be
+  implemented by the client. Buffer manager and HWFramebuffer in display engine will use these
+  methods to wait for buffer sync fd to be signaled/merge two buffer sync fds into one.
+
+  @sa CompManager::Init
+  @sa ResManager::Init
+  @sa HWInterface::Create
+*/
+class BufferSyncHandler {
+ public:
+  /*! @brief Method to wait for ouput buffer to be released.
+
+    @details This method waits for fd to be signaled by the producer/consumer.
+
+    @param[in] fd
+
+    @return \link DisplayError \endlink
+
+    @sa BufferManager::GetNextBuffer
+  */
+
+  virtual DisplayError SyncWait(int fd) = 0;
+
+  /*! @brief Method to merge two sync fds into one sync fd
+
+    @details This method merges two buffer sync fds into one sync fd, if a producer/consumer
+    requires to wait for more than one sync fds.
+
+    @param[in] fd1
+    @param[in] fd2
+    @param[out] merged_fd
+
+    @return \link DisplayError \endlink
+
+    @sa HWFrameBuffer::RotatorCommit
+ */
+
+  virtual DisplayError SyncMerge(int fd1, int fd2, int *merged_fd) = 0;
+
+ protected:
+  virtual ~BufferSyncHandler() { }
+};
+
+}  // namespace sde
+
+#endif  // __BUFFER_SYNC_HANDLER_H__
+
diff --git a/displayengine/include/core/core_interface.h b/displayengine/include/core/core_interface.h
old mode 100755
new mode 100644
index 2229d1e..114d9aa
--- a/displayengine/include/core/core_interface.h
+++ b/displayengine/include/core/core_interface.h
@@ -1,25 +1,30 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 /*! @file core_interface.h
@@ -36,6 +41,9 @@
 
 #include "display_interface.h"
 #include "sde_types.h"
+#include "buffer_allocator.h"
+
+class BufferSyncHandler;
 
 /*! @brief Display engine interface version.
 
@@ -65,6 +73,11 @@
 
 namespace sde {
 
+/*! @brief Forward declaration for debug handler.
+*/
+class DebugHandler;
+
+
 /*! @brief Event data associated with hotplug event.
 
   @sa CoreEventHandler::Hotplug
@@ -120,7 +133,9 @@
     This interface shall be called only once.
 
     @param[in] event_handler \link CoreEventHandler \endlink
-    @param[in] log_handler \link LogHandler \endlink
+    @param[in] debug_handler \link DebugHandler \endlink
+    @param[in] buffer_allocator \link BufferAllocator \endlink
+    @param[in] buffer_sync_handler \link BufferSyncHandler \endlink
     @param[out] interface \link CoreInterface \endlink
     @param[in] version \link SDE_VERSION_TAG \endlink. Client must not override this argument.
 
@@ -128,8 +143,10 @@
 
     @sa DestroyCore
   */
-  static DisplayError CreateCore(CoreEventHandler *event_handler, LogHandler *log_handler,
-                                 CoreInterface **interface, uint32_t version = SDE_VERSION_TAG);
+  static DisplayError CreateCore(CoreEventHandler *event_handler, DebugHandler *debug_handler,
+                                 BufferAllocator *buffer_allocator,
+                                 BufferSyncHandler *buffer_sync_handler, CoreInterface **interface,
+                                 uint32_t version = SDE_VERSION_TAG);
 
   /*! @brief Method to release handle to display core interface.
 
diff --git a/displayengine/include/core/debug_interface.h b/displayengine/include/core/debug_interface.h
new file mode 100644
index 0000000..c90e1ff
--- /dev/null
+++ b/displayengine/include/core/debug_interface.h
@@ -0,0 +1,128 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+/*! @file debug_interface.h
+  @brief This file provides the debug interface for display engine.
+*/
+#ifndef __DEBUG_INTERFACE_H__
+#define __DEBUG_INTERFACE_H__
+
+namespace sde {
+
+/*! @brief This enum represents different modules/logical unit tags that a log message may
+  be associated with. Client may use this to filter messages for dynamic logging.
+
+  @sa DisplayLogHandler
+*/
+enum DebugTag {
+  kTagNone,             //!< Debug log is not tagged. This type of logs should always be printed.
+  kTagResources,        //!< Debug log is tagged for resource management.
+  kTagStrategy,         //!< Debug log is tagged for strategy decisions.
+  kTagCompManager,      //!< Debug log is tagged for composition manager.
+  kTagDriverConfig,     //!< Debug log is tagged for driver config.
+  kTagBufferManager,    //!< Debug log is tagged for buffer manager state transitions.
+  kTagOfflineCtrl,      //!< Debug log is tagged for offline controller.
+};
+
+/*! @brief Display debug handler class.
+
+  @details This class defines display debug handler. The handle contains methods which client
+  should implement to get different levels of logging/tracing from display engine. Display engine
+   will call into these methods at appropriate times to send logging/tracing information.
+
+  @sa CoreInterface::CreateCore
+*/
+class DebugHandler {
+ public:
+  /*! @brief Method to handle error messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Error(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle warning messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Warning(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle informative messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Info(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle verbose messages.
+
+    @param[in] tag \link DebugTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Verbose(DebugTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to begin trace for a module/logical unit.
+
+    @param[in] class_name \link name of the class that the function belongs to \endlink
+    @param[in] function_name \link name of the function to be traced \endlink
+    @param[in] custom_string \link custom string for multiple traces within a function \endlink
+  */
+  virtual void BeginTrace(const char *class_name, const char *function_name,
+                          const char *custom_string) = 0;
+
+  /*! @brief Method to end trace for a module/logical unit.
+  */
+  virtual void EndTrace() = 0;
+
+ protected:
+  virtual ~DebugHandler() { }
+};
+
+/*! @brief Scope tracer template class.
+
+  @details This class template implements the funtionality to capture the trace for function/
+  module. It starts the trace upon object creation and ends the trace upon object destruction.
+*/
+template <class T>
+class ScopeTracer {
+ public:
+  ScopeTracer(const char *class_name, const char *function_name) {
+    T::Get()->BeginTrace(class_name, function_name, "");
+  }
+
+  ~ScopeTracer() { T::Get()->EndTrace(); }
+};
+
+}  // namespace sde
+
+#endif  // __DEBUG_INTERFACE_H__
+
+
+
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index 1e99d1a..c054fae 100644
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -284,6 +284,14 @@
 
   /*! @brief Method to set active configuration for variable properties of the display device.
 
+    @param[in] variable_info \link DisplayConfigVariableInfo \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info) = 0;
+
+  /*! @brief Method to set active configuration for variable properties of the display device.
+
     @param[in] index index of the mode corresponding to variable properties.
 
     @return \link DisplayError \endlink
diff --git a/displayengine/include/core/layer_buffer.h b/displayengine/include/core/layer_buffer.h
old mode 100755
new mode 100644
index 51fa5c5..9f7110a
--- a/displayengine/include/core/layer_buffer.h
+++ b/displayengine/include/core/layer_buffer.h
@@ -96,6 +96,8 @@
   kFormatRGB565Ubwc,                  //!< UBWC aligned RGB565 format
 
   kFormatYCbCr420SPVenusUbwc,         //!< UBWC aligned Venus NV12 format
+
+  kFormatInvalid = 0xFFFFFFFF,
 };
 
 /*! @brief This structure defines a color sample plane belonging to a buffer format. RGB buffer
@@ -123,6 +125,7 @@
                             //!< video/ui buffer
   uint64_t macro_tile : 1;  //!< This flag shall be set by client to indicate that the buffer format
                             //!< is macro tiled.
+
   LayerBufferFlags() : secure(0), video(0), macro_tile(0) { }
 };
 
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
old mode 100755
new mode 100644
index 67a812d..0a37c79
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,6 +32,7 @@
 #define __LAYER_STACK_H__
 
 #include <stdint.h>
+#include <utils/constants.h>
 
 #include "layer_buffer.h"
 #include "sde_types.h"
@@ -137,6 +138,8 @@
   float bottom;   //!< Bottom-most pixel coordinate.
 
   LayerRect() : left(0.0f), top(0.0f), right(0.0f), bottom(0.0f) { }
+
+  LayerRect(float l, float t, float r, float b) : left(l), top(t), right(r), bottom(b) { }
 };
 
 /*! @brief This structure defines an array of display layer rectangles.
@@ -194,8 +197,10 @@
 
   LayerFlags flags;                 //!< Flags associated with this layer.
 
+  uint32_t frame_rate;              //!< Rate at which frames are being updated for this layer.
+
   Layer() : input_buffer(NULL), composition(kCompositionGPU), blending(kBlendingNone),
-            plane_alpha(0) { }
+            plane_alpha(0), frame_rate(0) { }
 };
 
 /*! @brief This structure defines a layer stack that contains layers which need to be composed and
diff --git a/displayengine/include/core/sde_types.h b/displayengine/include/core/sde_types.h
old mode 100755
new mode 100644
index 6090889..0055306
--- a/displayengine/include/core/sde_types.h
+++ b/displayengine/include/core/sde_types.h
@@ -1,25 +1,30 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 /*! @file sde_types.h
@@ -48,59 +53,6 @@
   kErrorTimeOut,          //!< The operation has timed out to prevent client from waiting forever.
 };
 
-/*! @brief This enum represents different modules/logical unit tags that a log message may be
-  associated with. Client may use this to filter messages for dynamic logging.
-
-  @sa DisplayLogHandler
-*/
-enum LogTag {
-  kTagNone,             //!< Log is not tagged. This type of logs should always be printed.
-  kTagResources,        //!< Log is tagged for resource management.
-  kTagStrategy,         //!< Log is tagged for strategy decisions.
-};
-
-/*! @brief Display log handler class.
-
-  @details This class defines display log handler. The handle contains methods which client should
-  implement to get different levels of logging from display engine. Display engine will call into
-  these methods at appropriate times to send logging information.
-
-  @sa CoreInterface::CreateCore
-*/
-class LogHandler {
- public:
-  /*! @brief Method to handle error messages.
-
-    @param[in] tag \link LogTag \endlink
-    @param[in] format \link message format with variable argument list \endlink
-  */
-  virtual void Error(LogTag tag, const char *format, ...) = 0;
-
-  /*! @brief Method to handle warning messages.
-
-    @param[in] tag \link LogTag \endlink
-    @param[in] format \link message format with variable argument list \endlink
-  */
-  virtual void Warning(LogTag tag, const char *format, ...) = 0;
-
-  /*! @brief Method to handle informative messages.
-
-    @param[in] tag \link LogTag \endlink
-    @param[in] format \link message format with variable argument list \endlink
-  */
-  virtual void Info(LogTag tag, const char *format, ...) = 0;
-
-  /*! @brief Method to handle verbose messages.
-
-    @param[in] tag \link LogTag \endlink
-    @param[in] format \link message format with variable argument list \endlink
-  */
-  virtual void Verbose(LogTag tag, const char *format, ...) = 0;
-
- protected:
-  virtual ~LogHandler() { }
-};
-
 /*! @brief This structure is defined for client and library compatibility check purpose only. This
   structure is used in SDE_VERSION_TAG definition only. Client should not refer it directly for
   any purpose.
diff --git a/displayengine/include/utils/constants.h b/displayengine/include/utils/constants.h
index a7b9f0f..04a5f77 100644
--- a/displayengine/include/utils/constants.h
+++ b/displayengine/include/utils/constants.h
@@ -25,6 +25,8 @@
 #ifndef __CONSTANTS_H__
 #define __CONSTANTS_H__
 
+#include <stdlib.h>
+
 #define LIKELY(exp) __builtin_expect((exp) != 0, true)
 #define UNLIKELY(exp) __builtin_expect((exp) != 0, false)
 
@@ -47,7 +49,9 @@
 #define SET_BIT(value, bit) (value |= (1 << (bit)))
 #define CLEAR_BIT(value, bit) (value &= (~(1 << (bit))))
 #define IS_BIT_SET(value, bit) (value & (1 << (bit)))
+
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
 
 namespace sde {
 
diff --git a/displayengine/include/utils/debug.h b/displayengine/include/utils/debug.h
index 7983c84..65079a9 100644
--- a/displayengine/include/utils/debug.h
+++ b/displayengine/include/utils/debug.h
@@ -1,25 +1,30 @@
 /*
 * Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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 __DEBUG_H__
@@ -27,9 +32,10 @@
 
 #include <stdint.h>
 #include <core/sde_types.h>
+#include <core/debug_interface.h>
 
-#define DLOG(tag, method, format, ...) Debug::GetLogHandler()->method(tag, \
-                                            __CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
+#define DLOG(tag, method, format, ...) Debug::Get()->method(tag, __CLASS__ "::%s: " format, \
+                                                            __FUNCTION__, ##__VA_ARGS__)
 
 #define DLOGE_IF(tag, format, ...) DLOG(tag, Error, format, ##__VA_ARGS__)
 #define DLOGW_IF(tag, format, ...) DLOG(tag, Warning, format, ##__VA_ARGS__)
@@ -41,12 +47,18 @@
 #define DLOGI(format, ...) DLOGI_IF(kTagNone, format, ##__VA_ARGS__)
 #define DLOGV(format, ...) DLOGV_IF(kTagNone, format, ##__VA_ARGS__)
 
+#define DTRACE_BEGIN(custom_string) Debug::Get()->BeginTrace(__CLASS__, __FUNCTION__, custom_string)
+#define DTRACE_END() Debug::Get()->EndTrace()
+#define DTRACE_SCOPED() ScopeTracer <Debug> scope_tracer(__CLASS__, __FUNCTION__)
+
 namespace sde {
 
 class Debug {
  public:
-  static inline void SetLogHandler(LogHandler *log_handler) { debug_.log_handler_ = log_handler; }
-  static inline LogHandler* GetLogHandler() { return debug_.log_handler_; }
+  static inline void SetDebugHandler(DebugHandler *debug_handler) {
+    debug_.debug_handler_ = debug_handler;
+  }
+  static inline DebugHandler* Get() { return debug_.debug_handler_; }
   static inline bool IsVirtualDriver() { return debug_.virtual_driver_; }
   static uint32_t GetSimulationFlag();
   static uint32_t GetHDMIResolution();
@@ -55,18 +67,21 @@
  private:
   Debug();
 
-  // By default, drop any log messages coming from Display Engine. It will be overriden by Display
-  // Engine client when core is successfully initialized.
-  class DefaultLogHandler : public LogHandler {
+  // By default, drop any log messages/traces coming from Display Engine. It will be overriden by
+  // Display Engine client when core is successfully initialized.
+  class DefaultDebugHandler : public DebugHandler {
    public:
-    virtual void Error(LogTag /*tag*/, const char */*format*/, ...) { }
-    virtual void Warning(LogTag /*tag*/, const char */*format*/, ...) { }
-    virtual void Info(LogTag /*tag*/, const char */*format*/, ...) { }
-    virtual void Verbose(LogTag /*tag*/, const char */*format*/, ...) { }
+    virtual void Error(DebugTag /*tag*/, const char */*format*/, ...) { }
+    virtual void Warning(DebugTag /*tag*/, const char */*format*/, ...) { }
+    virtual void Info(DebugTag /*tag*/, const char */*format*/, ...) { }
+    virtual void Verbose(DebugTag /*tag*/, const char */*format*/, ...) { }
+    virtual void BeginTrace(const char */*class_name*/, const char */*function_name*/,
+                            const char */*custom_string*/) { }
+    virtual void EndTrace() { }
   };
 
-  DefaultLogHandler default_log_handler_;
-  LogHandler *log_handler_;
+  DefaultDebugHandler default_debug_handler_;
+  DebugHandler *debug_handler_;
   bool virtual_driver_;
   static Debug debug_;
 };
diff --git a/displayengine/include/utils/locker.h b/displayengine/include/utils/locker.h
index 2c1ef9a..549a282 100644
--- a/displayengine/include/utils/locker.h
+++ b/displayengine/include/utils/locker.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -28,7 +28,11 @@
 #include <stdint.h>
 #include <pthread.h>
 
-#define SCOPE_LOCK(locker) Locker::ScopeLock scopeLock(locker)
+#define SCOPE_LOCK(locker) Locker::ScopeLock lock(locker)
+#define SEQUENCE_ENTRY_SCOPE_LOCK(locker) Locker::SequenceEntryScopeLock lock(locker)
+#define SEQUENCE_EXIT_SCOPE_LOCK(locker) Locker::SequenceExitScopeLock lock(locker)
+#define SEQUENCE_WAIT_SCOPE_LOCK(locker) Locker::SequenceWaitScopeLock lock(locker)
+#define SEQUENCE_CANCEL_SCOPE_LOCK(locker) Locker::SequenceCancelScopeLock lock(locker)
 
 namespace sde {
 
@@ -48,7 +52,78 @@
     Locker &locker_;
   };
 
-  Locker() {
+  class SequenceEntryScopeLock {
+   public:
+    explicit SequenceEntryScopeLock(Locker& locker) : locker_(locker) {
+      locker_.Lock();
+      locker_.sequence_wait_ = 1;
+    }
+
+    ~SequenceEntryScopeLock() {
+      locker_.Unlock();
+    }
+
+   private:
+    Locker &locker_;
+  };
+
+  class SequenceExitScopeLock {
+   public:
+    explicit SequenceExitScopeLock(Locker& locker) : locker_(locker) {
+      locker_.Lock();
+      locker_.sequence_wait_ = 0;
+    }
+
+    ~SequenceExitScopeLock() {
+      locker_.Broadcast();
+      locker_.Unlock();
+    }
+
+   private:
+    Locker &locker_;
+  };
+
+  class SequenceWaitScopeLock {
+   public:
+    explicit SequenceWaitScopeLock(Locker& locker) : locker_(locker), error_(false) {
+      locker_.Lock();
+
+      if (locker_.sequence_wait_ == 1) {
+        locker_.Wait();
+        error_ = (locker_.sequence_wait_ == -1);
+      }
+    }
+
+    ~SequenceWaitScopeLock() {
+      locker_.Unlock();
+    }
+
+    bool IsError() {
+      return error_;
+    }
+
+   private:
+    Locker &locker_;
+    bool error_;
+  };
+
+  class SequenceCancelScopeLock {
+   public:
+    explicit SequenceCancelScopeLock(Locker& locker) : locker_(locker) {
+      locker_.Lock();
+      locker_.sequence_wait_ = -1;
+    }
+
+    ~SequenceCancelScopeLock() {
+      locker_.Broadcast();
+      locker_.Unlock();
+    }
+
+   private:
+    Locker &locker_;
+  };
+
+  Locker() : sequence_wait_(0) {
     pthread_mutex_init(&mutex_, 0);
     pthread_cond_init(&condition_, 0);
   }
@@ -63,7 +138,7 @@
   void Signal() { pthread_cond_signal(&condition_); }
   void Broadcast() { pthread_cond_broadcast(&condition_); }
   void Wait() { pthread_cond_wait(&condition_, &mutex_); }
-  int WaitFinite(long int ms) {
+  int WaitFinite(int ms) {
     struct timespec ts;
     struct timeval tv;
     gettimeofday(&tv, NULL);
@@ -77,6 +152,11 @@
  private:
   pthread_mutex_t mutex_;
   pthread_cond_t condition_;
+  int sequence_wait_;   // This flag is set to 1 on sequence entry, 0 on exit, and -1 on cancel.
+                        // Some routines will wait for sequence of function calls to finish
+                        // so that capturing a transitionary snapshot of context is prevented.
+                        // If flag is set to -1, these routines will exit without doing any
+                        // further processing.
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/Android.mk b/displayengine/libs/core/Android.mk
index 92569a5..1623c13 100644
--- a/displayengine/libs/core/Android.mk
+++ b/displayengine/libs/core/Android.mk
@@ -23,6 +23,7 @@
                                  offline_ctrl.cpp \
                                  hw_interface.cpp \
                                  hw_framebuffer.cpp \
-                                 dump_impl.cpp
+                                 dump_impl.cpp \
+                                 buffer_manager.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/core/buffer_manager.cpp b/displayengine/libs/core/buffer_manager.cpp
new file mode 100644
index 0000000..95c310a
--- /dev/null
+++ b/displayengine/libs/core/buffer_manager.cpp
@@ -0,0 +1,293 @@
+/*
+* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*  * Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above
+*    copyright notice, this list of conditions and the following
+*    disclaimer in the documentation and/or other materials provided
+*    with the distribution.
+*  * Neither the name of The Linux Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/debug.h>
+#include <utils/constants.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#include "buffer_manager.h"
+
+#define __CLASS__ "BufferManager"
+
+namespace sde {
+
+// --------------------------------- BufferSlot Implementation -------------------------------------
+
+DisplayError BufferManager::BufferSlot::Init() {
+  uint32_t buffer_count = hw_buffer_info.buffer_config.buffer_count;
+  size_t buffer_size = hw_buffer_info.alloc_buffer_info.size;
+
+  release_fd = new int[buffer_count];
+  if (release_fd == NULL) {
+    return kErrorMemory;
+  }
+
+  offset = new uint32_t[buffer_count];
+  if (offset == NULL) {
+    delete[] release_fd;
+    release_fd = NULL;
+    return kErrorMemory;
+  }
+
+  for (uint32_t idx = 0; idx < buffer_count; idx++) {
+    release_fd[idx] = -1;
+    offset[idx] = UINT32((buffer_size / buffer_count) * idx);
+  }
+  curr_index = 0;
+
+  return kErrorNone;
+}
+
+DisplayError BufferManager::BufferSlot::Deinit() {
+  uint32_t buffer_count = hw_buffer_info.buffer_config.buffer_count;
+
+  for (uint32_t idx = 0; idx < buffer_count; idx++) {
+    if (release_fd[idx] >= 0) {
+      close(release_fd[idx]);
+      release_fd[idx] = -1;
+    }
+  }
+
+  if (offset) {
+    delete[] offset;
+    offset = NULL;
+  }
+
+  if (release_fd) {
+    delete[] release_fd;
+    release_fd = NULL;
+  }
+
+  state = kBufferSlotFree;
+  hw_buffer_info = HWBufferInfo();
+
+  return kErrorNone;
+}
+
+// BufferManager State Transition
+// *******************************************************
+// Current State *             Next State
+//               *****************************************
+//               *   FREE       READY        ACQUIRED
+// *******************************************************
+//  FREE         *    NA         NA        GetNextBuffer()
+//  READY        *   Stop()      NA        GetNextBuffer()
+//  ACQUIRED     *    NA       Start()          NA
+//********************************************************
+
+// ------------------------------- BufferManager Implementation ------------------------------------
+
+BufferManager::BufferManager(BufferAllocator *buffer_allocator,
+                             BufferSyncHandler *buffer_sync_handler)
+    : buffer_allocator_(buffer_allocator), buffer_sync_handler_(buffer_sync_handler),
+      num_used_slot_(0) {
+}
+
+void BufferManager::Start() {
+  uint32_t slot = 0, num_ready_slot = 0;
+
+  // Change the state of acquired buffer_slot to kBufferSlotReady
+  while ((num_ready_slot < num_used_slot_) && (slot < kMaxBufferSlotCount)) {
+    if (buffer_slot_[slot].state == kBufferSlotFree) {
+      slot++;
+      continue;
+    }
+
+    buffer_slot_[slot++].state = kBufferSlotReady;
+    num_ready_slot++;
+  }
+}
+
+DisplayError BufferManager::GetNextBuffer(HWBufferInfo *hw_buffer_info) {
+  DisplayError error = kErrorNone;
+  const BufferConfig &buffer_config = hw_buffer_info->buffer_config;
+
+  DLOGI_IF(kTagBufferManager, "Input: w = %d h = %d f = %d", buffer_config.width,
+           buffer_config.height, buffer_config.format);
+
+  uint32_t free_slot = num_used_slot_;
+  uint32_t acquired_slot = kMaxBufferSlotCount;
+  uint32_t num_used_slot = 0;
+
+  // First look for a buffer slot in ready state, if no buffer slot found in ready state matching
+  // with current input config, assign a buffer slot in free state and allocate buffers for it.
+  for (uint32_t slot = 0; slot < kMaxBufferSlotCount && num_used_slot < num_used_slot_; slot++) {
+    HWBufferInfo &hw_buffer_info = buffer_slot_[slot].hw_buffer_info;
+
+    if (buffer_slot_[slot].state == kBufferSlotFree) {
+      free_slot = slot;
+    } else {
+      if ((buffer_slot_[slot].state == kBufferSlotReady)) {
+        if ((::memcmp(&buffer_config, &hw_buffer_info.buffer_config, sizeof(BufferConfig)) == 0)) {
+          buffer_slot_[slot].state = kBufferSlotAcquired;
+          acquired_slot = slot;
+          break;
+        }
+      }
+      num_used_slot++;
+    }
+  }
+
+  // If the input config does not match with existing config, then allocate buffers for the new
+  // buffer slot and change the state to kBufferSlotAcquired
+  if (acquired_slot == kMaxBufferSlotCount) {
+    if (free_slot >= kMaxBufferSlotCount) {
+      return kErrorMemory;
+    }
+
+    buffer_slot_[free_slot].hw_buffer_info.buffer_config = hw_buffer_info->buffer_config;
+
+    error = buffer_allocator_->AllocateBuffer(&buffer_slot_[free_slot].hw_buffer_info);
+    if (error != kErrorNone) {
+      return error;
+    }
+
+    buffer_slot_[free_slot].Init();
+    buffer_slot_[free_slot].state = kBufferSlotAcquired;
+    acquired_slot = free_slot;
+    num_used_slot_++;
+
+    DLOGI_IF(kTagBufferManager, "Allocate Buffer acquired_slot = %d ", acquired_slot);
+  }
+
+  const AllocatedBufferInfo &alloc_buffer_info =
+    buffer_slot_[acquired_slot].hw_buffer_info.alloc_buffer_info;
+  uint32_t curr_index = buffer_slot_[acquired_slot].curr_index;
+
+  // Wait for the release fence fd before buffer slot being given to the client.
+  buffer_sync_handler_->SyncWait(buffer_slot_[acquired_slot].release_fd[curr_index]);
+  buffer_slot_[acquired_slot].release_fd[curr_index] = -1;
+
+  hw_buffer_info->output_buffer.width = buffer_config.width;
+  hw_buffer_info->output_buffer.height = buffer_config.height;
+  hw_buffer_info->output_buffer.format = buffer_config.format;
+  hw_buffer_info->output_buffer.flags.secure = buffer_config.secure;
+
+  hw_buffer_info->output_buffer.planes[0].stride = alloc_buffer_info.stride;
+  hw_buffer_info->output_buffer.planes[0].fd = alloc_buffer_info.fd;
+  hw_buffer_info->output_buffer.planes[0].offset = buffer_slot_[acquired_slot].offset[curr_index];
+  hw_buffer_info->slot = acquired_slot;
+
+  DLOGI_IF(kTagBufferManager, "Output: w = %d h = %d f = %d session_id %d acquired slot = %d " \
+           "num_used_slot %d curr_index = %d offset %d", hw_buffer_info->output_buffer.width,
+           hw_buffer_info->output_buffer.height, hw_buffer_info->output_buffer.format,
+           hw_buffer_info->session_id, acquired_slot, num_used_slot_, curr_index,
+           hw_buffer_info->output_buffer.planes[0].offset);
+
+  return kErrorNone;
+}
+
+DisplayError BufferManager::Stop(int *session_ids) {
+  DisplayError error = kErrorNone;
+  uint32_t slot = 0, count = 0;
+
+  // Free all the buffer slots which were not acquired in the current cycle and deallocate the
+  // buffers associated with it.
+  while ((num_used_slot_ > 0) && (slot < kMaxBufferSlotCount)) {
+    if (buffer_slot_[slot].state == kBufferSlotReady) {
+      if (buffer_slot_[slot].hw_buffer_info.session_id != -1) {
+        session_ids[count++] = buffer_slot_[slot].hw_buffer_info.session_id;
+      }
+
+      error = FreeBufferSlot(slot);
+      if (error != kErrorNone) {
+        return error;
+      }
+
+      num_used_slot_--;
+    }
+    slot++;
+  }
+
+  session_ids[count] = -1;
+
+  return kErrorNone;
+}
+
+DisplayError BufferManager::SetReleaseFd(uint32_t slot, int fd) {
+  if ((slot >= kMaxBufferSlotCount) || (buffer_slot_[slot].state != kBufferSlotAcquired)) {
+    DLOGE("Invalid Parameters slot %d state %s", slot, buffer_slot_[slot].state);
+    kErrorParameters;
+  }
+
+  uint32_t &curr_index = buffer_slot_[slot].curr_index;
+  const HWBufferInfo &hw_buffer_info = buffer_slot_[slot].hw_buffer_info;
+  uint32_t buffer_count = hw_buffer_info.buffer_config.buffer_count;
+
+  // 1. Store the release fence fd, so that buffer manager waits for the release fence fd to be
+  //    signaled and gives the buffer slot to the client.
+  // 2. Modify the curr_index to point to next buffer.
+  buffer_slot_[slot].release_fd[curr_index] = fd;
+  curr_index = (curr_index + 1) % buffer_count;
+
+  DLOGI_IF(kTagBufferManager, "w = %d h = %d f = %d session_id %d slot = %d curr_index = %d " \
+           "sync fd %d", hw_buffer_info.output_buffer.width, hw_buffer_info.output_buffer.height,
+           hw_buffer_info.output_buffer.format, hw_buffer_info.session_id, slot, curr_index, fd);
+
+  return kErrorNone;
+}
+
+
+DisplayError BufferManager::SetSessionId(uint32_t slot, int session_id) {
+  if ((slot >= kMaxBufferSlotCount) || (buffer_slot_[slot].state != kBufferSlotAcquired)) {
+    DLOGE("Invalid Parameters slot %d state %s", slot, buffer_slot_[slot].state);
+    kErrorParameters;
+  }
+
+  HWBufferInfo *hw_buffer_info = &buffer_slot_[slot].hw_buffer_info;
+
+  hw_buffer_info->session_id = session_id;
+
+  DLOGI_IF(kTagBufferManager, "w = %d h = %d f = %d session_id %d slot = %d",
+           hw_buffer_info->output_buffer.width, hw_buffer_info->output_buffer.height,
+           hw_buffer_info->output_buffer.format, hw_buffer_info->session_id, slot);
+
+  return kErrorNone;
+}
+
+DisplayError BufferManager::FreeBufferSlot(uint32_t slot) {
+  DisplayError error = kErrorNone;
+
+  HWBufferInfo *hw_buffer_info = &buffer_slot_[slot].hw_buffer_info;
+
+  error = buffer_allocator_->FreeBuffer(hw_buffer_info);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  DLOGI_IF(kTagBufferManager, "session_id %d slot = %d num_used_slot %d",
+           hw_buffer_info->session_id, slot, num_used_slot_);
+
+  buffer_slot_[slot].Deinit();
+
+  return kErrorNone;
+}
+
+}  // namespace sde
diff --git a/displayengine/libs/core/buffer_manager.h b/displayengine/libs/core/buffer_manager.h
new file mode 100644
index 0000000..29bcd03
--- /dev/null
+++ b/displayengine/libs/core/buffer_manager.h
@@ -0,0 +1,82 @@
+/*
+* Copyright (c) 2015, 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 __BUFFER_MANAGER_H__
+#define __BUFFER_MANAGER_H__
+
+#include <utils/locker.h>
+#include <core/buffer_allocator.h>
+#include "hw_interface.h"
+
+namespace sde {
+
+class BufferManager {
+ public:
+  BufferManager(BufferAllocator *buffer_allocator, BufferSyncHandler *buffer_sync_handler);
+
+  void Start();
+  DisplayError GetNextBuffer(HWBufferInfo *hw_buffer_info);
+  DisplayError Stop(int *session_ids);
+  DisplayError SetReleaseFd(uint32_t slot, int fd);
+  DisplayError SetSessionId(uint32_t slot, int session_id);
+
+ private:
+  static const uint32_t kMaxBufferSlotCount = 32;
+
+  enum kBufferSlotState {
+    kBufferSlotFree     = 0,
+    kBufferSlotReady    = 1,
+    kBufferSlotAcquired = 2,
+  };
+
+  struct BufferSlot {
+    HWBufferInfo hw_buffer_info;
+    kBufferSlotState state;
+    int *release_fd;
+    uint32_t *offset;
+    uint32_t curr_index;
+
+    BufferSlot() : state(kBufferSlotFree), release_fd(NULL), offset(NULL), curr_index(0) { }
+    DisplayError Init();
+    DisplayError Deinit();
+  };
+
+  DisplayError FreeBufferSlot(uint32_t index);
+
+  BufferSlot buffer_slot_[kMaxBufferSlotCount];
+  BufferAllocator *buffer_allocator_;
+  BufferSyncHandler *buffer_sync_handler_;
+  uint32_t num_used_slot_;
+};
+
+}  // namespace sde
+
+#endif  // __BUFFER_MANAGER_H__
+
+
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index c35a4db..7e888ee 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -25,6 +25,7 @@
 #include <dlfcn.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
+#include <core/buffer_allocator.h>
 
 #include "comp_manager.h"
 #include "strategy_default.h"
@@ -38,12 +39,13 @@
     registered_displays_(0), configured_displays_(0), safe_mode_(false) {
 }
 
-DisplayError CompManager::Init(const HWResourceInfo &hw_res_info) {
+DisplayError CompManager::Init(const HWResourceInfo &hw_res_info, BufferAllocator *buffer_allocator,
+                               BufferSyncHandler *buffer_sync_handler) {
   SCOPE_LOCK(locker_);
 
   DisplayError error = kErrorNone;
 
-  error = res_mgr_.Init(hw_res_info);
+  error = res_mgr_.Init(hw_res_info, buffer_allocator, buffer_sync_handler);
   if (error != kErrorNone) {
     return error;
   }
@@ -108,6 +110,7 @@
                             &display_comp_ctx->strategy_intf) != kErrorNone) {
     DLOGW("Unable to create strategy interface");
     delete display_comp_ctx;
+    display_comp_ctx = NULL;
     return kErrorUndefined;
   }
 
@@ -115,15 +118,22 @@
   if (error != kErrorNone) {
     destroy_strategy_intf_(display_comp_ctx->strategy_intf);
     delete display_comp_ctx;
+    display_comp_ctx = NULL;
     return error;
   }
 
   SET_BIT(registered_displays_, type);
   display_comp_ctx->display_type = type;
   *display_ctx = display_comp_ctx;
-  // New display device has been added, so move the composition mode to safe mode until unless
+  // New non-primary display device has been added, so move the composition mode to safe mode until
   // resources for the added display is configured properly.
-  safe_mode_ = true;
+  if (type != kPrimary) {
+    safe_mode_ = true;
+  }
+
+  DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+           "display type %d", registered_displays_, configured_displays_,
+           display_comp_ctx->display_type);
 
   return kErrorNone;
 }
@@ -140,7 +150,14 @@
   CLEAR_BIT(registered_displays_, display_comp_ctx->display_type);
   CLEAR_BIT(configured_displays_, display_comp_ctx->display_type);
 
-  delete display_comp_ctx;
+  DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+           "display type %d", registered_displays_, configured_displays_,
+           display_comp_ctx->display_type);
+
+  if (display_comp_ctx) {
+    delete display_comp_ctx;
+    display_comp_ctx = NULL;
+  }
 
   return kErrorNone;
 }
@@ -223,16 +240,27 @@
   return error;
 }
 
-void CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
+DisplayError CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
   SCOPE_LOCK(locker_);
   DisplayCompositionContext *display_comp_ctx =
                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+  Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+
+  DisplayError error = kErrorNone;
+  error = res_mgr_.PostPrepare(display_resource_ctx, hw_layers);
+  if (error != kErrorNone) {
+    return error;
+  }
+
   display_comp_ctx->strategy_intf->Stop();
+
+  return kErrorNone;
 }
 
-void CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+DisplayError CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
   SCOPE_LOCK(locker_);
 
+  DisplayError error = kErrorNone;
   DisplayCompositionContext *display_comp_ctx =
                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
   SET_BIT(configured_displays_, display_comp_ctx->display_type);
@@ -240,9 +268,18 @@
       safe_mode_ = false;
   }
 
-  res_mgr_.PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
+  error = res_mgr_.PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
+  if (error != kErrorNone) {
+    return error;
+  }
 
   display_comp_ctx->idle_fallback = false;
+
+  DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+           "display type %d", registered_displays_, configured_displays_,
+           display_comp_ctx->display_type);
+
+  return kErrorNone;
 }
 
 void CompManager::Purge(Handle display_ctx) {
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index 674f0d0..24a0fff 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -36,15 +36,16 @@
 class CompManager : public DumpImpl {
  public:
   CompManager();
-  DisplayError Init(const HWResourceInfo &hw_res_info_);
+  DisplayError Init(const HWResourceInfo &hw_res_info_, BufferAllocator *buffer_allocator,
+                    BufferSyncHandler *buffer_sync_handler_);
   DisplayError Deinit();
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
                                Handle *res_mgr_hnd);
   DisplayError UnregisterDisplay(Handle res_mgr_hnd);
   void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
-  void PostPrepare(Handle display_ctx, HWLayers *hw_layers);
-  void PostCommit(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
   void Purge(Handle display_ctx);
   bool ProcessIdleTimeout(Handle display_ctx);
 
diff --git a/displayengine/libs/core/core_impl.cpp b/displayengine/libs/core/core_impl.cpp
old mode 100755
new mode 100644
index 0669f9f..bd6ab9a
--- a/displayengine/libs/core/core_impl.cpp
+++ b/displayengine/libs/core/core_impl.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -35,8 +35,10 @@
 
 namespace sde {
 
-CoreImpl::CoreImpl(CoreEventHandler *event_handler)
-  : event_handler_(event_handler), hw_intf_(NULL) {
+CoreImpl::CoreImpl(CoreEventHandler *event_handler, BufferAllocator *buffer_allocator,
+                   BufferSyncHandler *buffer_sync_handler)
+  : event_handler_(event_handler), buffer_allocator_(buffer_allocator),
+    buffer_sync_handler_(buffer_sync_handler), hw_intf_(NULL) {
 }
 
 DisplayError CoreImpl::Init() {
@@ -44,7 +46,7 @@
 
   DisplayError error = kErrorNone;
 
-  error = HWInterface::Create(&hw_intf_);
+  error = HWInterface::Create(&hw_intf_, buffer_sync_handler_);
   if (UNLIKELY(error != kErrorNone)) {
     return error;
   }
@@ -56,7 +58,7 @@
     return error;
   }
 
-  error = comp_mgr_.Init(hw_res_info);
+  error = comp_mgr_.Init(hw_res_info, buffer_allocator_, buffer_sync_handler_);
   if (UNLIKELY(error != kErrorNone)) {
     HWInterface::Destroy(hw_intf_);
     return error;
@@ -83,7 +85,7 @@
 }
 
 DisplayError CoreImpl::CreateDisplay(DisplayType type, DisplayEventHandler *event_handler,
-                                    DisplayInterface **intf) {
+                                     DisplayInterface **intf) {
   SCOPE_LOCK(locker_);
 
   if (UNLIKELY(!event_handler || !intf)) {
@@ -93,15 +95,15 @@
   DisplayBase *display_base = NULL;
   switch (type) {
   case kPrimary:
-    display_base = new DisplayPrimary(event_handler, hw_intf_, &comp_mgr_);
+    display_base = new DisplayPrimary(event_handler, hw_intf_, &comp_mgr_, &offline_ctrl_);
     break;
 
   case kHDMI:
-    display_base = new DisplayHDMI(event_handler, hw_intf_, &comp_mgr_);
+    display_base = new DisplayHDMI(event_handler, hw_intf_, &comp_mgr_, &offline_ctrl_);
     break;
 
   case kVirtual:
-    display_base = new DisplayVirtual(event_handler, hw_intf_, &comp_mgr_);
+    display_base = new DisplayVirtual(event_handler, hw_intf_, &comp_mgr_, &offline_ctrl_);
     break;
 
   default:
@@ -116,6 +118,7 @@
   DisplayError error = display_base->Init();
   if (UNLIKELY(error != kErrorNone)) {
     delete display_base;
+    display_base = NULL;
     return error;
   }
 
@@ -133,6 +136,7 @@
   DisplayBase *display_base = static_cast<DisplayBase *>(intf);
   display_base->Deinit();
   delete display_base;
+  display_base = NULL;
 
   return kErrorNone;
 }
diff --git a/displayengine/libs/core/core_impl.h b/displayengine/libs/core/core_impl.h
index ad86c60..e289a23 100644
--- a/displayengine/libs/core/core_impl.h
+++ b/displayengine/libs/core/core_impl.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -42,7 +42,8 @@
   // This class implements display core interface revision 1.0.
   static const uint16_t kRevision = SET_REVISION(1, 0);
 
-  explicit CoreImpl(CoreEventHandler *event_handler);
+  CoreImpl(CoreEventHandler *event_handler, BufferAllocator *buffer_allocator,
+           BufferSyncHandler *buffer_sync_handler);
   virtual ~CoreImpl() { }
 
   // This method returns the interface revision for the current display core object.
@@ -59,6 +60,8 @@
  protected:
   Locker locker_;
   CoreEventHandler *event_handler_;
+  BufferAllocator *buffer_allocator_;
+  BufferSyncHandler *buffer_sync_handler_;
   HWInterface *hw_intf_;
   CompManager comp_mgr_;
   OfflineCtrl offline_ctrl_;
diff --git a/displayengine/libs/core/core_interface.cpp b/displayengine/libs/core/core_interface.cpp
old mode 100755
new mode 100644
index fb8700a..c982b4d
--- a/displayengine/libs/core/core_interface.cpp
+++ b/displayengine/libs/core/core_interface.cpp
@@ -1,30 +1,36 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include <utils/locker.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
+#include <core/buffer_sync_handler.h>
 
 #include "core_impl.h"
 
@@ -45,11 +51,14 @@
   Locker locker;
 } g_core;
 
-DisplayError CoreInterface::CreateCore(CoreEventHandler *event_handler, LogHandler *log_handler,
+// TODO(user): Have a single structure handle carries all the interface pointers.
+DisplayError CoreInterface::CreateCore(CoreEventHandler *event_handler, DebugHandler *debug_handler,
+                                       BufferAllocator *buffer_allocator,
+                                       BufferSyncHandler *buffer_sync_handler,
                                        CoreInterface **interface, uint32_t client_version) {
   SCOPE_LOCK(g_core.locker);
 
-  if (UNLIKELY(!event_handler || !log_handler || !interface)) {
+  if (!event_handler || !debug_handler || !buffer_allocator || !buffer_sync_handler || !interface) {
     return kErrorParameters;
   }
 
@@ -68,11 +77,11 @@
     return kErrorUndefined;
   }
 
-  Debug::SetLogHandler(log_handler);
+  Debug::SetDebugHandler(debug_handler);
 
   // Create appropriate CoreImpl object based on client version.
   if (GET_REVISION(client_version) == CoreImpl::kRevision) {
-    core_impl = new CoreImpl(event_handler);
+    core_impl = new CoreImpl(event_handler, buffer_allocator, buffer_sync_handler);
   } else {
     return kErrorNotSupported;
   }
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 95e15d5..058bacc 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -26,17 +26,20 @@
 #include <utils/debug.h>
 
 #include "display_base.h"
+#include "offline_ctrl.h"
 
 #define __CLASS__ "DisplayBase"
 
 namespace sde {
 
+// TODO(user): Have a single structure handle carries all the interface pointers and variables.
 DisplayBase::DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
-             HWDeviceType hw_device_type, HWInterface *hw_intf, CompManager *comp_manager)
+                         HWDeviceType hw_device_type, HWInterface *hw_intf,
+                         CompManager *comp_manager, OfflineCtrl *offline_ctrl)
   : display_type_(display_type), event_handler_(event_handler), hw_device_type_(hw_device_type),
-    hw_intf_(hw_intf), comp_manager_(comp_manager), state_(kStateOff), hw_device_(0),
-    display_comp_ctx_(0), display_attributes_(NULL), num_modes_(0), active_mode_index_(0),
-    pending_commit_(false), vsync_enable_(false) {
+    hw_intf_(hw_intf), comp_manager_(comp_manager), offline_ctrl_(offline_ctrl), state_(kStateOff),
+    hw_device_(0), display_comp_ctx_(0), display_attributes_(NULL), num_modes_(0),
+    active_mode_index_(0), pending_commit_(false), vsync_enable_(false) {
 }
 
 DisplayError DisplayBase::Init() {
@@ -83,13 +86,21 @@
     goto CleanupOnError;
   }
 
+  error = offline_ctrl_->RegisterDisplay(display_type_, &display_offline_ctx_);
+  if (UNLIKELY(error != kErrorNone)) {
+    goto CleanupOnError;
+  }
+
   return kErrorNone;
 
 CleanupOnError:
-  comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  if (display_comp_ctx_) {
+    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  }
 
   if (display_attributes_) {
     delete[] display_attributes_;
+    display_attributes_ = NULL;
   }
 
   hw_intf_->Close(hw_device_);
@@ -100,8 +111,15 @@
 DisplayError DisplayBase::Deinit() {
   SCOPE_LOCK(locker_);
 
+  offline_ctrl_->UnregisterDisplay(display_offline_ctx_);
+
   comp_manager_->UnregisterDisplay(display_comp_ctx_);
-  delete[] display_attributes_;
+
+  if (display_attributes_) {
+    delete[] display_attributes_;
+    display_attributes_ = NULL;
+  }
+
   hw_intf_->Close(hw_device_);
 
   return kErrorNone;
@@ -118,7 +136,7 @@
 
   pending_commit_ = false;
 
-  if ((state_ == kStateOn)) {
+  if (state_ == kStateOn) {
     // Clean hw layers for reuse.
     hw_layers_.info = HWLayersInfo();
     hw_layers_.info.stack = layer_stack;
@@ -130,11 +148,17 @@
         break;
       }
 
-      error = hw_intf_->Validate(hw_device_, &hw_layers_);
+      error = offline_ctrl_->Prepare(display_offline_ctx_, &hw_layers_);
       if (error == kErrorNone) {
-        // Strategy is successful now, wait for Commit().
-        pending_commit_ = true;
-        break;
+        error = hw_intf_->Validate(hw_device_, &hw_layers_);
+        if (error == kErrorNone) {
+          error = comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+          if (error == kErrorNone) {
+            // Strategy is successful now, wait for Commit().
+            pending_commit_ = true;
+            break;
+          }
+        }
       }
     }
     comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
@@ -159,11 +183,18 @@
       DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
       return kErrorUndefined;
     }
-    error = hw_intf_->Commit(hw_device_, &hw_layers_);
+
+    error = offline_ctrl_->Commit(display_offline_ctx_, &hw_layers_);
     if (error == kErrorNone) {
-      comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
-    } else {
-      DLOGE("Unexpected error. Commit failed on driver.");
+      error = hw_intf_->Commit(hw_device_, &hw_layers_);
+      if (error == kErrorNone) {
+        error = comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
+        if (error != kErrorNone) {
+          DLOGE("Composition manager PostCommit failed");
+        }
+      } else {
+        DLOGE("Unexpected error. Commit failed on driver.");
+      }
     }
   } else {
     return kErrorNotSupported;
@@ -276,9 +307,14 @@
 
   switch (state) {
   case kStateOff:
-    hw_layers_.info.count = 0;
-    comp_manager_->Purge(display_comp_ctx_);
-    error = hw_intf_->PowerOff(hw_device_);
+    // Invoke flush during suspend for HDMI and virtual displays. StateOff is handled
+    // separately for primary in DisplayPrimary::SetDisplayState() function.
+    error = hw_intf_->Flush(hw_device_);
+    if (error == kErrorNone) {
+      comp_manager_->Purge(display_comp_ctx_);
+      state_ = state;
+      hw_layers_.info.count = 0;
+    }
     break;
 
   case kStateOn:
@@ -305,6 +341,36 @@
   return error;
 }
 
+DisplayError DisplayBase::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+  SCOPE_LOCK(locker_);
+  DisplayError error = kErrorNone;
+
+  if (!variable_info) {
+    return kErrorParameters;
+  }
+
+  HWDisplayAttributes display_attributes = display_attributes_[active_mode_index_];
+
+  display_attributes.x_pixels = variable_info->x_pixels;
+  display_attributes.y_pixels = variable_info->y_pixels;
+  display_attributes.fps = variable_info->fps;
+
+  // if display is already connected, unregister display from composition manager and register
+  // the display with new configuration.
+  if (display_comp_ctx_) {
+    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  }
+
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes, &display_comp_ctx_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  display_attributes_[active_mode_index_] = display_attributes;
+
+  return kErrorNone;
+}
+
 DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
   SCOPE_LOCK(locker_);
   DisplayError error = kErrorNone;
@@ -315,9 +381,18 @@
 
   error = hw_intf_->SetDisplayAttributes(hw_device_, index);
   if (error != kErrorNone) {
-    active_mode_index_ = index;
+    return error;
   }
 
+  active_mode_index_ = index;
+
+  if (display_comp_ctx_) {
+    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  }
+
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[index],
+                                         &display_comp_ctx_);
+
   return error;
 }
 
@@ -388,6 +463,8 @@
     HWLayerConfig &layer_config = hw_layers_.config[i];
     HWPipeInfo &left_pipe = hw_layers_.config[i].left_pipe;
     HWPipeInfo &right_pipe = hw_layers_.config[i].right_pipe;
+    HWRotateInfo &left_rotate = hw_layers_.config[i].rotates[0];
+    HWRotateInfo &right_rotate = hw_layers_.config[i].rotates[1];
 
     AppendString(buffer, length, "\n\nsde idx: %u, actual idx: %u", i, hw_layers_.info.index[i]);
     AppendString(buffer, length, "\nw: %u, h: %u, fmt: %u",
@@ -395,13 +472,29 @@
     AppendRect(buffer, length, "\nsrc_rect:", &layer.src_rect);
     AppendRect(buffer, length, "\ndst_rect:", &layer.dst_rect);
 
-    AppendString(buffer, length, "\n\tleft split =>");
-    AppendString(buffer, length, "\n\t  pipe id: 0x%x", left_pipe.pipe_id);
-    AppendRect(buffer, length, "\n\t  src_roi:", &left_pipe.src_roi);
-    AppendRect(buffer, length, "\n\t  dst_roi:", &left_pipe.dst_roi);
+    if (left_rotate.valid) {
+      AppendString(buffer, length, "\n\tleft rotate =>");
+      AppendString(buffer, length, "\n\t  pipe id: 0x%x", left_rotate.pipe_id);
+      AppendRect(buffer, length, "\n\t  src_roi:", &left_rotate.src_roi);
+      AppendRect(buffer, length, "\n\t  dst_roi:", &left_rotate.dst_roi);
+    }
 
-    if (layer_config.is_right_pipe) {
-      AppendString(buffer, length, "\n\tright split =>");
+    if (right_rotate.valid) {
+      AppendString(buffer, length, "\n\tright rotate =>");
+      AppendString(buffer, length, "\n\t  pipe id: 0x%x", right_rotate.pipe_id);
+      AppendRect(buffer, length, "\n\t  src_roi:", &right_rotate.src_roi);
+      AppendRect(buffer, length, "\n\t  dst_roi:", &right_rotate.dst_roi);
+    }
+
+    if (left_pipe.valid) {
+      AppendString(buffer, length, "\n\tleft pipe =>");
+      AppendString(buffer, length, "\n\t  pipe id: 0x%x", left_pipe.pipe_id);
+      AppendRect(buffer, length, "\n\t  src_roi:", &left_pipe.src_roi);
+      AppendRect(buffer, length, "\n\t  dst_roi:", &left_pipe.dst_roi);
+    }
+
+    if (right_pipe.valid) {
+      AppendString(buffer, length, "\n\tright pipe =>");
       AppendString(buffer, length, "\n\t  pipe id: 0x%x", right_pipe.pipe_id);
       AppendRect(buffer, length, "\n\t  src_roi:", &right_pipe.src_roi);
       AppendRect(buffer, length, "\n\t  dst_roi:", &right_pipe.dst_roi);
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 5ff219b..d2b67e3 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -31,13 +31,18 @@
 
 #include "hw_interface.h"
 #include "comp_manager.h"
+#include "buffer_manager.h"
+
 
 namespace sde {
 
+class OfflineCtrl;
+
 class DisplayBase : public DisplayInterface, HWEventHandler, DumpImpl {
  public:
   DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
-              HWDeviceType hw_device_type, HWInterface *hw_intf, CompManager *comp_manager);
+              HWDeviceType hw_device_type, HWInterface *hw_intf, CompManager *comp_manager,
+              OfflineCtrl *offline_ctrl);
   virtual ~DisplayBase() { }
   virtual DisplayError Init();
   virtual DisplayError Deinit();
@@ -51,6 +56,7 @@
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
   virtual DisplayError SetDisplayState(DisplayState state);
+  virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
   virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetVSyncState(bool enable);
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
@@ -73,9 +79,11 @@
   HWDeviceType hw_device_type_;
   HWInterface *hw_intf_;
   CompManager *comp_manager_;
+  OfflineCtrl *offline_ctrl_;
   DisplayState state_;
   Handle hw_device_;
   Handle display_comp_ctx_;
+  Handle display_offline_ctx_;
   HWDisplayAttributes *display_attributes_;
   uint32_t num_modes_;
   uint32_t active_mode_index_;
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index 07bbca0..ed2a859 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,9 +32,8 @@
 namespace sde {
 
 DisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf,
-                         CompManager *comp_manager)
-  : DisplayBase(kHDMI, event_handler, kDeviceHDMI, hw_intf, comp_manager) {
-}
+                         CompManager *comp_manager, OfflineCtrl *offline_ctrl)
+  : DisplayBase(kHDMI, event_handler, kDeviceHDMI, hw_intf, comp_manager, offline_ctrl) { }
 
 int DisplayHDMI::GetBestConfig() {
   uint32_t best_config_mode = 0;
@@ -77,29 +76,5 @@
   return best_config_mode;
 }
 
-DisplayError DisplayHDMI::SetDisplayState(DisplayState state) {
-  DisplayError error = kErrorNone;
-
-  DLOGI("Set state = %d", state);
-
-  if (state == kStateOff) {
-    SCOPE_LOCK(locker_);
-    if (state == state_) {
-      DLOGI("Same state transition is requested.");
-      return kErrorNone;
-    }
-    error = hw_intf_->Flush(hw_device_);
-    if (error == kErrorNone) {
-      comp_manager_->Purge(display_comp_ctx_);
-      state_ = state;
-      hw_layers_.info.count = 0;
-    }
-  } else {
-    error = DisplayBase::SetDisplayState(state);
-  }
-
-  return error;
-}
-
 }  // namespace sde
 
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 8de7fdf..91e4797 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -31,9 +31,9 @@
 
 class DisplayHDMI : public DisplayBase {
  public:
-  DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager);
+  DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager,
+              OfflineCtrl *offline_ctrl);
   virtual int GetBestConfig();
-  virtual DisplayError SetDisplayState(DisplayState state);
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
old mode 100755
new mode 100644
index e4bd031..ac44fe3
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,8 +32,31 @@
 namespace sde {
 
 DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInterface *hw_intf,
-                               CompManager *comp_manager)
-  : DisplayBase(kPrimary, event_handler, kDevicePrimary, hw_intf, comp_manager) {
+                               CompManager *comp_manager, OfflineCtrl *offline_ctrl)
+  : DisplayBase(kPrimary, event_handler, kDevicePrimary, hw_intf, comp_manager, offline_ctrl) { }
+
+DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
+  DisplayError error = kErrorNone;
+
+  DLOGI("Set state = %d", state);
+
+  if (state == kStateOff) {
+    SCOPE_LOCK(locker_);
+    if (state == state_) {
+      DLOGI("Same state transition is requested.");
+      return kErrorNone;
+    }
+    error = hw_intf_->PowerOff(hw_device_);
+    if (error == kErrorNone) {
+      comp_manager_->Purge(display_comp_ctx_);
+      state_ = state;
+      hw_layers_.info.count = 0;
+    }
+  } else {
+    error = DisplayBase::SetDisplayState(state);
+  }
+
+  return error;
 }
 
 }  // namespace sde
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index 183e964..79fbddf 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,7 +32,8 @@
 class DisplayPrimary : public DisplayBase {
  public:
   DisplayPrimary(DisplayEventHandler *event_handler, HWInterface *hw_intf,
-                 CompManager *comp_manager);
+                 CompManager *comp_manager, OfflineCtrl *offline_ctrl);
+  virtual DisplayError SetDisplayState(DisplayState state);
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/display_virtual.cpp b/displayengine/libs/core/display_virtual.cpp
old mode 100755
new mode 100644
index 2fef178..84a825f
--- a/displayengine/libs/core/display_virtual.cpp
+++ b/displayengine/libs/core/display_virtual.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,9 +32,8 @@
 namespace sde {
 
 DisplayVirtual::DisplayVirtual(DisplayEventHandler *event_handler, HWInterface *hw_intf,
-                               CompManager *comp_manager)
-  : DisplayBase(kVirtual, event_handler, kDeviceVirtual, hw_intf, comp_manager) {
-}
+                               CompManager *comp_manager, OfflineCtrl *offline_ctrl)
+  : DisplayBase(kVirtual, event_handler, kDeviceVirtual, hw_intf, comp_manager, offline_ctrl) { }
 
 }  // namespace sde
 
diff --git a/displayengine/libs/core/display_virtual.h b/displayengine/libs/core/display_virtual.h
index a8e29e7..9697702 100644
--- a/displayengine/libs/core/display_virtual.h
+++ b/displayengine/libs/core/display_virtual.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,7 +32,7 @@
 class DisplayVirtual : public DisplayBase {
  public:
   DisplayVirtual(DisplayEventHandler *event_handler, HWInterface *hw_intf,
-                 CompManager *comp_manager);
+                 CompManager *comp_manager, OfflineCtrl *offline_ctrl);
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index 57a2b69..5d1f725 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -1,25 +1,30 @@
 /*
 * Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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.
 */
 
 #define __STDC_FORMAT_MACROS
@@ -39,9 +44,10 @@
 
 #include "hw_framebuffer.h"
 
+
 #define __CLASS__ "HWFrameBuffer"
 
-#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, display = %d errno = %d, desc = %s", #ioctl, \
+#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, \
                                       type, errno, strerror(errno))
 
 #ifdef DISPLAY_CORE_VIRTUAL_DRIVER
@@ -59,9 +65,10 @@
 
 namespace sde {
 
-HWFrameBuffer::HWFrameBuffer() : event_thread_name_("SDE_EventThread"), fake_vsync_(false),
-                                 exit_threads_(false), fb_path_("/sys/devices/virtual/graphics/fb"),
-                                 hotplug_enabled_(false) {
+HWFrameBuffer::HWFrameBuffer(BufferSyncHandler *buffer_sync_handler)
+  : event_thread_name_("SDE_EventThread"), fake_vsync_(false), exit_threads_(false),
+    fb_path_("/sys/devices/virtual/graphics/fb"), hotplug_enabled_(false),
+    buffer_sync_handler_(buffer_sync_handler) {
   // Pointer to actual driver interfaces.
   ioctl_ = ::ioctl;
   open_ = ::open;
@@ -165,6 +172,10 @@
     goto CleanupOnError;
   }
 
+  // Disable HPD at start if HDMI is external, it will be enabled later when the display powers on
+  // This helps for framework reboot or adb shell stop/start
+  EnableHotPlugDetection(0);
+
   return kErrorNone;
 
 CleanupOnError:
@@ -190,7 +201,7 @@
 
   for (int display = 0; display < kNumPhysicalDisplays; display++) {
     for (int event = 0; event < kNumDisplayEvents; event++) {
-      close(poll_fds_[display][event].fd);
+      close_(poll_fds_[display][event].fd);
     }
   }
   if (supported_video_modes_) {
@@ -225,16 +236,20 @@
   case kDeviceVirtual:
     snprintf(device_name, sizeof(device_name), "%s%d", "/dev/graphics/fb", fb_node_index_[type]);
     break;
+  case kDeviceRotator:
+    snprintf(device_name, sizeof(device_name), "%s", "/dev/mdss_rotator");
+    break;
   default:
     break;
   }
 
   hw_context->device_fd = open_(device_name, O_RDWR);
   if (hw_context->device_fd < 0) {
-    DLOGE("open %s failed.", device_name);
-    error = kErrorResources;
+    DLOGE("open %s failed err = %d errstr = %s", device_name, errno,  strerror(errno));
     delete hw_context;
+    return kErrorResources;
   }
+
   hw_context->type = type;
 
   *device = hw_context;
@@ -247,6 +262,7 @@
 
   switch (hw_context->type) {
   case kDevicePrimary:
+  case kDeviceVirtual:
     break;
   case kDeviceHDMI:
     hdmi_mode_count_ = 0;
@@ -268,6 +284,7 @@
 
   switch (hw_context->type) {
   case kDevicePrimary:
+  case kDeviceVirtual:
     *count = 1;
     break;
   case kDeviceHDMI:
@@ -286,6 +303,8 @@
 DisplayError HWFrameBuffer::GetDisplayAttributes(Handle device,
                                                  HWDisplayAttributes *display_attributes,
                                                  uint32_t index) {
+  DTRACE_SCOPED();
+
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
   int &device_fd = hw_context->device_fd;
   // Variable screen info
@@ -294,7 +313,7 @@
   switch (hw_context->type) {
   case kDevicePrimary:
     {
-      if (ioctl_(device_fd, FBIOGET_VSCREENINFO, &var_screeninfo) == -1) {
+      if (ioctl_(device_fd, FBIOGET_VSCREENINFO, &var_screeninfo) < 0) {
         IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
         return kErrorHardware;
       }
@@ -302,7 +321,7 @@
       // Frame rate
       STRUCT_VAR(msmfb_metadata, meta_data);
       meta_data.op = metadata_op_frame_rate;
-      if (ioctl_(device_fd, MSMFB_METADATA_GET, &meta_data) == -1) {
+      if (ioctl_(device_fd, MSMFB_METADATA_GET, &meta_data) < 0) {
         IOCTL_LOGE(MSMFB_METADATA_GET, hw_context->type);
         return kErrorHardware;
       }
@@ -357,6 +376,9 @@
     }
     break;
 
+  case kDeviceVirtual:
+    break;
+
   default:
     return kErrorParameters;
   }
@@ -365,18 +387,21 @@
 }
 
 DisplayError HWFrameBuffer::SetDisplayAttributes(Handle device, uint32_t index) {
+  DTRACE_SCOPED();
+
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
   DisplayError error = kErrorNone;
 
   switch (hw_context->type) {
   case kDevicePrimary:
+  case kDeviceVirtual:
     break;
 
   case kDeviceHDMI:
     {
       // Variable screen info
       STRUCT_VAR(fb_var_screeninfo, vscreeninfo);
-      if (ioctl_(hw_context->device_fd, FBIOGET_VSCREENINFO, &vscreeninfo) == -1) {
+      if (ioctl_(hw_context->device_fd, FBIOGET_VSCREENINFO, &vscreeninfo) < 0) {
         IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
         return kErrorHardware;
       }
@@ -402,7 +427,7 @@
       STRUCT_VAR(msmfb_metadata, metadata);
       metadata.op = metadata_op_vic;
       metadata.data.video_info_code = timing_mode->video_format;
-      if (ioctl(hw_context->device_fd, MSMFB_METADATA_SET, &metadata) == -1) {
+      if (ioctl(hw_context->device_fd, MSMFB_METADATA_SET, &metadata) < 0) {
         IOCTL_LOGE(MSMFB_METADATA_SET, hw_context->type);
         return kErrorHardware;
       }
@@ -413,7 +438,7 @@
             vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
 
       vscreeninfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
-      if (ioctl_(hw_context->device_fd, FBIOPUT_VSCREENINFO, &vscreeninfo) == -1) {
+      if (ioctl_(hw_context->device_fd, FBIOPUT_VSCREENINFO, &vscreeninfo) < 0) {
         IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
         return kErrorHardware;
       }
@@ -455,9 +480,11 @@
 
 
 DisplayError HWFrameBuffer::PowerOn(Handle device) {
+  DTRACE_SCOPED();
+
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
 
-  if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_UNBLANK) == -1) {
+  if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
     IOCTL_LOGE(FB_BLANK_UNBLANK, hw_context->type);
     return kErrorHardware;
   }
@@ -471,11 +498,14 @@
 }
 
 DisplayError HWFrameBuffer::PowerOff(Handle device) {
+  DTRACE_SCOPED();
+
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+  HWDisplay *hw_display = &hw_context->hw_display;
 
   switch (hw_context->type) {
   case kDevicePrimary:
-    if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) == -1) {
+    if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
       IOCTL_LOGE(FB_BLANK_POWERDOWN, hw_context->type);
       return kErrorHardware;
     }
@@ -500,9 +530,11 @@
 }
 
 DisplayError HWFrameBuffer::SetVSyncState(Handle device, bool enable) {
+  DTRACE_SCOPED();
+
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
   int vsync_on = enable ? 1 : 0;
-  if (ioctl_(hw_context->device_fd, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) == -1) {
+  if (ioctl_(hw_context->device_fd, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) {
     IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, hw_context->type);
     return kErrorHardware;
   }
@@ -510,65 +542,222 @@
   return kErrorNone;
 }
 
-DisplayError HWFrameBuffer::Validate(Handle device, HWLayers *hw_layers) {
-  DisplayError error = kErrorNone;
+DisplayError HWFrameBuffer::OpenRotatorSession(Handle device, HWLayers *hw_layers) {
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+  HWRotator *hw_rotator = &hw_context->hw_rotator;
+
+  hw_rotator->Reset();
+
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+    LayerBuffer *input_buffer = layer.input_buffer;
+    bool rot90 = (layer.transform.rotation == 90.0f);
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+      if (rotate_info->valid) {
+        HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+
+        if (rot_buf_info->session_id < 0) {
+          STRUCT_VAR(mdp_rotation_config, mdp_rot_config);
+          mdp_rot_config.version = MDP_ROTATION_REQUEST_VERSION_1_0;
+          mdp_rot_config.input.width = input_buffer->width;
+          mdp_rot_config.input.height = input_buffer->height;
+          SetFormat(input_buffer->format, &mdp_rot_config.input.format);
+          mdp_rot_config.output.width = rot_buf_info->output_buffer.width;
+          mdp_rot_config.output.height = rot_buf_info->output_buffer.height;
+          SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_config.output.format);
+          mdp_rot_config.frame_rate = layer.frame_rate;
+
+          if (ioctl_(hw_context->device_fd, MDSS_ROTATION_OPEN, &mdp_rot_config) < 0) {
+            IOCTL_LOGE(MDSS_ROTATION_OPEN, hw_context->type);
+            return kErrorHardware;
+          }
+
+          rot_buf_info->session_id = mdp_rot_config.session_id;
+
+          DLOGV_IF(kTagDriverConfig, "session_id %d", rot_buf_info->session_id);
+        }
+      }
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::CloseRotatorSession(Handle device, int32_t session_id) {
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
 
-  hw_context->ResetMDPCommit();
+  if (ioctl_(hw_context->device_fd, MDSS_ROTATION_CLOSE, (uint32_t)session_id) < 0) {
+    IOCTL_LOGE(MDSS_ROTATION_CLOSE, hw_context->type);
+    return kErrorHardware;
+  }
+
+  DLOGV_IF(kTagDriverConfig, "session_id %d", session_id);
+
+  return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::Validate(Handle device, HWLayers *hw_layers) {
+  DTRACE_SCOPED();
+
+  DisplayError error = kErrorNone;
+
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+  switch (hw_context->type) {
+    case kDevicePrimary:
+    case kDeviceHDMI:
+    case kDeviceVirtual:
+      error = DisplayValidate(hw_context, hw_layers);
+      if (error != kErrorNone) {
+        return error;
+      }
+      break;
+    case kDeviceRotator:
+      error = RotatorValidate(hw_context, hw_layers);
+      if (error != kErrorNone) {
+        return error;
+      }
+      break;
+    default:
+      break;
+  }
+  return error;
+}
+
+DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
+  DisplayError error = kErrorNone;
+
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+  switch (hw_context->type) {
+    case kDevicePrimary:
+    case kDeviceHDMI:
+    case kDeviceVirtual:
+      error = DisplayCommit(hw_context, hw_layers);
+      if (error != kErrorNone) {
+        return error;
+      }
+      break;
+    case kDeviceRotator:
+      error = RotatorCommit(hw_context, hw_layers);
+      if (error != kErrorNone) {
+        return error;
+      }
+      break;
+    default:
+      break;
+  }
+  return error;
+}
+
+DisplayError HWFrameBuffer::DisplayValidate(HWContext *hw_context, HWLayers *hw_layers) {
+  DisplayError error = kErrorNone;
+  HWDisplay *hw_display = &hw_context->hw_display;
+
+  hw_display->Reset();
 
   HWLayersInfo &hw_layer_info = hw_layers->info;
   LayerStack *stack = hw_layer_info.stack;
 
-  mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
-  mdp_input_layer *mdp_layers = hw_context->mdp_layers;
+  DLOGV_IF(kTagDriverConfig, "************************** %s Validate Input ***********************",
+           GetDeviceString(hw_context->type));
+  DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
+
+  mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
+  mdp_input_layer *mdp_layers = hw_display->mdp_in_layers;
+  mdp_output_layer *mdp_out_layer = &hw_display->mdp_out_layer;
   uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt;
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     uint32_t layer_index = hw_layer_info.index[i];
     Layer &layer = stack->layers[layer_index];
     LayerBuffer *input_buffer = layer.input_buffer;
-    HWLayerConfig &config = hw_layers->config[i];
+    HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+    HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
+    mdp_input_layer mdp_layer;
 
-    uint32_t split_count = hw_layers->config[i].is_right_pipe ? 2 : 1;
-    for (uint32_t j = 0; j < split_count; j++) {
-      HWPipeInfo &pipe = (j == 0) ? config.left_pipe : config.right_pipe;
-      mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_count];
-      mdp_layer.alpha = layer.plane_alpha;
-      mdp_layer.z_order = static_cast<uint16_t>(i);
-      mdp_layer.transp_mask = 0xffffffff;
-      mdp_layer.horz_deci = pipe.horizontal_decimation;
-      mdp_layer.vert_deci = pipe.vertical_decimation;
+    for (uint32_t count = 0; count < 2; count++) {
+      HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
 
-      SetBlending(layer.blending, &mdp_layer.blend_op);
-
-      SetRect(pipe.src_roi, &mdp_layer.src_rect);
-      SetRect(pipe.dst_roi, &mdp_layer.dst_rect);
-
-      mdp_layer.pipe_ndx = pipe.pipe_id;
-
-      mdp_layer_buffer &mdp_buffer_left = mdp_layer.buffer;
-      mdp_buffer_left.width = input_buffer->width;
-      mdp_buffer_left.height = input_buffer->height;
-
-      error = SetFormat(layer.input_buffer->format, &mdp_buffer_left.format);
-      if (error != kErrorNone) {
-        return error;
+      if (rotate_info->valid) {
+        input_buffer = &rotate_info->hw_buffer_info.output_buffer;
       }
 
-      if (layer.transform.flip_vertical) {
-        mdp_layer.flags |= MDP_LAYER_FLIP_UD;
-      }
+      if (pipe_info->valid) {
+        mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_count];
+        mdp_layer_buffer &mdp_buffer = mdp_layer.buffer;
 
-      if (layer.transform.flip_horizontal) {
-        mdp_layer.flags |= MDP_LAYER_FLIP_LR;
-      }
+        mdp_buffer.width = input_buffer->width;
+        mdp_buffer.height = input_buffer->height;
 
-      mdp_layer_count++;
+        error = SetFormat(input_buffer->format, &mdp_buffer.format);
+        if (error != kErrorNone) {
+          return error;
+        }
+
+        mdp_layer.alpha = layer.plane_alpha;
+        mdp_layer.z_order = static_cast<uint16_t>(i);
+        mdp_layer.transp_mask = 0xffffffff;
+        SetBlending(layer.blending, &mdp_layer.blend_op);
+        mdp_layer.pipe_ndx = pipe_info->pipe_id;
+        mdp_layer.horz_deci = pipe_info->horizontal_decimation;
+        mdp_layer.vert_deci = pipe_info->vertical_decimation;
+
+        SetRect(pipe_info->src_roi, &mdp_layer.src_rect);
+        SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
+
+        // Flips will be taken care by rotator, if layer requires 90 rotation. So Dont use MDP for
+        // flip operation, if layer transform is 90.
+        if (!layer.transform.rotation) {
+          if (layer.transform.flip_vertical) {
+            mdp_layer.flags |= MDP_LAYER_FLIP_UD;
+          }
+
+          if (layer.transform.flip_horizontal) {
+            mdp_layer.flags |= MDP_LAYER_FLIP_LR;
+          }
+        }
+
+        mdp_layer_count++;
+
+        DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
+                 i, count ? "Right" : "Left");
+        DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d", mdp_buffer.width, mdp_buffer.height,
+                 mdp_buffer.format);
+        DLOGV_IF(kTagDriverConfig, "plane_alpha %d, zorder %d, blending %d, horz_deci %d, "
+                 "vert_deci %d", mdp_layer.alpha, mdp_layer.z_order, mdp_layer.blend_op,
+                 mdp_layer.horz_deci, mdp_layer.vert_deci);
+        DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_layer.src_rect.x,
+                 mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h);
+        DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x,
+                 mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h);
+        DLOGV_IF(kTagDriverConfig, "*************************************************************");
+      }
     }
   }
 
+  if (hw_context->type == kDeviceVirtual) {
+    LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+    // TODO(user): Need to assign the writeback id from the resource manager, since the support
+    // has not been added hard coding it to 2 for now.
+    mdp_out_layer->writeback_ndx = 2;
+    mdp_out_layer->buffer.width = output_buffer->width;
+    mdp_out_layer->buffer.height = output_buffer->height;
+    SetFormat(output_buffer->format, &mdp_out_layer->buffer.format);
+
+    DLOGI_IF(kTagDriverConfig, "******************* Output buffer Info **********************");
+    DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d",
+             mdp_out_layer->buffer.width, mdp_out_layer->buffer.height,
+             mdp_out_layer->buffer.format, mdp_out_layer->writeback_ndx);
+    DLOGI_IF(kTagDriverConfig, "*************************************************************");
+  }
+
   mdp_commit.flags |= MDP_VALIDATE_LAYER;
-  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
     return kErrorHardware;
   }
@@ -576,67 +765,305 @@
   return kErrorNone;
 }
 
-DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
-  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+DisplayError HWFrameBuffer::DisplayCommit(HWContext *hw_context, HWLayers *hw_layers) {
+  DTRACE_SCOPED();
+
+  HWDisplay *hw_display = &hw_context->hw_display;
   HWLayersInfo &hw_layer_info = hw_layers->info;
   LayerStack *stack = hw_layer_info.stack;
 
-  mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
-  mdp_input_layer *mdp_layers = hw_context->mdp_layers;
+  DLOGV_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+           GetDeviceString(hw_context->type));
+  DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
+
+  mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
+  mdp_input_layer *mdp_layers = hw_display->mdp_in_layers;
+  mdp_output_layer *mdp_out_layer = &hw_display->mdp_out_layer;
   uint32_t mdp_layer_index = 0;
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     uint32_t layer_index = hw_layer_info.index[i];
     LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
+    HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+    HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
 
-    uint32_t split_count = hw_layers->config[i].is_right_pipe ? 2 : 1;
-    for (uint32_t j = 0; j < split_count; j++) {
-      mdp_layer_buffer &mdp_buffer = mdp_layers[mdp_layer_index].buffer;
+    for (uint32_t count = 0; count < 2; count++) {
+      HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
 
-      if (input_buffer->planes[0].fd >= 0) {
-        mdp_buffer.plane_count = 1;
-        mdp_buffer.planes[0].fd = input_buffer->planes[0].fd;
-        mdp_buffer.planes[0].offset = input_buffer->planes[0].offset;
-        mdp_buffer.planes[0].stride = input_buffer->planes[0].stride;
-      } else {
-        DLOGW("Invalid buffer fd, setting plane count to 0");
-        mdp_buffer.plane_count = 0;
+      if (rotate_info->valid) {
+        input_buffer = &rotate_info->hw_buffer_info.output_buffer;
       }
 
-      mdp_buffer.fence = input_buffer->acquire_fence_fd;
-      mdp_layer_index++;
+      if (pipe_info->valid) {
+        mdp_layer_buffer &mdp_buffer = mdp_layers[mdp_layer_index].buffer;
+        mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_index];
+        if (input_buffer->planes[0].fd >= 0) {
+          mdp_buffer.plane_count = 1;
+          mdp_buffer.planes[0].fd = input_buffer->planes[0].fd;
+          mdp_buffer.planes[0].offset = input_buffer->planes[0].offset;
+          SetStride(hw_context->type, input_buffer->format, input_buffer->planes[0].stride,
+                    &mdp_buffer.planes[0].stride);
+        } else {
+          DLOGW("Invalid buffer fd, setting plane count to 0");
+          mdp_buffer.plane_count = 0;
+        }
+
+        mdp_buffer.fence = input_buffer->acquire_fence_fd;
+        mdp_layer_index++;
+
+        DLOGV_IF(kTagDriverConfig, "****************** Layer[%d] %s pipe Input *******************",
+                 i, count ? "Right" : "Left");
+        DLOGI_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d, horz_deci %d, vert_deci %d",
+                 mdp_buffer.width, mdp_buffer.height, mdp_buffer.format, mdp_layer.horz_deci,
+                 mdp_layer.vert_deci);
+        DLOGI_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_buf_stride %d, " \
+                 "in_plane_count %d, in_fence %d, layer count %d", mdp_buffer.planes[0].fd,
+                 mdp_buffer.planes[0].offset, mdp_buffer.planes[0].stride, mdp_buffer.plane_count,
+                 mdp_buffer.fence, mdp_commit.input_layer_cnt);
+        DLOGV_IF(kTagDriverConfig, "*************************************************************");
+      }
     }
   }
+  if (hw_context->type == kDeviceVirtual) {
+    LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
 
+    if (output_buffer->planes[0].fd >= 0) {
+      mdp_out_layer->buffer.planes[0].fd = output_buffer->planes[0].fd;
+      mdp_out_layer->buffer.planes[0].offset = output_buffer->planes[0].offset;
+      SetStride(hw_context->type, output_buffer->format, output_buffer->planes[0].stride,
+                &mdp_out_layer->buffer.planes[0].stride);
+      mdp_out_layer->buffer.plane_count = 1;
+    } else {
+      DLOGW("Invalid output buffer fd, setting plane count to 0");
+      mdp_out_layer->buffer.plane_count = 0;
+    }
+
+    mdp_out_layer->buffer.fence = output_buffer->acquire_fence_fd;
+
+    DLOGI_IF(kTagDriverConfig, "******************* Output buffer Info **********************");
+    DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, acquire_fence %d",
+             mdp_out_layer->buffer.planes[0].fd, mdp_out_layer->buffer.planes[0].offset,
+             mdp_out_layer->buffer.planes[0].stride,  mdp_out_layer->buffer.fence);
+    DLOGI_IF(kTagDriverConfig, "*************************************************************");
+  }
+
+  mdp_commit.release_fence = -1;
   mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
-  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) < 0) {
     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
     return kErrorHardware;
   }
 
+  stack->retire_fence_fd = mdp_commit.retire_fence;
+
   // MDP returns only one release fence for the entire layer stack. Duplicate this fence into all
   // layers being composed by MDP.
-  stack->retire_fence_fd = mdp_commit.retire_fence;
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     uint32_t layer_index = hw_layer_info.index[i];
     LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
+    HWRotateInfo *left_rotate = &hw_layers->config[i].rotates[0];
+    HWRotateInfo *right_rotate = &hw_layers->config[i].rotates[1];
 
-    input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+    if (!left_rotate->valid && !right_rotate->valid) {
+      input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+      continue;
+    }
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+      if (rotate_info->valid) {
+        input_buffer = &rotate_info->hw_buffer_info.output_buffer;
+        input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+        close_(input_buffer->acquire_fence_fd);
+        input_buffer->acquire_fence_fd = -1;
+      }
+    }
   }
-  close(mdp_commit.release_fence);
+  DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+           GetDeviceString(hw_context->type));
+  DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd);
+  DLOGI_IF(kTagDriverConfig, "*************************************************************");
+
+  close_(mdp_commit.release_fence);
+
+  return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::RotatorValidate(HWContext *hw_context, HWLayers *hw_layers) {
+  HWRotator *hw_rotator = &hw_context->hw_rotator;
+  DLOGV_IF(kTagDriverConfig, "************************* %s Validate Input ************************",
+           GetDeviceString(hw_context->type));
+
+  hw_rotator->Reset();
+
+  mdp_rotation_request *mdp_rot_request = &hw_rotator->mdp_rot_req;
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+
+  uint32_t &rot_count = mdp_rot_request->count;
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+      if (rotate_info->valid) {
+        HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+        mdp_rotation_item *mdp_rot_item = &mdp_rot_request->list[rot_count];
+        bool rot90 = (layer.transform.rotation == 90.0f);
+
+        if (rot90) {
+          mdp_rot_item->flags |= MDP_ROTATION_90;
+        }
+
+        if (layer.transform.flip_horizontal) {
+          mdp_rot_item->flags |= MDP_ROTATION_FLIP_LR;
+        }
+
+        if (layer.transform.flip_vertical) {
+          mdp_rot_item->flags |= MDP_ROTATION_FLIP_UD;
+        }
+
+        SetRect(rotate_info->src_roi, &mdp_rot_item->src_rect);
+        SetRect(rotate_info->dst_roi, &mdp_rot_item->dst_rect);
+
+        // TODO(user): Need to assign the writeback id and pipe id  returned from resource manager.
+        mdp_rot_item->pipe_idx = 0;
+        mdp_rot_item->wb_idx = 0;
+
+        mdp_rot_item->input.width = layer.input_buffer->width;
+        mdp_rot_item->input.height = layer.input_buffer->height;
+        SetFormat(layer.input_buffer->format, &mdp_rot_item->input.format);
+
+        mdp_rot_item->output.width = rot_buf_info->output_buffer.width;
+        mdp_rot_item->output.height = rot_buf_info->output_buffer.height;
+        SetFormat(rot_buf_info->output_buffer.format, &mdp_rot_item->output.format);
+
+        rot_count++;
+
+        DLOGV_IF(kTagDriverConfig, "******************** Layer[%d] %s rotate ********************",
+                 i, count ? "Right" : "Left");
+        DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d,\t out_w %d, out_h %d, out_f %d",
+                 mdp_rot_item->input.width, mdp_rot_item->input.height, mdp_rot_item->input.format,
+                 mdp_rot_item->output.width, mdp_rot_item->output.height,
+                 mdp_rot_item->output.format);
+        DLOGV_IF(kTagDriverConfig, "pipe_id %d, wb_id %d, rot_flag %d", mdp_rot_item->pipe_idx,
+                 mdp_rot_item->wb_idx, mdp_rot_item->flags);
+        DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_rot_item->src_rect.x,
+                 mdp_rot_item->src_rect.y, mdp_rot_item->src_rect.w, mdp_rot_item->src_rect.h);
+        DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_rot_item->dst_rect.x,
+                 mdp_rot_item->dst_rect.y, mdp_rot_item->dst_rect.w, mdp_rot_item->dst_rect.h);
+        DLOGV_IF(kTagDriverConfig, "*************************************************************");
+      }
+    }
+  }
+
+  mdp_rot_request->flags = MDSS_ROTATION_REQUEST_VALIDATE;
+  if (ioctl_(hw_context->device_fd, MDSS_ROTATION_REQUEST, mdp_rot_request) < 0) {
+    IOCTL_LOGE(MDSS_ROTATION_REQUEST, hw_context->type);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWFrameBuffer::RotatorCommit(HWContext *hw_context, HWLayers *hw_layers) {
+  HWRotator *hw_rotator = &hw_context->hw_rotator;
+  mdp_rotation_request *mdp_rot_request = &hw_rotator->mdp_rot_req;
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  uint32_t rot_count = 0;
+
+  DLOGV_IF(kTagDriverConfig, "************************* %s Commit Input **************************",
+           GetDeviceString(hw_context->type));
+  DLOGV_IF(kTagDriverConfig, "Rotate layer count is %d", mdp_rot_request->count);
+
+  mdp_rot_request->list = hw_rotator->mdp_rot_layers;
+
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+      if (rotate_info->valid) {
+        HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+        mdp_rotation_item *mdp_rot_item = &mdp_rot_request->list[rot_count];
+
+        mdp_rot_item->input.planes[0].fd = layer.input_buffer->planes[0].fd;
+        mdp_rot_item->input.planes[0].offset = layer.input_buffer->planes[0].offset;
+        SetStride(hw_context->type, layer.input_buffer->format, layer.input_buffer->width,
+                  &mdp_rot_item->input.planes[0].stride);
+        mdp_rot_item->input.plane_count = 1;
+        mdp_rot_item->input.fence = layer.input_buffer->acquire_fence_fd;
+
+        mdp_rot_item->output.planes[0].fd = rot_buf_info->output_buffer.planes[0].fd;
+        mdp_rot_item->output.planes[0].offset = rot_buf_info->output_buffer.planes[0].offset;
+        SetStride(hw_context->type, rot_buf_info->output_buffer.format,
+                  rot_buf_info->output_buffer.planes[0].stride,
+                  &mdp_rot_item->output.planes[0].stride);
+        mdp_rot_item->output.plane_count = 1;
+        mdp_rot_item->output.fence = -1;
+
+        rot_count++;
+
+        DLOGV_IF(kTagDriverConfig, "******************** Layer[%d] %s rotate ********************",
+                 i, count ? "Right" : "Left");
+        DLOGV_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_stride %d, " \
+                 "in_plane_count %d, in_fence %d", mdp_rot_item->input.planes[0].fd,
+                 mdp_rot_item->input.planes[0].offset, mdp_rot_item->input.planes[0].stride,
+                 mdp_rot_item->input.plane_count, mdp_rot_item->input.fence);
+        DLOGV_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, out_plane_count %d, " \
+                 "out_fence %d", mdp_rot_item->output.planes[0].fd,
+                 mdp_rot_item->output.planes[0].offset, mdp_rot_item->output.planes[0].stride,
+                 mdp_rot_item->output.plane_count, mdp_rot_item->output.fence);
+        DLOGV_IF(kTagDriverConfig, "*************************************************************");
+      }
+    }
+  }
+
+  mdp_rot_request->flags &= ~MDSS_ROTATION_REQUEST_VALIDATE;
+  if (ioctl_(hw_context->device_fd, MDSS_ROTATION_REQUEST, mdp_rot_request) < 0) {
+    IOCTL_LOGE(MDSS_ROTATION_REQUEST, hw_context->type);
+    return kErrorHardware;
+  }
+
+  rot_count = 0;
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
+
+    layer.input_buffer->release_fence_fd = -1;
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWRotateInfo *rotate_info = &hw_layers->config[i].rotates[count];
+
+      if (rotate_info->valid) {
+        HWBufferInfo *rot_buf_info = &rotate_info->hw_buffer_info;
+        mdp_rotation_item *mdp_rot_item = &mdp_rot_request->list[rot_count];
+
+        SyncMerge(layer.input_buffer->release_fence_fd, dup(mdp_rot_item->output.fence),
+                  &layer.input_buffer->release_fence_fd);
+
+        rot_buf_info->output_buffer.acquire_fence_fd = dup(mdp_rot_item->output.fence);
+
+        close_(mdp_rot_item->output.fence);
+        rot_count++;
+      }
+    }
+  }
 
   return kErrorNone;
 }
 
 DisplayError HWFrameBuffer::Flush(Handle device) {
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+  HWDisplay *hw_display = &hw_context->hw_display;
 
-  hw_context->ResetMDPCommit();
-  mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
+  hw_display->Reset();
+  mdp_layer_commit_v1 &mdp_commit = hw_display->mdp_disp_commit.commit_v1;
   mdp_commit.input_layer_cnt = 0;
   mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
 
-  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_display->mdp_disp_commit) == -1) {
     IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
     return kErrorHardware;
   }
@@ -670,6 +1097,47 @@
   return kErrorNone;
 }
 
+DisplayError HWFrameBuffer::SetStride(HWDeviceType device_type, LayerBufferFormat format,
+                                      uint32_t width, uint32_t *target) {
+  // TODO(user): This SetStride function is an workaround to satisfy the driver expectation for
+  // rotator and virtual devices. Eventually this will be taken care in the driver.
+  if (device_type != kDeviceRotator && device_type != kDeviceVirtual) {
+    *target = width;
+    return kErrorNone;
+  }
+
+  switch (format) {
+  case kFormatARGB8888:
+  case kFormatRGBA8888:
+  case kFormatBGRA8888:
+  case kFormatRGBX8888:
+  case kFormatBGRX8888:
+    *target = width * 4;
+    break;
+  case kFormatRGB888:
+    *target = width * 3;
+    break;
+  case kFormatRGB565:
+    *target = width * 3;
+    break;
+  case kFormatYCbCr420SemiPlanarVenus:
+  case kFormatYCbCr420Planar:
+  case kFormatYCrCb420Planar:
+  case kFormatYCbCr420SemiPlanar:
+  case kFormatYCrCb420SemiPlanar:
+    *target = width;
+    break;
+  case kFormatYCbCr422Packed:
+    *target = width * 2;
+    break;
+  default:
+    DLOGE("Unsupported format type %d", format);
+    return kErrorParameters;
+  }
+
+  return kErrorNone;
+}
+
 void HWFrameBuffer::SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target) {
   switch (source) {
   case kBlendingPremultiplied:  *target = BLEND_OP_PREMULTIPLIED;   break;
@@ -685,6 +1153,31 @@
   target->h = UINT32(source.bottom) - target->y;
 }
 
+void HWFrameBuffer::SyncMerge(const int &fd1, const int &fd2, int *target) {
+  if (fd1 >= 0 && fd2 >= 0) {
+    buffer_sync_handler_->SyncMerge(fd1, fd2, target);
+  } else if (fd1 >= 0) {
+    *target = fd1;
+  } else if (fd2 >= 0) {
+    *target = fd2;
+  }
+}
+
+const char *HWFrameBuffer::GetDeviceString(HWDeviceType type) {
+  switch (type) {
+  case kDevicePrimary:
+    return "Primary Display Device";
+  case kDeviceHDMI:
+    return "HDMI Display Device";
+  case kDeviceVirtual:
+    return "Virtual Display Device";
+  case kDeviceRotator:
+    return "Rotator Device";
+  default:
+    return "Invalid Device";
+  }
+}
+
 void* HWFrameBuffer::DisplayEventThread(void *context) {
   if (context) {
     return reinterpret_cast<HWFrameBuffer *>(context)->DisplayEventThreadHandler();
@@ -718,7 +1211,7 @@
     pthread_exit(0);
   }
 
-  typedef void (HWFrameBuffer::*EventHandler)(int, char *);
+  typedef void (HWFrameBuffer::*EventHandler)(int, char*);
   EventHandler event_handler[kNumDisplayEvents] = { &HWFrameBuffer::HandleVSync,
                                                     &HWFrameBuffer::HandleBlank,
                                                     &HWFrameBuffer::HandleIdleTimeout };
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index 54f44a1..6df705d 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -30,7 +30,7 @@
 #include <stdlib.h>
 #include <linux/msm_mdp_ext.h>
 #include <video/msm_hdmi_modes.h>
-
+#include <linux/mdss_rotator.h>
 #include <poll.h>
 #include <pthread.h>
 
@@ -40,7 +40,7 @@
 
 class HWFrameBuffer : public HWInterface {
  public:
-  HWFrameBuffer();
+  explicit HWFrameBuffer(BufferSyncHandler *buffer_sync_handler);
   DisplayError Init();
   DisplayError Deinit();
   virtual DisplayError GetHWCapabilities(HWResourceInfo *hw_res_info);
@@ -56,28 +56,64 @@
   virtual DisplayError Doze(Handle device);
   virtual DisplayError SetVSyncState(Handle device, bool enable);
   virtual DisplayError Standby(Handle device);
+  virtual DisplayError OpenRotatorSession(Handle device, HWLayers *hw_layers);
+  virtual DisplayError CloseRotatorSession(Handle device, int32_t session_id);
   virtual DisplayError Validate(Handle device, HWLayers *hw_layers);
   virtual DisplayError Commit(Handle device, HWLayers *hw_layers);
   virtual DisplayError Flush(Handle device);
   virtual void SetIdleTimeoutMs(Handle device, uint32_t timeout_ms);
 
  private:
+  struct HWDisplay {
+    mdp_layer_commit mdp_disp_commit;
+    mdp_input_layer mdp_in_layers[kMaxSDELayers * 2];   // split panel (left + right)
+    mdp_output_layer mdp_out_layer;
+
+    HWDisplay() { Reset(); }
+
+    void Reset() {
+      memset(&mdp_disp_commit, 0, sizeof(mdp_disp_commit));
+      memset(&mdp_in_layers, 0, sizeof(mdp_in_layers));
+      memset(&mdp_out_layer, 0, sizeof(mdp_out_layer));
+
+      for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
+        mdp_in_layers[i].buffer.fence = -1;
+      }
+
+      mdp_disp_commit.version = MDP_COMMIT_VERSION_1_0;
+      mdp_disp_commit.commit_v1.input_layers = mdp_in_layers;
+      mdp_disp_commit.commit_v1.output_layer = &mdp_out_layer;
+      mdp_disp_commit.commit_v1.release_fence = -1;
+    }
+  };
+
+  struct HWRotator {
+    struct mdp_rotation_request mdp_rot_req;
+    struct mdp_rotation_item mdp_rot_layers[kMaxSDELayers * 2];  // split panel (left + right)
+
+    HWRotator() { Reset(); }
+
+    void Reset() {
+      memset(&mdp_rot_req, 0, sizeof(mdp_rot_req));
+      memset(&mdp_rot_layers, 0, sizeof(mdp_rot_layers));
+
+      for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
+        mdp_rot_layers[i].input.fence = -1;
+        mdp_rot_layers[i].output.fence = -1;
+      }
+
+      mdp_rot_req.version = MDP_ROTATION_REQUEST_VERSION_1_0;
+      mdp_rot_req.list = mdp_rot_layers;
+    }
+  };
+
   struct HWContext {
     HWDeviceType type;
     int device_fd;
-    mdp_layer_commit mdp_commit;
-    mdp_input_layer mdp_layers[kMaxSDELayers * 2];   // split panel (left + right) for worst case
+    HWRotator hw_rotator;
+    HWDisplay hw_display;
 
-    HWContext() : type(kDeviceMax), device_fd(-1) {
-      ResetMDPCommit();
-    }
-
-    void ResetMDPCommit() {
-      memset(&mdp_commit, 0, sizeof(mdp_commit));
-      memset(&mdp_layers, 0, sizeof(mdp_layers));
-      mdp_commit.version = MDP_COMMIT_VERSION_1_0;
-      mdp_commit.commit_v1.input_layers = mdp_layers;
-    }
+    HWContext() : type(kDeviceMax), device_fd(-1) { }
   };
 
   enum PanelType {
@@ -120,9 +156,20 @@
   static const int kNumDisplayEvents = 3;
   static const int kHWMdssVersion5 = 500;  // MDSS_V5
 
+  DisplayError DisplayValidate(HWContext *device_ctx, HWLayers *hw_layers);
+  DisplayError DisplayCommit(HWContext *device_ctx, HWLayers *hw_layers);
+
+  DisplayError RotatorValidate(HWContext *device_ctx, HWLayers *hw_layers);
+  DisplayError RotatorCommit(HWContext *device_ctx, HWLayers *hw_layers);
+
   inline DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
+  inline DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format,
+                                uint32_t width, uint32_t *target);
   inline void SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target);
   inline void SetRect(const LayerRect &source, mdp_rect *target);
+  inline void SyncMerge(const int &fd1, const int &fd2, int *target);
+
+  inline const char *GetDeviceString(HWDeviceType type);
 
   // Event Thread to receive vsync/blank events
   static void* DisplayEventThread(void *context);
@@ -172,6 +219,7 @@
   uint32_t hdmi_modes_[256];
   // Holds the hdmi timing information. Ex: resolution, fps etc.,
   msm_hdmi_mode_timing_info *supported_video_modes_;
+  BufferSyncHandler *buffer_sync_handler_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/hw_interface.cpp b/displayengine/libs/core/hw_interface.cpp
old mode 100755
new mode 100644
index 3ab0c7e..6b99a73
--- a/displayengine/libs/core/hw_interface.cpp
+++ b/displayengine/libs/core/hw_interface.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -29,11 +29,11 @@
 
 namespace sde {
 
-DisplayError HWInterface::Create(HWInterface **intf) {
+DisplayError HWInterface::Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler) {
   DisplayError error = kErrorNone;
   HWFrameBuffer *hw_frame_buffer = NULL;
 
-  hw_frame_buffer = new HWFrameBuffer();
+  hw_frame_buffer = new HWFrameBuffer(buffer_sync_handler);
   error = hw_frame_buffer->Init();
   if (UNLIKELY(error != kErrorNone)) {
     delete hw_frame_buffer;
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index 6e87edd..1217b95 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -28,6 +28,8 @@
 #include <core/display_interface.h>
 #include <private/strategy_interface.h>
 #include <utils/constants.h>
+#include <core/buffer_allocator.h>
+#include <core/buffer_sync_handler.h>
 
 namespace sde {
 
@@ -44,7 +46,8 @@
   kDevicePrimary,
   kDeviceHDMI,
   kDeviceVirtual,
-  kDeviceMax
+  kDeviceRotator,
+  kDeviceMax,
 };
 
 struct HWResourceInfo {
@@ -90,48 +93,68 @@
       max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false),
       has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
       has_non_scalar_rgb(false), is_src_split(false), always_src_split(false) { }
+
+  void Reset() { *this = HWResourceInfo(); }
+};
+
+struct HWBufferInfo : public BufferInfo {
+  LayerBuffer output_buffer;
+  int session_id;
+  uint32_t slot;
+
+  HWBufferInfo() : session_id(-1), slot(0) { }
 };
 
 struct HWRotateInfo {
-  int pipe_id;
+  uint32_t pipe_id;
   LayerRect src_roi;
   LayerRect dst_roi;
+  LayerBufferFormat dst_format;
   HWBlockType writeback_id;
   float downscale_ratio_x;
   float downscale_ratio_y;
+  HWBufferInfo hw_buffer_info;
+  bool valid;
 
-  HWRotateInfo() : pipe_id(0), writeback_id(kHWWriteback0), downscale_ratio_x(1.0f),
-      downscale_ratio_y(1.0f) { }
+  HWRotateInfo() : pipe_id(0), dst_format(kFormatInvalid), writeback_id(kHWWriteback0),
+                   downscale_ratio_x(1.0f), downscale_ratio_y(1.0f), valid(false) { }
 
-  inline void Reset() { *this = HWRotateInfo(); }
+  void Reset() { *this = HWRotateInfo(); }
 };
 
 struct HWPipeInfo {
-  int pipe_id;
+  uint32_t pipe_id;
   LayerRect src_roi;
   LayerRect dst_roi;
   uint8_t horizontal_decimation;
   uint8_t vertical_decimation;
+  bool valid;
 
-  HWPipeInfo() : pipe_id(0), horizontal_decimation(0), vertical_decimation(0) { }
+  HWPipeInfo() : pipe_id(0), horizontal_decimation(0), vertical_decimation(0), valid(false) { }
 
-  inline void Reset() { *this = HWPipeInfo(); }
+  void Reset() { *this = HWPipeInfo(); }
 };
 
 struct HWLayerConfig {
   bool use_non_dma_pipe;  // set by client
-  bool is_right_pipe;  // indicate if right pipe is valid
   HWPipeInfo left_pipe;  // pipe for left side of the buffer
   HWPipeInfo right_pipe;  // pipe for right side of the buffer
   uint32_t num_rotate;  // number of rotate
   HWRotateInfo rotates[kMaxRotatePerLayer];  // rotation for the buffer
 
-  HWLayerConfig() : use_non_dma_pipe(false), is_right_pipe(false), num_rotate(0) { }
+  HWLayerConfig() : use_non_dma_pipe(false), num_rotate(0) { }
+
+  void Reset() { *this = HWLayerConfig(); }
 };
 
 struct HWLayers {
   HWLayersInfo info;
   HWLayerConfig config[kMaxSDELayers];
+  int closed_session_ids[kMaxSDELayers * 2];  // split panel (left + right)
+
+  HWLayers() { memset(closed_session_ids, -1, sizeof(closed_session_ids)); }
+
+  void Reset() { *this = HWLayers(); }
 };
 
 struct HWDisplayAttributes : DisplayConfigVariableInfo {
@@ -139,6 +162,8 @@
   uint32_t split_left;
 
   HWDisplayAttributes() : is_device_split(false), split_left(0) { }
+
+  void Reset() { *this = HWDisplayAttributes(); }
 };
 
 // HWEventHandler - Implemented in DisplayBase and HWInterface implementation
@@ -148,12 +173,12 @@
   virtual DisplayError Blank(bool blank) = 0;
   virtual void IdleTimeout() = 0;
  protected:
-  virtual ~HWEventHandler() {}
+  virtual ~HWEventHandler() { }
 };
 
 class HWInterface {
  public:
-  static DisplayError Create(HWInterface **intf);
+  static DisplayError Create(HWInterface **intf, BufferSyncHandler *buffer_sync_handler);
   static DisplayError Destroy(HWInterface *intf);
   virtual DisplayError GetHWCapabilities(HWResourceInfo *hw_res_info) = 0;
   virtual DisplayError Open(HWDeviceType type, Handle *device, HWEventHandler *eventhandler) = 0;
@@ -168,6 +193,8 @@
   virtual DisplayError Doze(Handle device) = 0;
   virtual DisplayError SetVSyncState(Handle device, bool enable) = 0;
   virtual DisplayError Standby(Handle device) = 0;
+  virtual DisplayError OpenRotatorSession(Handle device, HWLayers *hw_layers) = 0;
+  virtual DisplayError CloseRotatorSession(Handle device, int32_t session_id) = 0;
   virtual DisplayError Validate(Handle device, HWLayers *hw_layers) = 0;
   virtual DisplayError Commit(Handle device, HWLayers *hw_layers) = 0;
   virtual DisplayError Flush(Handle device) = 0;
diff --git a/displayengine/libs/core/offline_ctrl.cpp b/displayengine/libs/core/offline_ctrl.cpp
old mode 100755
new mode 100644
index c380d52..5ffaf22
--- a/displayengine/libs/core/offline_ctrl.cpp
+++ b/displayengine/libs/core/offline_ctrl.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -31,17 +31,131 @@
 
 namespace sde {
 
-OfflineCtrl::OfflineCtrl() : hw_intf_(NULL) {
+// TODO(user): Move this offline controller under composition manager like other modules
+// [resource manager]. Implement session management and buffer management in offline controller.
+OfflineCtrl::OfflineCtrl() : hw_intf_(NULL), hw_rotator_device_(NULL) {
 }
 
 DisplayError OfflineCtrl::Init(HWInterface *hw_intf, HWResourceInfo hw_res_info) {
   hw_intf_ = hw_intf;
+  DisplayError error = kErrorNone;
+
+  error = hw_intf_->Open(kDeviceRotator, &hw_rotator_device_, NULL);
+  if (error != kErrorNone) {
+    DLOGW("Failed to open rotator device");
+  }
+
   return kErrorNone;
 }
 
 DisplayError OfflineCtrl::Deinit() {
+  DisplayError error = kErrorNone;
+
+  error = hw_intf_->Close(hw_rotator_device_);
+  if (error != kErrorNone) {
+    DLOGW("Failed to close rotator device");
+    return error;
+  }
+
   return kErrorNone;
 }
 
+DisplayError OfflineCtrl::RegisterDisplay(DisplayType type, Handle *display_ctx) {
+  DisplayOfflineContext *disp_offline_ctx = new DisplayOfflineContext();
+  if (disp_offline_ctx == NULL) {
+    return kErrorMemory;
+  }
+
+  disp_offline_ctx->display_type = type;
+  *display_ctx = disp_offline_ctx;
+
+  return kErrorNone;
+}
+
+void OfflineCtrl::UnregisterDisplay(Handle display_ctx) {
+  DisplayOfflineContext *disp_offline_ctx = reinterpret_cast<DisplayOfflineContext *>(display_ctx);
+
+  delete disp_offline_ctx;
+  disp_offline_ctx = NULL;
+}
+
+
+DisplayError OfflineCtrl::Prepare(Handle display_ctx, HWLayers *hw_layers) {
+  DisplayError error = kErrorNone;
+
+  DisplayOfflineContext *disp_offline_ctx = reinterpret_cast<DisplayOfflineContext *>(display_ctx);
+
+  if (!hw_rotator_device_ && IsRotationRequired(hw_layers)) {
+    DLOGV_IF(kTagOfflineCtrl, "No Rotator device found");
+    return kErrorHardware;
+  }
+
+  disp_offline_ctx->pending_rot_commit = false;
+
+  uint32_t i = 0;
+  while (hw_layers->closed_session_ids[i] >= 0) {
+    error = hw_intf_->CloseRotatorSession(hw_rotator_device_, hw_layers->closed_session_ids[i]);
+    if (LIKELY(error != kErrorNone)) {
+      DLOGE("Rotator close session failed");
+      return error;
+    }
+    hw_layers->closed_session_ids[i++] = -1;
+  }
+
+
+  if (IsRotationRequired(hw_layers)) {
+    error = hw_intf_->OpenRotatorSession(hw_rotator_device_, hw_layers);
+    if (LIKELY(error != kErrorNone)) {
+      DLOGE("Rotator open session failed");
+      return error;
+    }
+
+    error = hw_intf_->Validate(hw_rotator_device_, hw_layers);
+    if (LIKELY(error != kErrorNone)) {
+      DLOGE("Rotator validation failed");
+      return error;
+    }
+    disp_offline_ctx->pending_rot_commit = true;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError OfflineCtrl::Commit(Handle display_ctx, HWLayers *hw_layers) {
+  DisplayError error = kErrorNone;
+
+  DisplayOfflineContext *disp_offline_ctx = reinterpret_cast<DisplayOfflineContext *>(display_ctx);
+
+  if (disp_offline_ctx->pending_rot_commit) {
+    error = hw_intf_->Commit(hw_rotator_device_, hw_layers);
+    if (error != kErrorNone) {
+      DLOGE("Rotator commit failed");
+      return error;
+    }
+    disp_offline_ctx->pending_rot_commit = false;
+  }
+
+  return kErrorNone;
+}
+
+bool OfflineCtrl::IsRotationRequired(HWLayers *hw_layers) {
+  HWLayersInfo &layer_info = hw_layers->info;
+
+  for (uint32_t i = 0; i < layer_info.count; i++) {
+    Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+
+    HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+    if (rotate->valid) {
+      return true;
+    }
+
+    rotate = &hw_layers->config[i].rotates[1];
+    if (rotate->valid) {
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/offline_ctrl.h b/displayengine/libs/core/offline_ctrl.h
index 8987bb3..fafdf7c 100644
--- a/displayengine/libs/core/offline_ctrl.h
+++ b/displayengine/libs/core/offline_ctrl.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -26,6 +26,7 @@
 #define __OFFLINE_CTRL_H__
 
 #include <utils/locker.h>
+#include <utils/debug.h>
 
 #include "hw_interface.h"
 
@@ -36,9 +37,23 @@
   OfflineCtrl();
   DisplayError Init(HWInterface *hw_intf, HWResourceInfo hw_res_info);
   DisplayError Deinit();
+  DisplayError RegisterDisplay(DisplayType type, Handle *display_ctx);
+  void UnregisterDisplay(Handle display_ctx);
+  DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError Commit(Handle display_ctx, HWLayers *hw_layers);
 
  private:
+  struct DisplayOfflineContext {
+    DisplayType display_type;
+    bool pending_rot_commit;
+
+    DisplayOfflineContext() : display_type(kPrimary), pending_rot_commit(false) { }
+  };
+
+  bool IsRotationRequired(HWLayers *hw_layers);
+
   HWInterface *hw_intf_;
+  Handle hw_rotator_device_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index 0c8859f..cf2a5c7 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -58,7 +58,7 @@
   dst_rect.right = floorf(dst_rect.right);
   dst_rect.bottom = floorf(dst_rect.bottom);
   rotate->src_roi = *src_rect;
-  rotate->pipe_id = kPipeIdNeedsAssignment;
+  rotate->valid = true;
   rotate->dst_roi = dst_rect;
 
   *src_rect = dst_rect;
@@ -72,21 +72,20 @@
   HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
   HWPipeInfo *left_pipe = &layer_config->left_pipe;
   HWPipeInfo *right_pipe = &layer_config->right_pipe;
-  layer_config->is_right_pipe = false;
 
   if ((src_rect.right - src_rect.left) > kMaxSourcePipeWidth ||
       (dst_rect.right - dst_rect.left) > kMaxInterfaceWidth || hw_res_info_.always_src_split) {
     SplitRect(transform.flip_horizontal, src_rect, dst_rect, &left_pipe->src_roi,
               &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
-    left_pipe->pipe_id = kPipeIdNeedsAssignment;
-    right_pipe->pipe_id = kPipeIdNeedsAssignment;
-    layer_config->is_right_pipe = true;
+    left_pipe->valid = true;
+    right_pipe->valid = true;
   } else {
     left_pipe->src_roi = src_rect;
     left_pipe->dst_roi = dst_rect;
-    left_pipe->pipe_id = kPipeIdNeedsAssignment;
+    left_pipe->valid = true;
     right_pipe->Reset();
   }
+
   return kErrorNone;
 }
 
@@ -94,12 +93,13 @@
                                             const LayerTransform &transform,
                                             const LayerRect &src_rect, const LayerRect &dst_rect,
                                             HWLayerConfig *layer_config) {
+  LayerRect scissor_dst_left, scissor_dst_right;
   HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
+
   // for display split case
   HWPipeInfo *left_pipe = &layer_config->left_pipe;
   HWPipeInfo *right_pipe = &layer_config->right_pipe;
   LayerRect scissor, dst_left, crop_left, crop_right, dst_right;
-  layer_config->is_right_pipe = false;
   scissor.right = FLOAT(display_attributes.split_left);
   scissor.bottom = FLOAT(display_attributes.y_pixels);
 
@@ -123,9 +123,8 @@
     // 2 pipes both are on the left
     SplitRect(transform.flip_horizontal, crop_left, dst_left, &left_pipe->src_roi,
               &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
-    left_pipe->pipe_id = kPipeIdNeedsAssignment;
-    right_pipe->pipe_id = kPipeIdNeedsAssignment;
-    layer_config->is_right_pipe = true;
+    left_pipe->valid = true;
+    right_pipe->valid = true;
   } else if ((crop_right.right - crop_right.left) > kMaxSourcePipeWidth) {
     if (crop_left.right != crop_left.left) {
       DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
@@ -135,14 +134,13 @@
     // 2 pipes both are on the right
     SplitRect(transform.flip_horizontal, crop_right, dst_right, &left_pipe->src_roi,
               &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
-    left_pipe->pipe_id = kPipeIdNeedsAssignment;
-    right_pipe->pipe_id = kPipeIdNeedsAssignment;
-    layer_config->is_right_pipe = true;
+    left_pipe->valid = true;
+    right_pipe->valid = true;
   } else if (UINT32(dst_left.right) > UINT32(dst_left.left)) {
     // assign left pipe
     left_pipe->src_roi = crop_left;
     left_pipe->dst_roi = dst_left;
-    left_pipe->pipe_id = kPipeIdNeedsAssignment;
+    left_pipe->valid = true;
   } else {
     // Set default value, left_pipe is not needed.
     left_pipe->Reset();
@@ -150,16 +148,15 @@
 
   // assign right pipe if needed
   if (UINT32(dst_right.right) > UINT32(dst_right.left)) {
-    if (left_pipe->pipe_id) {
+    if (left_pipe->valid) {
       right_pipe->src_roi = crop_right;
       right_pipe->dst_roi = dst_right;
-      right_pipe->pipe_id = kPipeIdNeedsAssignment;
-      layer_config->is_right_pipe = true;
+      right_pipe->valid = true;
     } else {
       // If left pipe is not used, use left pipe first.
       left_pipe->src_roi = crop_right;
       left_pipe->dst_roi = dst_right;
-      left_pipe->pipe_id = kPipeIdNeedsAssignment;
+      left_pipe->valid = true;
       right_pipe->Reset();
     }
   } else {
@@ -230,12 +227,12 @@
     //    rectangle of video layer to be even.
     // 2. Normalize source and destination rect of a layer to multiple of 1.
     uint32_t factor = (1 << layer.input_buffer->flags.video);
-    if (left_pipe.pipe_id == kPipeIdNeedsAssignment) {
+    if (left_pipe.valid) {
       NormalizeRect(factor, &left_pipe.src_roi);
       NormalizeRect(1, &left_pipe.dst_roi);
     }
 
-    if (right_pipe.pipe_id == kPipeIdNeedsAssignment) {
+    if (right_pipe.valid) {
       NormalizeRect(factor, &right_pipe.src_roi);
       NormalizeRect(1, &right_pipe.dst_roi);
     }
@@ -421,6 +418,7 @@
     return;
 
   CalculateCut(transform, &left_cut_ratio, &top_cut_ratio, &right_cut_ratio, &bottom_cut_ratio);
+
   crop_left += crop_width * left_cut_ratio;
   crop_top += crop_height * top_cut_ratio;
   crop_right -= crop_width * right_cut_ratio;
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index e3fbdda..16fc8b4 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -33,12 +33,23 @@
 namespace sde {
 
 ResManager::ResManager()
-  : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL), virtual_count_(0) {
+  : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL), virtual_count_(0),
+    buffer_allocator_(NULL), buffer_sync_handler_(NULL) {
 }
 
-DisplayError ResManager::Init(const HWResourceInfo &hw_res_info) {
+DisplayError ResManager::Init(const HWResourceInfo &hw_res_info, BufferAllocator *buffer_allocator,
+                              BufferSyncHandler *buffer_sync_handler) {
   hw_res_info_ = hw_res_info;
 
+  buffer_sync_handler_ = buffer_sync_handler;
+
+  if (!hw_res_info_.max_mixer_width)
+    hw_res_info_.max_mixer_width = kMaxSourcePipeWidth;
+
+  buffer_allocator_ = buffer_allocator;
+
+  buffer_sync_handler_ = buffer_sync_handler;
+
   DisplayError error = kErrorNone;
 
   // TODO(user): Remove this. Disable src_split as kernel not supported yet
@@ -80,6 +91,9 @@
   DLOGI("hw_rev=%x, DMA=%d RGB=%d VIG=%d", hw_res_info_.hw_revision, hw_res_info_.num_dma_pipe,
     hw_res_info_.num_rgb_pipe, hw_res_info_.num_vig_pipe);
 
+  // TODO(user): Need to get it from HW capability
+  hw_res_info_.num_rotator = 2;
+
   if (hw_res_info_.num_rotator > kMaxNumRotator) {
     DLOGE("Number of rotator is over the limit! %d", hw_res_info_.num_rotator);
     return kErrorParameters;
@@ -143,6 +157,13 @@
     return kErrorMemory;
   }
 
+  display_resource_ctx->buffer_manager = new BufferManager(buffer_allocator_, buffer_sync_handler_);
+  if (display_resource_ctx->buffer_manager == NULL) {
+    delete display_resource_ctx;
+    display_resource_ctx = NULL;
+    return kErrorMemory;
+  }
+
   hw_block_ctx_[hw_block_id].is_in_use = true;
 
   display_resource_ctx->display_attributes = attributes;
@@ -254,8 +275,9 @@
 
   // allocate rotator
   error = AcquireRotator(display_resource_ctx, rotate_count);
-  if (error != kErrorNone)
+  if (error != kErrorNone) {
     return error;
+  }
 
   rotate_count = 0;
   for (uint32_t i = 0; i < layer_info.count; i++) {
@@ -278,7 +300,7 @@
     bool is_yuv = IsYuvFormat(layer.input_buffer->format);
 
     // left pipe is needed
-    if (pipe_info->pipe_id) {
+    if (pipe_info->valid) {
       need_scale = IsScalingNeeded(pipe_info);
       left_index = GetPipe(hw_block_id, is_yuv, need_scale, false, use_non_dma_pipe);
       if (left_index >= num_pipe_) {
@@ -293,7 +315,7 @@
     }
 
     pipe_info =  &layer_config.right_pipe;
-    if (pipe_info->pipe_id == 0) {
+    if (!pipe_info->valid) {
       // assign single pipe
       if (left_index < num_pipe_) {
         layer_config.left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
@@ -336,6 +358,12 @@
     goto CleanupOnError;
   }
 
+  error = AllocRotatorBuffer(display_ctx, hw_layers);
+  if (error != kErrorNone) {
+    DLOGV_IF(kTagResources, "Rotator buffer allocation failed");
+    goto CleanupOnError;
+  }
+
   return kErrorNone;
 
 CleanupOnError:
@@ -348,6 +376,11 @@
 }
 
 bool ResManager::CheckBandwidth(DisplayResourceContext *display_ctx, HWLayers *hw_layers) {
+  // No need to check bandwidth for virtual displays
+  if (display_ctx->display_type == kVirtual) {
+    return true;
+  }
+
   float max_pipe_bw = FLOAT(hw_res_info_.max_pipe_bw) / 1000000;  // KBps to GBps
   float max_sde_clk = FLOAT(hw_res_info_.max_sde_clk) / 1000000;  // Hz to MHz
   const struct HWLayersInfo &layer_info = hw_layers->info;
@@ -360,19 +393,19 @@
   for (uint32_t i = 0; i < layer_info.count; i++) {
     Layer &layer = layer_info.stack->layers[layer_info.index[i]];
     float bpp = GetBpp(layer.input_buffer->format);
-    uint32_t left_id = hw_layers->config[i].left_pipe.pipe_id;
-    uint32_t right_id = hw_layers->config[i].right_pipe.pipe_id;
+    HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+    HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
 
-    left_pipe_bw[i] = left_id ? GetPipeBw(display_ctx, &hw_layers->config[i].left_pipe, bpp) : 0;
-    right_pipe_bw[i] = right_id ? GetPipeBw(display_ctx, &hw_layers->config[i].right_pipe, bpp) : 0;
+    left_pipe_bw[i] = left_pipe->valid ? GetPipeBw(display_ctx, left_pipe, bpp) : 0;
+    right_pipe_bw[i] = right_pipe->valid ? GetPipeBw(display_ctx, right_pipe, bpp) : 0;
 
     if ((left_pipe_bw[i] > max_pipe_bw) || (right_pipe_bw[i] > max_pipe_bw)) {
       DLOGV_IF(kTagResources, "Pipe bandwidth exceeds limit for layer index = %d", i);
       return false;
     }
 
-    float left_clk = left_id ? GetClockForPipe(display_ctx, &hw_layers->config[i].left_pipe) : 0;
-    float right_clk = right_id ? GetClockForPipe(display_ctx, &hw_layers->config[i].right_pipe) : 0;
+    float left_clk = left_pipe->valid ? GetClockForPipe(display_ctx, left_pipe) : 0;
+    float right_clk = right_pipe->valid ? GetClockForPipe(display_ctx, right_pipe) : 0;
 
     left_max_clk = MAX(left_clk, left_max_clk);
     right_max_clk = MAX(right_clk, right_max_clk);
@@ -556,12 +589,105 @@
   }
 }
 
-void ResManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+DisplayError ResManager::AllocRotatorBuffer(Handle display_ctx, HWLayers *hw_layers) {
+  DisplayResourceContext *display_resource_ctx =
+                          reinterpret_cast<DisplayResourceContext *>(display_ctx);
+  DisplayError error = kErrorNone;
+
+  BufferManager *buffer_manager = display_resource_ctx->buffer_manager;
+  HWLayersInfo &layer_info = hw_layers->info;
+
+  // TODO(user): Do session management during prepare and allocate buffer and associate that with
+  // the session during commit.
+  buffer_manager->Start();
+
+  for (uint32_t i = 0; i < layer_info.count; i++) {
+    Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+    HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+
+    if (rotate->valid) {
+      LayerBufferFormat rot_ouput_format;
+      SetRotatorOutputFormat(layer.input_buffer->format, false, true, &rot_ouput_format);
+
+      HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+      hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right - rotate->dst_roi.left);
+      hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom - rotate->dst_roi.top);
+      hw_buffer_info->buffer_config.format = rot_ouput_format;
+      hw_buffer_info->buffer_config.buffer_count = 2;
+      hw_buffer_info->buffer_config.secure = layer.input_buffer->flags.secure;
+
+      error = buffer_manager->GetNextBuffer(hw_buffer_info);
+      if (error != kErrorNone) {
+        return error;
+      }
+    }
+
+    rotate = &hw_layers->config[i].rotates[1];
+    if (rotate->valid) {
+      LayerBufferFormat rot_ouput_format;
+      SetRotatorOutputFormat(layer.input_buffer->format, false, true, &rot_ouput_format);
+
+      HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+      hw_buffer_info->buffer_config.width = UINT32(rotate->dst_roi.right - rotate->dst_roi.left);
+      hw_buffer_info->buffer_config.height = UINT32(rotate->dst_roi.bottom - rotate->dst_roi.top);
+      hw_buffer_info->buffer_config.format = rot_ouput_format;
+      hw_buffer_info->buffer_config.buffer_count = 2;
+      hw_buffer_info->buffer_config.secure = layer.input_buffer->flags.secure;
+
+      error = buffer_manager->GetNextBuffer(hw_buffer_info);
+      if (error != kErrorNone) {
+        return error;
+      }
+    }
+  }
+  buffer_manager->Stop(hw_layers->closed_session_ids);
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
+  SCOPE_LOCK(locker_);
+  DisplayResourceContext *display_resource_ctx =
+                          reinterpret_cast<DisplayResourceContext *>(display_ctx);
+  DisplayError error = kErrorNone;
+
+  BufferManager *buffer_manager = display_resource_ctx->buffer_manager;
+  HWLayersInfo &layer_info = hw_layers->info;
+
+  for (uint32_t i = 0; i < layer_info.count; i++) {
+    Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+    HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+
+    if (rotate->valid) {
+      HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+
+      error = buffer_manager->SetSessionId(hw_buffer_info->slot, hw_buffer_info->session_id);
+      if (error != kErrorNone) {
+        return error;
+      }
+    }
+
+    rotate = &hw_layers->config[i].rotates[1];
+    if (rotate->valid) {
+      HWBufferInfo *hw_buffer_info = &rotate->hw_buffer_info;
+
+      error = buffer_manager->SetSessionId(hw_buffer_info->slot, hw_buffer_info->session_id);
+      if (error != kErrorNone) {
+        return error;
+      }
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
   SCOPE_LOCK(locker_);
   DisplayResourceContext *display_resource_ctx =
                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
   HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
   uint64_t frame_count = display_resource_ctx->frame_count;
+  DisplayError error = kErrorNone;
 
   DLOGV_IF(kTagResources, "Resource for hw_block = %d, frame_count = %d", hw_block_id, frame_count);
 
@@ -609,6 +735,37 @@
     }
   }
   display_resource_ctx->frame_start = false;
+
+  BufferManager *buffer_manager = display_resource_ctx->buffer_manager;
+  HWLayersInfo &layer_info = hw_layers->info;
+
+  for (uint32_t i = 0; i < layer_info.count; i++) {
+    Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+    HWRotateInfo *rotate = &hw_layers->config[i].rotates[0];
+
+    if (rotate->valid) {
+      HWBufferInfo *rot_buf_info = &rotate->hw_buffer_info;
+
+      error = buffer_manager->SetReleaseFd(rot_buf_info->slot,
+                                                rot_buf_info->output_buffer.release_fence_fd);
+      if (error != kErrorNone) {
+        return error;
+      }
+    }
+
+    rotate = &hw_layers->config[i].rotates[1];
+    if (rotate->valid) {
+      HWBufferInfo *rot_buf_info = &rotate->hw_buffer_info;
+
+      error = buffer_manager->SetReleaseFd(rot_buf_info->slot,
+                                                rot_buf_info->output_buffer.release_fence_fd);
+      if (error != kErrorNone) {
+        return error;
+      }
+    }
+  }
+
+  return kErrorNone;
 }
 
 void ResManager::Purge(Handle display_ctx) {
@@ -798,8 +955,10 @@
                                         const uint32_t rotate_count) {
   if (rotate_count == 0)
     return kErrorNone;
-  if (hw_res_info_.num_rotator == 0)
+  if (hw_res_info_.num_rotator == 0) {
+    DLOGV_IF(kTagResources, "Rotator hardware is not available");
     return kErrorResources;
+  }
 
   uint32_t i, j, pipe_index, num_rotator;
   if (rotate_count > hw_res_info_.num_rotator)
@@ -840,7 +999,7 @@
 }
 
 void ResManager::AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_count) {
-  if (!rotate->pipe_id)
+  if (!rotate->valid)
     return;
   // Interleave rotator assignment
   if ((*rotate_count & 0x1) && (hw_res_info_.num_rotator > 1)) {
@@ -869,5 +1028,43 @@
   }
 }
 
+void ResManager::SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
+                                        LayerBufferFormat *output_format) {
+  switch (input_format) {
+  case kFormatRGB565:
+    if (rot90)
+      *output_format = kFormatRGB888;
+    else
+      *output_format = input_format;
+    break;
+  case kFormatRGBA8888:
+    if (bwc)
+      *output_format = kFormatBGRA8888;
+    else
+      *output_format = input_format;
+    break;
+  case kFormatYCbCr420SemiPlanarVenus:
+  case kFormatYCbCr420SemiPlanar:
+    if (rot90)
+      *output_format = kFormatYCrCb420SemiPlanar;
+    else
+      *output_format = input_format;
+    break;
+  case kFormatYCbCr420Planar:
+  case kFormatYCrCb420Planar:
+    *output_format = kFormatYCrCb420SemiPlanar;
+    break;
+  default:
+    *output_format = input_format;
+    break;
+  }
+
+  DLOGV_IF(kTagResources, "Input format %x, Output format = %x, rot90 %d", input_format,
+           *output_format, rot90);
+
+  return;
+}
+
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index 1f65c50..926b2b7 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -30,13 +30,15 @@
 
 #include "hw_interface.h"
 #include "dump_impl.h"
+#include "buffer_manager.h"
 
 namespace sde {
 
 class ResManager : public DumpImpl {
  public:
   ResManager();
-  DisplayError Init(const HWResourceInfo &hw_res_info);
+  DisplayError Init(const HWResourceInfo &hw_res_info, BufferAllocator *buffer_allocator,
+                    BufferSyncHandler *buffer_sync_handler);
   DisplayError Deinit();
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
                                Handle *display_ctx);
@@ -44,7 +46,8 @@
   DisplayError Start(Handle display_ctx);
   DisplayError Stop(Handle display_ctx);
   DisplayError Acquire(Handle display_ctx, HWLayers *hw_layers);
-  void PostCommit(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
   void Purge(Handle display_ctx);
 
   // DumpImpl method
@@ -111,14 +114,23 @@
 
   struct DisplayResourceContext {
     HWDisplayAttributes display_attributes;
+    BufferManager *buffer_manager;
     DisplayType display_type;
     HWBlockType hw_block_id;
     uint64_t frame_count;
     int32_t session_id;  // applicable for virtual display sessions only
     uint32_t rotate_count;
     bool frame_start;
+
     DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0), session_id(-1),
                     rotate_count(0), frame_start(false) { }
+
+    ~DisplayResourceContext() {
+      if (buffer_manager) {
+        delete buffer_manager;
+        buffer_manager = NULL;
+      }
+    }
   };
 
   struct HWBlockContext {
@@ -184,6 +196,9 @@
   void AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_cnt);
   void ClearRotator(DisplayResourceContext *display_resource_ctx);
   void NormalizeRect(const uint32_t &factor, LayerRect *rect);
+  DisplayError AllocRotatorBuffer(Handle display_ctx, HWLayers *hw_layers);
+  void SetRotatorOutputFormat(const LayerBufferFormat &input_format, bool bwc, bool rot90,
+                              LayerBufferFormat *output_format);
 
   template <class T>
   inline void Swap(T &a, T &b) {
@@ -217,6 +232,9 @@
   float last_primary_bw_;
   uint32_t virtual_count_;
   struct HWRotator rotators_[kMaxNumRotator];
+  BufferAllocator *buffer_allocator_;
+  BufferSyncHandler *buffer_sync_handler_;  // Pointer to buffer sync handler that was defined by
+                                            // the display engine's client
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/Android.mk b/displayengine/libs/hwc/Android.mk
old mode 100755
new mode 100644
index 1271e00..d31c71e
--- a/displayengine/libs/hwc/Android.mk
+++ b/displayengine/libs/hwc/Android.mk
@@ -6,17 +6,20 @@
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := hardware/qcom/display/displayengine/include/ \
                                  hardware/qcom/display/libgralloc/ \
-                                 hardware/qcom/display/libqservice/
+                                 hardware/qcom/display/libqservice/ \
+                                 hardware/qcom/display/libqdutils/
 LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
                                  -Wconversion -Wall -Werror \
                                  -DLOG_TAG=\"SDE\"
 LOCAL_SHARED_LIBRARIES        := libsde libqservice libbinder libhardware libhardware_legacy \
-                                 libutils libcutils
+                                 libutils libcutils libsync libmemalloc libqdutils
 LOCAL_SRC_FILES               := hwc_session.cpp \
                                  hwc_display.cpp \
                                  hwc_display_primary.cpp \
                                  hwc_display_external.cpp \
                                  hwc_display_virtual.cpp \
-                                 hwc_logger.cpp
+                                 hwc_debugger.cpp \
+                                 hwc_buffer_allocator.cpp \
+                                 hwc_buffer_sync_handler.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/hwc/hwc_buffer_allocator.cpp b/displayengine/libs/hwc/hwc_buffer_allocator.cpp
new file mode 100644
index 0000000..d4f4bac
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_buffer_allocator.cpp
@@ -0,0 +1,171 @@
+/*
+* Copyright (c) 2015, 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 <gralloc_priv.h>
+#include <memalloc.h>
+#include <gr.h>
+#include <alloc_controller.h>
+#include <utils/constants.h>
+#include <core/buffer_allocator.h>
+
+#include "hwc_debugger.h"
+#include "hwc_buffer_allocator.h"
+
+#define __CLASS__ "HWCBufferAllocator"
+
+namespace sde {
+
+HWCBufferAllocator::HWCBufferAllocator() {
+  alloc_controller_ = gralloc::IAllocController::getInstance();
+}
+
+DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
+  gralloc::alloc_data data;
+
+  const BufferConfig &buffer_config = buffer_info->buffer_config;
+  AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+  MetaBufferInfo *meta_buffer_info = new MetaBufferInfo();
+
+  if (!meta_buffer_info) {
+    return kErrorMemory;
+  }
+
+  int alloc_flags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
+  int error = 0;
+
+  int width = INT(buffer_config.width);
+  int height = INT(buffer_config.height);
+  int format;
+
+  error = SetHALFormat(buffer_config.format, &format);
+  if (error != 0) {
+    return kErrorParameters;
+  }
+
+  if (buffer_config.secure) {
+    alloc_flags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
+    alloc_flags |= GRALLOC_USAGE_PROTECTED;
+    data.align = kSecureBufferAlignment;
+  } else {
+    data.align = getpagesize();
+  }
+
+  if (buffer_config.cache == false) {
+    // Allocate uncached buffers
+    alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+  }
+
+  int aligned_width = 0, aligned_height = 0;
+  uint32_t buffer_size = getBufferSizeAndDimensions(width, height, format, alloc_flags,
+                                                    aligned_width, aligned_height);
+
+  buffer_size = ROUND_UP((buffer_size * buffer_config.buffer_count), data.align);
+
+  data.base = 0;
+  data.fd = -1;
+  data.offset = 0;
+  data.size = buffer_size;
+  data.uncached = !buffer_config.cache;
+
+  error = alloc_controller_->allocate(data, alloc_flags);
+  if (error != 0) {
+    DLOGE("Error allocating memory size %d uncached %d", data.size, data.uncached);
+    return kErrorMemory;
+  }
+
+  alloc_buffer_info->fd = data.fd;
+  alloc_buffer_info->stride = aligned_width;
+  alloc_buffer_info->size = buffer_size;
+
+  meta_buffer_info->base_addr = data.base;
+  meta_buffer_info->alloc_type = data.allocType;
+
+  buffer_info->private_data = meta_buffer_info;
+
+  return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::FreeBuffer(BufferInfo *buffer_info) {
+  int ret = 0;
+
+  AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+  MetaBufferInfo *meta_buffer_info = static_cast<MetaBufferInfo *> (buffer_info->private_data);
+  if ((alloc_buffer_info->fd < 0) || (meta_buffer_info->base_addr == NULL)) {
+    return kErrorNone;
+  }
+
+  gralloc::IMemAlloc *memalloc = alloc_controller_->getAllocator(meta_buffer_info->alloc_type);
+  if (memalloc == NULL) {
+    DLOGE("Memalloc handle is NULL, alloc type %d", meta_buffer_info->alloc_type);
+    return kErrorResources;
+  }
+
+  ret = memalloc->free_buffer(meta_buffer_info->base_addr, alloc_buffer_info->size, 0,
+                              alloc_buffer_info->fd);
+  if (ret != 0) {
+    DLOGE("Error freeing buffer base_addr %p size %d fd %d", meta_buffer_info->base_addr,
+          alloc_buffer_info->size, alloc_buffer_info->fd);
+    return kErrorMemory;
+  }
+
+  alloc_buffer_info->fd = -1;
+  alloc_buffer_info->stride = 0;
+  alloc_buffer_info->size = 0;
+
+  meta_buffer_info->base_addr = NULL;
+  meta_buffer_info->alloc_type = 0;
+
+  delete meta_buffer_info;
+  meta_buffer_info = NULL;
+
+  return kErrorNone;
+}
+
+int HWCBufferAllocator::SetHALFormat(LayerBufferFormat format, int *target) {
+  switch (format) {
+  case kFormatRGBA8888:                 *target = HAL_PIXEL_FORMAT_RGBA_8888;             break;
+  case kFormatRGBX8888:                 *target = HAL_PIXEL_FORMAT_RGBX_8888;             break;
+  case kFormatRGB888:                   *target = HAL_PIXEL_FORMAT_RGB_888;               break;
+  case kFormatRGB565:                   *target = HAL_PIXEL_FORMAT_RGB_565;               break;
+  case kFormatBGRA8888:                 *target = HAL_PIXEL_FORMAT_BGRA_8888;             break;
+  case kFormatYCrCb420Planar:           *target = HAL_PIXEL_FORMAT_YV12;                  break;
+  case kFormatYCrCb420SemiPlanar:       *target = HAL_PIXEL_FORMAT_YCrCb_420_SP;          break;
+  case kFormatYCbCr420SemiPlanar:       *target = HAL_PIXEL_FORMAT_YCbCr_420_SP;          break;
+  case kFormatYCbCr422Packed:           *target = HAL_PIXEL_FORMAT_YCbCr_422_I;           break;
+  case kFormatYCbCr420SemiPlanarVenus:  *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;    break;
+
+  default:
+    DLOGE("Unsupported format = 0x%x", format);
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+}  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_buffer_allocator.h b/displayengine/libs/hwc/hwc_buffer_allocator.h
new file mode 100644
index 0000000..123f04a
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_buffer_allocator.h
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2015, 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 __HWC_BUFFER_ALLOCATOR_H__
+#define __HWC_BUFFER_ALLOCATOR_H__
+
+#include <sys/mman.h>
+#include <fcntl.h>
+
+namespace gralloc {
+
+class IAllocController;
+
+}  // namespace gralloc
+
+namespace sde {
+
+class HWCBufferAllocator : public BufferAllocator {
+ public:
+  HWCBufferAllocator();
+
+  DisplayError AllocateBuffer(BufferInfo *buffer_info);
+  DisplayError FreeBuffer(BufferInfo *buffer_info);
+
+ private:
+  static const size_t kSecureBufferAlignment = 0x00100000;
+
+  struct MetaBufferInfo {
+    int alloc_type;              //!< Specifies allocation type set by the buffer allocator.
+    void *base_addr;             //!< Specifies the base address of the allocated output buffer.
+  };
+
+  int SetHALFormat(LayerBufferFormat format, int *target);
+
+  gralloc::IAllocController *alloc_controller_;
+};
+
+}  // namespace sde
+#endif  // __HWC_BUFFER_ALLOCATOR_H__
+
diff --git a/displayengine/libs/hwc/hwc_buffer_sync_handler.cpp b/displayengine/libs/hwc/hwc_buffer_sync_handler.cpp
new file mode 100644
index 0000000..31788ea
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_buffer_sync_handler.cpp
@@ -0,0 +1,71 @@
+/*
+* Copyright (c) 2015, 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 <sync/sync.h>
+#include <utils/constants.h>
+
+#include "hwc_debugger.h"
+#include "hwc_buffer_sync_handler.h"
+
+#define __CLASS__ "HWCBufferSyncHandler"
+
+namespace sde {
+
+DisplayError HWCBufferSyncHandler::SyncWait(int fd) {
+  int error = 0;
+
+  if (fd >= 0) {
+    error = sync_wait(fd, 1000);
+    if (error < 0) {
+      DLOGE("sync_wait error errno = %d, desc = %s", errno,  strerror(errno));
+      close(fd);
+      return kErrorTimeOut;
+    }
+    close(fd);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWCBufferSyncHandler::SyncMerge(int fd1, int fd2, int *merged_fd) {
+  DisplayError error = kErrorNone;
+
+  *merged_fd = sync_merge("SyncMerge", fd1, fd2);
+  if (*merged_fd == -1) {
+    DLOGE(" Sync merge error! fd1 %d fd2 %d", fd1, fd2);
+    error = kErrorFileDescriptor;
+  }
+  close(fd1);
+  close(fd2);
+
+  return error;
+}
+
+}  // namespace sde
+
diff --git a/displayengine/libs/hwc/hwc_buffer_sync_handler.h b/displayengine/libs/hwc/hwc_buffer_sync_handler.h
new file mode 100644
index 0000000..26b1d33
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_buffer_sync_handler.h
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 2015, 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 __HWC_BUFFER_SYNC_HANDLER_H__
+#define __HWC_BUFFER_SYNC_HANDLER_H__
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <core/sde_types.h>
+#include <core/buffer_sync_handler.h>
+
+namespace sde {
+
+class HWCBufferSyncHandler : public BufferSyncHandler {
+ public:
+  HWCBufferSyncHandler() { }
+
+  virtual DisplayError SyncWait(int fd);
+  virtual DisplayError SyncMerge(int fd1, int fd2, int *merged_fd);
+};
+
+}  // namespace sde
+#endif  // __HWC_BUFFER_SYNC_HANDLER_H__
+
+
diff --git a/displayengine/libs/hwc/hwc_debugger.cpp b/displayengine/libs/hwc/hwc_debugger.cpp
new file mode 100644
index 0000000..d35e9cf
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_debugger.cpp
@@ -0,0 +1,135 @@
+/*
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/constants.h>
+
+#include "hwc_debugger.h"
+
+namespace sde {
+
+HWCDebugHandler HWCDebugHandler::debug_handler_;
+uint32_t HWCDebugHandler::debug_flags_ = 0x1;
+
+void HWCDebugHandler::DebugAll(bool enable) {
+  if (enable) {
+    debug_flags_ = 0xFFFFFFFF;
+  } else {
+    debug_flags_ = 0x1;   // kTagNone should always be printed.
+  }
+}
+
+void HWCDebugHandler::DebugResources(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagResources);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagResources);
+  }
+}
+
+void HWCDebugHandler::DebugStrategy(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagStrategy);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagStrategy);
+  }
+}
+
+void HWCDebugHandler::DebugCompManager(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagCompManager);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagCompManager);
+  }
+}
+
+void HWCDebugHandler::DebugDriverConfig(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagDriverConfig);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagDriverConfig);
+  }
+}
+
+void HWCDebugHandler::DebugBufferManager(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagBufferManager);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagBufferManager);
+  }
+}
+
+void HWCDebugHandler::DebugOfflineCtrl(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagOfflineCtrl);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagOfflineCtrl);
+  }
+}
+
+void HWCDebugHandler::Error(DebugTag /*tag*/, const char *format, ...) {
+  va_list list;
+  va_start(list, format);
+  __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, list);
+}
+
+void HWCDebugHandler::Warning(DebugTag /*tag*/, const char *format, ...) {
+  va_list list;
+  va_start(list, format);
+  __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, list);
+}
+
+void HWCDebugHandler::Info(DebugTag tag, const char *format, ...) {
+  if (IS_BIT_SET(debug_flags_, tag)) {
+    va_list list;
+    va_start(list, format);
+    __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, list);
+  }
+}
+
+void HWCDebugHandler::Verbose(DebugTag tag, const char *format, ...) {
+  if (IS_BIT_SET(debug_flags_, tag)) {
+    va_list list;
+    va_start(list, format);
+    __android_log_vprint(ANDROID_LOG_VERBOSE, LOG_TAG, format, list);
+  }
+}
+
+void HWCDebugHandler::BeginTrace(const char *class_name, const char *function_name,
+                                 const char *custom_string) {
+  char name[PATH_MAX] = {0};
+  snprintf(name, sizeof(name), "%s::%s::%s", class_name, function_name, custom_string);
+  atrace_begin(ATRACE_TAG, name);
+}
+
+void HWCDebugHandler::EndTrace() {
+  atrace_end(ATRACE_TAG);
+}
+
+}  // namespace sde
+
diff --git a/displayengine/libs/hwc/hwc_debugger.h b/displayengine/libs/hwc/hwc_debugger.h
new file mode 100644
index 0000000..def31db
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_debugger.h
@@ -0,0 +1,81 @@
+/*
+* Copyright (c) 2014 - 2015, 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 __HWC_DEBUGGER_H__
+#define __HWC_DEBUGGER_H__
+
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
+#include <core/sde_types.h>
+#include <core/debug_interface.h>
+#include <cutils/log.h>
+#include <utils/Trace.h>
+
+#define DLOG(Macro, format, ...) Macro(__CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
+
+#define DLOGE(format, ...) DLOG(ALOGE, format, ##__VA_ARGS__)
+#define DLOGW(format, ...) DLOG(ALOGW, format, ##__VA_ARGS__)
+#define DLOGI(format, ...) DLOG(ALOGI, format, ##__VA_ARGS__)
+#define DLOGV(format, ...) DLOG(ALOGV, format, ##__VA_ARGS__)
+
+#define DTRACE_BEGIN(custom_string) HWCDebugHandler::Get()->BeginTrace(__CLASS__, __FUNCTION__, \
+                                                                       custom_string)
+#define DTRACE_END() HWCDebugHandler::Get()->EndTrace()
+#define DTRACE_SCOPED() ScopeTracer<HWCDebugHandler> scope_tracer(__CLASS__, __FUNCTION__)
+
+namespace sde {
+
+class HWCDebugHandler : public DebugHandler {
+ public:
+  static inline DebugHandler* Get() { return &debug_handler_; }
+  static void DebugAll(bool enable);
+  static void DebugResources(bool enable);
+  static void DebugStrategy(bool enable);
+  static void DebugCompManager(bool enable);
+  static void DebugDriverConfig(bool enable);
+  static void DebugBufferManager(bool enable);
+  static void DebugOfflineCtrl(bool enable);
+
+  virtual void Error(DebugTag tag, const char *format, ...);
+  virtual void Warning(DebugTag tag, const char *format, ...);
+  virtual void Info(DebugTag tag, const char *format, ...);
+  virtual void Verbose(DebugTag tag, const char *format, ...);
+  virtual void BeginTrace(const char *class_name, const char *function_name,
+                          const char *custom_string);
+  virtual void EndTrace();
+
+ private:
+  static HWCDebugHandler debug_handler_;
+  static uint32_t debug_flags_;
+};
+
+}  // namespace sde
+
+#endif  // __HWC_DEBUGGER_H__
+
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index 5294faa..452bff1 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -1,33 +1,40 @@
 /*
 * Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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 <errno.h>
 #include <gralloc_priv.h>
 #include <utils/constants.h>
+#include <qdMetaData.h>
+#include <sync/sync.h>
 
 #include "hwc_display.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
 
 #define __CLASS__ "HWCDisplay"
 
@@ -36,13 +43,15 @@
 HWCDisplay::HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type,
                        int id)
   : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL),
-    flush_(false) {
+    flush_(false), output_buffer_(NULL), dump_frame_count_(0), dump_frame_index_(0),
+    dump_input_layers_(false) {
 }
 
 int HWCDisplay::Init() {
   DisplayError error = core_intf_->CreateDisplay(type_, this, &display_intf_);
   if (UNLIKELY(error != kErrorNone)) {
-    DLOGE("Display create failed. Error = %d", error);
+    DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p",
+      error, type_, this, &display_intf_);
     return -EINVAL;
   }
 
@@ -56,8 +65,9 @@
     return -EINVAL;
   }
 
-  if (LIKELY(layer_stack_memory_.raw)) {
+  if (layer_stack_memory_.raw) {
     delete[] layer_stack_memory_.raw;
+    layer_stack_memory_.raw = NULL;
   }
 
   return 0;
@@ -174,6 +184,10 @@
   return index;
 }
 
+int HWCDisplay::SetActiveConfig(hwc_display_contents_1_t *content_list) {
+  return 0;
+}
+
 int HWCDisplay::SetActiveConfig(int index) {
   DisplayError error = kErrorNone;
 
@@ -186,6 +200,14 @@
   return 0;
 }
 
+void HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+  dump_frame_count_ = count;
+  dump_frame_index_ = 0;
+  dump_input_layers_ = ((bit_mask_layer_type & (1 << INPUT_LAYER_DUMP)) != 0);
+
+  DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
+}
+
 DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
   if (*hwc_procs_) {
     (*hwc_procs_)->vsync(*hwc_procs_, id_, vsync.timestamp);
@@ -296,7 +318,8 @@
     LayerBuffer *layer_buffer = layer.input_buffer;
 
     if (pvt_handle) {
-      if (SetFormat(pvt_handle->format, pvt_handle->flags, &layer_buffer->format)) {
+      layer_buffer->format = GetSDEFormat(pvt_handle->format, pvt_handle->flags);
+      if (layer_buffer->format == kFormatInvalid) {
         return -EINVAL;
       }
 
@@ -310,6 +333,13 @@
         layer_stack_.flags.secure_present = true;
         layer_buffer->flags.secure = true;
       }
+
+      // TODO(user) : Initialize it to display refresh rate
+      layer.frame_rate = 60;
+      MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata);
+      if (meta_data && meta_data->operation & UPDATE_REFRESH_RATE) {
+        layer.frame_rate = meta_data->refreshrate;
+      }
     }
 
     SetRect(hwc_layer.displayFrame, &layer.dst_rect);
@@ -386,6 +416,8 @@
 
   size_t num_hw_layers = content_list->numHwLayers;
 
+  DumpInputBuffers(content_list);
+
   if (!flush_) {
     for (size_t i = 0; i < num_hw_layers; i++) {
       hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
@@ -411,13 +443,18 @@
     }
   }
 
+  return status;
+}
+
+int HWCDisplay::PostCommitLayerStack(hwc_display_contents_1_t *content_list) {
+  size_t num_hw_layers = content_list->numHwLayers;
+  int status = 0;
+
   if (flush_) {
     DisplayError error = display_intf_->Flush();
     if (error != kErrorNone) {
       DLOGE("Flush failed. Error = %d", error);
     }
-
-    flush_ = false;
   }
 
   for (size_t i = 0; i < num_hw_layers; i++) {
@@ -425,7 +462,7 @@
     Layer &layer = layer_stack_.layers[i];
     LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
 
-    if ((status == 0) && (layer.composition == kCompositionSDE ||
+    if (!flush_ && (layer.composition == kCompositionSDE ||
                          layer.composition == kCompositionGPUTarget)) {
       hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
     }
@@ -435,9 +472,21 @@
     }
   }
 
+  if (!flush_) {
+    content_list->retireFenceFd = layer_stack_.retire_fence_fd;
+
+    if (dump_frame_count_) {
+      dump_frame_count_--;
+      dump_frame_index_++;
+    }
+  }
+
+  flush_ = false;
+
   return status;
 }
 
+
 bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) {
   uint32_t layer_count = layer_stack_.layer_count;
 
@@ -526,44 +575,160 @@
   }
 }
 
-int HWCDisplay::SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target) {
-
-  if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
-    switch (source) {
-      case HAL_PIXEL_FORMAT_RGBA_8888:          *target = kFormatRGBA8888Ubwc;            break;
-      case HAL_PIXEL_FORMAT_RGB_565:            *target = kFormatRGB565Ubwc;              break;
-      case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
-      case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
-      case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:    *target = kFormatYCbCr420SPVenusUbwc;     break;
-      default:
-        DLOGE("Unsupported format type for UBWC %d", source);
-        return -EINVAL;
-    }
-    return 0;
-  }
-
-  switch (source) {
-  case HAL_PIXEL_FORMAT_RGBA_8888:            *target = kFormatRGBA8888;                  break;
-  case HAL_PIXEL_FORMAT_BGRA_8888:            *target = kFormatBGRA8888;                  break;
-  case HAL_PIXEL_FORMAT_RGBX_8888:            *target = kFormatRGBX8888;                  break;
-  case HAL_PIXEL_FORMAT_BGRX_8888:            *target = kFormatBGRX8888;                  break;
-  case HAL_PIXEL_FORMAT_RGB_888:              *target = kFormatRGB888;                    break;
-  case HAL_PIXEL_FORMAT_RGB_565:              *target = kFormatRGB565;                    break;
-  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:   *target = kFormatYCbCr420SemiPlanarVenus;   break;
-  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:  *target = kFormatYCbCr420SPVenusUbwc;   break;
-  default:
-    DLOGW("Unsupported format type = %d", source);
-    return -EINVAL;
-  }
-
-  return 0;
-}
-
 void HWCDisplay::SetIdleTimeoutMs(uint32_t timeout_ms) {
   if (display_intf_) {
     display_intf_->SetIdleTimeoutMs(timeout_ms);
   }
 }
 
+LayerBufferFormat HWCDisplay::GetSDEFormat(const int32_t &source, const int flags) {
+  LayerBufferFormat format = kFormatInvalid;
+  if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+    switch (source) {
+    case HAL_PIXEL_FORMAT_RGBA_8888:          format = kFormatRGBA8888Ubwc;            break;
+    case HAL_PIXEL_FORMAT_RGB_565:            format = kFormatRGB565Ubwc;              break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:    format = kFormatYCbCr420SPVenusUbwc;     break;
+    default:
+      DLOGE("Unsupported format type for UBWC %d", source);
+      return kFormatInvalid;
+    }
+    return format;
+  }
+
+  switch (source) {
+  case HAL_PIXEL_FORMAT_RGBA_8888:                format = kFormatRGBA8888;                 break;
+  case HAL_PIXEL_FORMAT_BGRA_8888:                format = kFormatBGRA8888;                 break;
+  case HAL_PIXEL_FORMAT_RGBX_8888:                format = kFormatRGBX8888;                 break;
+  case HAL_PIXEL_FORMAT_BGRX_8888:                format = kFormatBGRX8888;                 break;
+  case HAL_PIXEL_FORMAT_RGB_888:                  format = kFormatRGB888;                   break;
+  case HAL_PIXEL_FORMAT_RGB_565:                  format = kFormatRGB565;                   break;
+  case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:       format = kFormatYCbCr420SemiPlanarVenus;  break;
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:  format = kFormatYCbCr420SPVenusUbwc;      break;
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP:             format = kFormatYCrCb420SemiPlanar;       break;
+  default:
+    DLOGW("Unsupported format type = %d", source);
+    return kFormatInvalid;
+  }
+
+  return format;
+}
+
+void HWCDisplay::DumpInputBuffers(hwc_display_contents_1_t *content_list) {
+  size_t num_hw_layers = content_list->numHwLayers;
+  char dir_path[PATH_MAX];
+
+  if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
+    return;
+  }
+
+  snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
+
+  if (mkdir(dir_path, 0777) != 0 && errno != EEXIST) {
+    DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+    return;
+  }
+
+  // if directory exists already, need to explicitly change the permission.
+  if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+    DLOGW("Failed to change permissions on %s directory", dir_path);
+    return;
+  }
+
+  for (uint32_t i = 0; i < num_hw_layers; i++) {
+    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+    const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+
+    if (hwc_layer.acquireFenceFd >= 0) {
+      int error = sync_wait(hwc_layer.acquireFenceFd, 1000);
+      if (error < 0) {
+        DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+        return;
+      }
+    }
+
+    if (pvt_handle && pvt_handle->base) {
+      char dump_file_name[PATH_MAX];
+      size_t result = 0;
+
+      snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
+               dir_path, i, pvt_handle->width, pvt_handle->height,
+               GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
+
+      FILE* fp = fopen(dump_file_name, "w+");
+      if (fp) {
+        result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
+        fclose(fp);
+      }
+
+      DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
+    }
+  }
+}
+
+const char *HWCDisplay::GetHALPixelFormatString(int format) {
+  switch (format) {
+  case HAL_PIXEL_FORMAT_RGBA_8888:
+    return "RGBA_8888";
+  case HAL_PIXEL_FORMAT_RGBX_8888:
+    return "RGBX_8888";
+  case HAL_PIXEL_FORMAT_RGB_888:
+    return "RGB_888";
+  case HAL_PIXEL_FORMAT_RGB_565:
+    return "RGB_565";
+  case HAL_PIXEL_FORMAT_BGRA_8888:
+    return "BGRA_8888";
+  case HAL_PIXEL_FORMAT_RGBA_5551:
+    return "RGBA_5551";
+  case HAL_PIXEL_FORMAT_RGBA_4444:
+    return "RGBA_4444";
+  case HAL_PIXEL_FORMAT_YV12:
+    return "YV12";
+  case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+    return "YCbCr_422_SP_NV16";
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+    return "YCrCb_420_SP_NV21";
+  case HAL_PIXEL_FORMAT_YCbCr_422_I:
+    return "YCbCr_422_I_YUY2";
+  case HAL_PIXEL_FORMAT_YCrCb_422_I:
+    return "YCrCb_422_I_YVYU";
+  case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+    return "NV12_ENCODEABLE";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+    return "YCbCr_420_SP_TILED_TILE_4x2";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+    return "YCbCr_420_SP";
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+    return "YCrCb_420_SP_ADRENO";
+  case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+    return "YCrCb_422_SP";
+  case HAL_PIXEL_FORMAT_R_8:
+    return "R_8";
+  case HAL_PIXEL_FORMAT_RG_88:
+    return "RG_88";
+  case HAL_PIXEL_FORMAT_INTERLACE:
+    return "INTERLACE";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    return "YCbCr_420_SP_VENUS";
+  default:
+    return "Unknown pixel format";
+  }
+}
+
+const char *HWCDisplay::GetDisplayString() {
+  switch (type_) {
+  case kPrimary:
+    return "primary";
+  case kHDMI:
+    return "hdmi";
+  case kVirtual:
+    return "virtual";
+  default:
+    return "invalid";
+  }
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 262c719..3934078 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -43,6 +43,8 @@
   virtual int GetActiveConfig();
   virtual int SetActiveConfig(int index);
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual int SetActiveConfig(hwc_display_contents_1_t *content_list);
+  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
 
  protected:
   // Maximum number of layers supported by display engine.
@@ -81,6 +83,7 @@
   virtual int AllocateLayerStack(hwc_display_contents_1_t *content_list);
   virtual int PrepareLayerStack(hwc_display_contents_1_t *content_list);
   virtual int CommitLayerStack(hwc_display_contents_1_t *content_list);
+  virtual int PostCommitLayerStack(hwc_display_contents_1_t *content_list);
   bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
   void CacheLayerStackInfo(hwc_display_contents_1_t *content_list);
   inline void SetRect(const hwc_rect_t &source, LayerRect *target);
@@ -88,7 +91,16 @@
   inline void SetComposition(const int32_t &source, LayerComposition *target);
   inline void SetComposition(const int32_t &source, int32_t *target);
   inline void SetBlending(const int32_t &source, LayerBlending *target);
-  inline int SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target);
+  int SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target);
+  LayerBufferFormat GetSDEFormat(const int32_t &source, const int flags);
+  void DumpInputBuffers(hwc_display_contents_1_t *content_list);
+  const char *GetHALPixelFormatString(int format);
+  const char *GetDisplayString();
+
+  enum {
+    INPUT_LAYER_DUMP,
+    OUTPUT_LAYER_DUMP,
+  };
 
   CoreInterface *core_intf_;
   hwc_procs_t const **hwc_procs_;
@@ -99,6 +111,10 @@
   LayerStack layer_stack_;
   LayerStackCache layer_stack_cache_;
   bool flush_;
+  LayerBuffer *output_buffer_;
+  uint32_t dump_frame_count_;
+  uint32_t dump_frame_index_;
+  bool dump_input_layers_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_external.cpp b/displayengine/libs/hwc/hwc_display_external.cpp
index 468478b..2758e3a 100644
--- a/displayengine/libs/hwc/hwc_display_external.cpp
+++ b/displayengine/libs/hwc/hwc_display_external.cpp
@@ -1,31 +1,36 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include <utils/constants.h>
 
 #include "hwc_display_external.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
 
 #define __CLASS__ "HWCDisplayExternal"
 
@@ -59,7 +64,10 @@
     return status;
   }
 
-  content_list->retireFenceFd = layer_stack_.retire_fence_fd;
+  status = HWCDisplay::PostCommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
 
   return 0;
 }
diff --git a/displayengine/libs/hwc/hwc_display_primary.cpp b/displayengine/libs/hwc/hwc_display_primary.cpp
index b282ba6..6dbb723 100644
--- a/displayengine/libs/hwc/hwc_display_primary.cpp
+++ b/displayengine/libs/hwc/hwc_display_primary.cpp
@@ -1,31 +1,36 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include <utils/constants.h>
 
 #include "hwc_display_primary.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
 
 #define __CLASS__ "HWCDisplayPrimary"
 
@@ -59,7 +64,10 @@
     return status;
   }
 
-  content_list->retireFenceFd = layer_stack_.retire_fence_fd;
+  status = HWCDisplay::PostCommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
 
   return 0;
 }
diff --git a/displayengine/libs/hwc/hwc_display_virtual.cpp b/displayengine/libs/hwc/hwc_display_virtual.cpp
old mode 100755
new mode 100644
index 88cd073..9601e63
--- a/displayengine/libs/hwc/hwc_display_virtual.cpp
+++ b/displayengine/libs/hwc/hwc_display_virtual.cpp
@@ -1,47 +1,238 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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.
+* 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.
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include <utils/constants.h>
+#include <gralloc_priv.h>
+#include <sync/sync.h>
 
 #include "hwc_display_virtual.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
 
 #define __CLASS__ "HWCDisplayVirtual"
 
 namespace sde {
 
 HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
-  : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL) {
+  : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL),
+    dump_output_layer_(false) {
+}
+
+int HWCDisplayVirtual::Init() {
+  int status = 0;
+
+  output_buffer_ = new LayerBuffer();
+  if (!output_buffer_) {
+    return -ENOMEM;
+  }
+
+  return HWCDisplay::Init();
+}
+
+int HWCDisplayVirtual::Deinit() {
+  int status = 0;
+
+  status = HWCDisplay::Deinit();
+  if (status) {
+    return status;
+  }
+
+  if (output_buffer_) {
+    delete output_buffer_;
+  }
+
+  return status;
 }
 
 int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+  status = AllocateLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  status = SetOutputBuffer(content_list);
+  if (status) {
+    return status;
+  }
+
+  status = PrepareLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
   return 0;
 }
 
 int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  status = HWCDisplay::CommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  DumpOutputBuffer(content_list);
+
+  status = HWCDisplay::PostCommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  if (content_list->outbufAcquireFenceFd >= 0) {
+    close(content_list->outbufAcquireFenceFd);
+    content_list->outbufAcquireFenceFd = -1;
+  }
+
   return 0;
 }
 
+int HWCDisplayVirtual::SetActiveConfig(hwc_display_contents_1_t *content_list) {
+  const private_handle_t *output_handle =
+        static_cast<const private_handle_t *>(content_list->outbuf);
+  DisplayError error = kErrorNone;
+  int status = 0;
+
+  if (output_handle) {
+    LayerBufferFormat format = GetSDEFormat(output_handle->format, output_handle->flags);
+    if (format == kFormatInvalid) {
+      return -EINVAL;
+    }
+
+    if ((output_handle->width != INT(output_buffer_->width)) ||
+        (output_handle->height != INT(output_buffer_->height)) ||
+        (format != output_buffer_->format)) {
+      DisplayConfigVariableInfo variable_info;
+
+      variable_info.x_pixels = output_handle->width;
+      variable_info.y_pixels = output_handle->height;
+      // TODO(user): Need to get the framerate of primary display and update it.
+      variable_info.fps = 60;
+
+      error = display_intf_->SetActiveConfig(&variable_info);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+
+      status = SetOutputBuffer(content_list);
+      if (status) {
+        return status;
+      }
+    }
+  }
+
+  return 0;
+}
+
+int HWCDisplayVirtual::SetOutputBuffer(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  const private_handle_t *output_handle =
+        static_cast<const private_handle_t *>(content_list->outbuf);
+
+  // Fill output buffer parameters (width, height, format, plane information, fence)
+  output_buffer_->acquire_fence_fd = content_list->outbufAcquireFenceFd;
+
+  if (output_handle) {
+    output_buffer_->format = GetSDEFormat(output_handle->format, output_handle->flags);
+    if (output_buffer_->format == kFormatInvalid) {
+      return -EINVAL;
+    }
+
+    output_buffer_->width = output_handle->width;
+    output_buffer_->height = output_handle->height;
+    output_buffer_->flags.secure = 0;
+    output_buffer_->flags.video = 0;
+
+    // ToDo: Need to extend for non-RGB formats
+    output_buffer_->planes[0].fd = output_handle->fd;
+    output_buffer_->planes[0].offset = output_handle->offset;
+    output_buffer_->planes[0].stride = output_handle->width;
+  }
+
+  layer_stack_.output_buffer = output_buffer_;
+
+  return status;
+}
+
+void HWCDisplayVirtual::DumpOutputBuffer(hwc_display_contents_1_t *content_list) {
+  const private_handle_t *output_handle = (const private_handle_t *)(content_list->outbuf);
+  char dir_path[PATH_MAX];
+
+  if (!dump_frame_count_ || flush_ || !dump_output_layer_) {
+    return;
+  }
+
+  snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
+
+  if (mkdir(dir_path, 777) != 0 && errno != EEXIST) {
+    DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+    return;
+  }
+
+  // if directory exists already, need to explicitly change the permission.
+  if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+    DLOGW("Failed to change permissions on %s directory", dir_path);
+    return;
+  }
+
+  if (output_handle && output_handle->base) {
+    char dump_file_name[PATH_MAX];
+    size_t result = 0;
+
+    if (content_list->outbufAcquireFenceFd >= 0) {
+      int error = sync_wait(content_list->outbufAcquireFenceFd, 1000);
+      if (error < 0) {
+        DLOGW("sync_wait error errno = %d, desc = %s", errno,  strerror(errno));
+        return;
+      }
+    }
+
+    snprintf(dump_file_name, sizeof(dump_file_name), "%s/output_layer_%dx%d_%s_frame%d.raw",
+             dir_path, output_handle->width, output_handle->height,
+             GetHALPixelFormatString(output_handle->format), dump_frame_index_);
+
+    FILE* fp = fopen(dump_file_name, "w+");
+    if (fp) {
+      result = fwrite(reinterpret_cast<void *>(output_handle->base), output_handle->size, 1, fp);
+      fclose(fp);
+    }
+
+    DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
+  }
+}
+
+void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+  HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
+  dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
+
+  DLOGI("output_layer_dump_enable %d", dump_output_layer_);
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/hwc/hwc_display_virtual.h b/displayengine/libs/hwc/hwc_display_virtual.h
index 796ed32..7ac7c22 100644
--- a/displayengine/libs/hwc/hwc_display_virtual.h
+++ b/displayengine/libs/hwc/hwc_display_virtual.h
@@ -32,8 +32,18 @@
 class HWCDisplayVirtual : public HWCDisplay {
  public:
   explicit HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+  virtual int Init();
+  virtual int Deinit();
   virtual int Prepare(hwc_display_contents_1_t *content_list);
   virtual int Commit(hwc_display_contents_1_t *content_list);
+  virtual int SetActiveConfig(hwc_display_contents_1_t *content_list);
+  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+
+ private:
+  int SetOutputBuffer(hwc_display_contents_1_t *content_list);
+  void DumpOutputBuffer(hwc_display_contents_1_t *content_list);
+
+  bool dump_output_layer_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_logger.cpp b/displayengine/libs/hwc/hwc_logger.cpp
deleted file mode 100755
index 9d65e1c..0000000
--- a/displayengine/libs/hwc/hwc_logger.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without modification, are permitted
-* provided that the following conditions are met:
-*    * Redistributions of source code must retain the above copyright notice, this list of
-*      conditions and the following disclaimer.
-*    * Redistributions in binary form must reproduce the above copyright notice, this list of
-*      conditions and the following disclaimer in the documentation and/or other materials provided
-*      with the distribution.
-*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
-*      endorse or promote products derived from this software without specific prior written
-*      permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <utils/constants.h>
-
-#include "hwc_logger.h"
-
-namespace sde {
-
-HWCLogHandler HWCLogHandler::log_handler_;
-uint32_t HWCLogHandler::log_flags_ = 0x1;
-
-void HWCLogHandler::LogAll(bool enable) {
-  if (enable) {
-    log_flags_ = 0xFFFFFFFF;
-  } else {
-    log_flags_ = 0x1;   // kTagNone should always be printed.
-  }
-}
-
-void HWCLogHandler::LogResources(bool enable) {
-  if (enable) {
-    SET_BIT(log_flags_, kTagResources);
-  } else {
-    CLEAR_BIT(log_flags_, kTagResources);
-  }
-}
-
-void HWCLogHandler::LogStrategy(bool enable) {
-  if (enable) {
-    SET_BIT(log_flags_, kTagStrategy);
-  } else {
-    CLEAR_BIT(log_flags_, kTagStrategy);
-  }
-}
-
-void HWCLogHandler::Error(LogTag /*tag*/, const char *format, ...) {
-  va_list list;
-  va_start(list, format);
-  __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, list);
-}
-
-void HWCLogHandler::Warning(LogTag /*tag*/, const char *format, ...) {
-  va_list list;
-  va_start(list, format);
-  __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, list);
-}
-
-void HWCLogHandler::Info(LogTag tag, const char *format, ...) {
-  if (IS_BIT_SET(log_flags_, tag)) {
-    va_list list;
-    va_start(list, format);
-    __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, list);
-  }
-}
-
-void HWCLogHandler::Verbose(LogTag tag, const char *format, ...) {
-  if (IS_BIT_SET(log_flags_, tag)) {
-    va_list list;
-    va_start(list, format);
-    __android_log_vprint(ANDROID_LOG_VERBOSE, LOG_TAG, format, list);
-  }
-}
-
-}  // namespace sde
-
diff --git a/displayengine/libs/hwc/hwc_logger.h b/displayengine/libs/hwc/hwc_logger.h
deleted file mode 100755
index 7568990..0000000
--- a/displayengine/libs/hwc/hwc_logger.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-* Copyright (c) 2014, 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 __HWC_LOGGER_H__
-#define __HWC_LOGGER_H__
-
-#include <core/sde_types.h>
-#include <cutils/log.h>
-
-#define DLOG(Macro, format, ...) Macro(__CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
-
-#define DLOGE(format, ...) DLOG(ALOGE, format, ##__VA_ARGS__)
-#define DLOGW(format, ...) DLOG(ALOGW, format, ##__VA_ARGS__)
-#define DLOGI(format, ...) DLOG(ALOGI, format, ##__VA_ARGS__)
-#define DLOGV(format, ...) DLOG(ALOGV, format, ##__VA_ARGS__)
-
-namespace sde {
-
-class HWCLogHandler : public LogHandler {
- public:
-  static inline LogHandler* Get() { return &log_handler_; }
-  static void LogAll(bool enable);
-  static void LogResources(bool enable);
-  static void LogStrategy(bool enable);
-
-  virtual void Error(LogTag tag, const char *format, ...);
-  virtual void Warning(LogTag tag, const char *format, ...);
-  virtual void Info(LogTag tag, const char *format, ...);
-  virtual void Verbose(LogTag tag, const char *format, ...);
-
- private:
-  static HWCLogHandler log_handler_;
-  static uint32_t log_flags_;
-};
-
-}  // namespace sde
-
-#endif  // __HWC_LOGGER_H__
-
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index 8fd72b8..3bc4fd1 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -1,25 +1,30 @@
 /*
 * Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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 <core/dump_interface.h>
@@ -30,9 +35,12 @@
 #include <sys/prctl.h>
 #include <binder/Parcel.h>
 #include <QService.h>
+#include <core/buffer_allocator.h>
 
+#include "hwc_buffer_allocator.h"
+#include "hwc_buffer_sync_handler.h"
 #include "hwc_session.h"
-#include "hwc_logger.h"
+#include "hwc_debugger.h"
 
 #define __CLASS__ "HWCSession"
 
@@ -57,8 +65,8 @@
 Locker HWCSession::locker_;
 
 HWCSession::HWCSession(const hw_module_t *module) : core_intf_(NULL), hwc_procs_(NULL),
-            display_primary_(NULL), display_external_(NULL), hotplug_thread_exit_(false),
-            hotplug_thread_name_("HWC_HotPlugThread") {
+            display_primary_(NULL), display_external_(NULL), display_virtual_(NULL),
+            hotplug_thread_exit_(false), hotplug_thread_name_("HWC_HotPlugThread") {
   hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
   hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_4;
   hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module);
@@ -92,7 +100,20 @@
     return -EINVAL;
   }
 
-  DisplayError error = CoreInterface::CreateCore(this, HWCLogHandler::Get(), &core_intf_);
+  buffer_allocator_ = new HWCBufferAllocator();
+  if (buffer_allocator_ == NULL) {
+    DLOGE("Display core initialization failed due to no memory");
+    return -ENOMEM;
+  }
+
+  buffer_sync_handler_ = new HWCBufferSyncHandler();
+  if (buffer_sync_handler_ == NULL) {
+    DLOGE("Display core initialization failed due to no memory");
+    return -ENOMEM;
+  }
+
+  DisplayError error = CoreInterface::CreateCore(this, HWCDebugHandler::Get(), buffer_allocator_,
+                                                 buffer_sync_handler_, &core_intf_);
   if (error != kErrorNone) {
     DLOGE("Display core initialization failed. Error = %d", error);
     return -EINVAL;
@@ -187,7 +208,9 @@
 
 int HWCSession::Prepare(hwc_composer_device_1 *device, size_t num_displays,
                         hwc_display_contents_1_t **displays) {
-  SCOPE_LOCK(locker_);
+  DTRACE_SCOPED();
+
+  SEQUENCE_ENTRY_SCOPE_LOCK(locker_);
 
   if (!device || !displays) {
     return -EINVAL;
@@ -208,6 +231,15 @@
       }
       break;
     case HWC_DISPLAY_VIRTUAL:
+      if (hwc_session->ValidateContentList(content_list)) {
+        hwc_session->CreateVirtualDisplay(hwc_session, content_list);
+      } else {
+        hwc_session->DestroyVirtualDisplay(hwc_session);
+      }
+
+      if (hwc_session->display_virtual_) {
+        hwc_session->display_virtual_->Prepare(content_list);
+      }
       break;
     default:
       break;
@@ -220,7 +252,9 @@
 
 int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
                     hwc_display_contents_1_t **displays) {
-  SCOPE_LOCK(locker_);
+  DTRACE_SCOPED();
+
+  SEQUENCE_EXIT_SCOPE_LOCK(locker_);
 
   if (!device || !displays) {
     return -EINVAL;
@@ -241,6 +275,9 @@
       }
       break;
     case HWC_DISPLAY_VIRTUAL:
+      if (hwc_session->display_virtual_) {
+        hwc_session->display_virtual_->Commit(content_list);
+      }
       break;
     default:
       break;
@@ -252,7 +289,7 @@
 }
 
 int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
 
   if (!device) {
     return -EINVAL;
@@ -270,6 +307,8 @@
       status = hwc_session->display_external_->EventControl(event, enable);
     }
     break;
+  case HWC_DISPLAY_VIRTUAL:
+    break;
   default:
     status = -EINVAL;
   }
@@ -278,7 +317,7 @@
 }
 
 int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
 
   if (!device) {
     return -EINVAL;
@@ -296,6 +335,11 @@
       status = hwc_session->display_external_->SetPowerMode(mode);
     }
     break;
+  case HWC_DISPLAY_VIRTUAL:
+    if (hwc_session->display_virtual_) {
+      status = hwc_session->display_virtual_->SetPowerMode(mode);
+    }
+    break;
   default:
     status = -EINVAL;
   }
@@ -304,6 +348,8 @@
 }
 
 int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
   if (!device || !value) {
     return -EINVAL;
   }
@@ -321,7 +367,7 @@
 }
 
 void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
-  SCOPE_LOCK(locker_);
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
 
   if (!device || !buffer || !length) {
     return;
@@ -332,6 +378,8 @@
 
 int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
                                   size_t *num_configs) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
   if (!device || !configs || !num_configs) {
     return -EINVAL;
   }
@@ -348,6 +396,11 @@
       status = hwc_session->display_external_->GetDisplayConfigs(configs, num_configs);
     }
     break;
+  case HWC_DISPLAY_VIRTUAL:
+    if (hwc_session->display_virtual_) {
+      status = hwc_session->display_virtual_->GetDisplayConfigs(configs, num_configs);
+    }
+    break;
   default:
     status = -EINVAL;
   }
@@ -357,6 +410,8 @@
 
 int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
                                      const uint32_t *attributes, int32_t *values) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
   if (!device || !attributes || !values) {
     return -EINVAL;
   }
@@ -373,6 +428,11 @@
       status = hwc_session->display_external_->GetDisplayAttributes(config, attributes, values);
     }
     break;
+  case HWC_DISPLAY_VIRTUAL:
+    if (hwc_session->display_virtual_) {
+      status = hwc_session->display_virtual_->GetDisplayAttributes(config, attributes, values);
+    }
+    break;
   default:
     status = -EINVAL;
   }
@@ -381,6 +441,8 @@
 }
 
 int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
   if (!device) {
     return -1;
   }
@@ -397,6 +459,11 @@
       active_config = hwc_session->display_external_->GetActiveConfig();
     }
     break;
+  case HWC_DISPLAY_VIRTUAL:
+    if (hwc_session->display_virtual_) {
+      active_config = hwc_session->display_virtual_->GetActiveConfig();
+    }
+    break;
   default:
     active_config = -1;
   }
@@ -405,6 +472,8 @@
 }
 
 int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
   if (!device) {
     return -EINVAL;
   }
@@ -422,6 +491,8 @@
       status = 0;  // hwc_session->display_external_->SetActiveConfig(index);
     }
     break;
+  case HWC_DISPLAY_VIRTUAL:
+    break;
   default:
     status = -EINVAL;
   }
@@ -429,12 +500,67 @@
   return status;
 }
 
+bool HWCSession::ValidateContentList(hwc_display_contents_1_t *content_list) {
+  return (content_list && content_list->numHwLayers > 0 && content_list->outbuf);
+}
+
+int HWCSession::CreateVirtualDisplay(HWCSession *hwc_session,
+                                     hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  if (!hwc_session->display_virtual_) {
+    // Create virtual display device
+    hwc_session->display_virtual_ = new HWCDisplayVirtual(hwc_session->core_intf_,
+                                                          &hwc_session->hwc_procs_);
+    if (!hwc_session->display_virtual_) {
+      // This is not catastrophic. Leave a warning message for now.
+      DLOGW("Virtual Display creation failed");
+      return -ENOMEM;
+    }
+
+    status = hwc_session->display_virtual_->Init();
+    if (status) {
+      goto CleanupOnError;
+    }
+
+    status = hwc_session->display_virtual_->SetPowerMode(HWC_POWER_MODE_NORMAL);
+    if (status) {
+      goto CleanupOnError;
+    }
+  }
+
+  if (hwc_session->display_virtual_) {
+    status = hwc_session->display_virtual_->SetActiveConfig(content_list);
+  }
+
+  return status;
+
+CleanupOnError:
+  return hwc_session->DestroyVirtualDisplay(hwc_session);
+}
+
+int HWCSession::DestroyVirtualDisplay(HWCSession *hwc_session) {
+  int status = 0;
+
+  if (hwc_session->display_virtual_) {
+    status = hwc_session->display_virtual_->Deinit();
+    if (!status) {
+      delete hwc_session->display_virtual_;
+      hwc_session->display_virtual_ = NULL;
+    }
+  }
+
+  return status;
+}
+
 DisplayError HWCSession::Hotplug(const CoreEventHotplug &hotplug) {
   return kErrorNone;
 }
 
 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
                                              android::Parcel */*output_parcel*/) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
   switch (command) {
   case qService::IQService::DYNAMIC_DEBUG:
     DynamicDebug(input_parcel);
@@ -450,6 +576,11 @@
       display_primary_->SetIdleTimeoutMs(timeout);
     }
     break;
+
+  case qService::IQService::SET_FRAME_DUMP_CONFIG:
+    SetFrameDumpConfig(input_parcel);
+    break;
+
   default:
     DLOGW("QService command = %d is not supported", command);
     return -EINVAL;
@@ -458,6 +589,30 @@
   return 0;
 }
 
+void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
+  uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
+  uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
+  uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
+
+  if (bit_mask_display_type & (1 << qService::IQService::DUMP_PRIMARY_DISPLAY)) {
+    if (display_primary_) {
+      display_primary_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+
+  if (bit_mask_display_type & (1 << qService::IQService::DUMP_HDMI_DISPLAY)) {
+    if (display_external_) {
+      display_external_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+
+  if (bit_mask_display_type & (1 << qService::IQService::DUMP_VIRTUAL_DISPLAY)) {
+    if (display_virtual_) {
+      display_virtual_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+}
+
 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
   int type = input_parcel->readInt32();
   bool enable = (input_parcel->readInt32() > 0);
@@ -465,21 +620,34 @@
 
   switch (type) {
   case qService::IQService::DEBUG_ALL:
-    HWCLogHandler::LogAll(enable);
+    HWCDebugHandler::DebugAll(enable);
     break;
 
   case qService::IQService::DEBUG_MDPCOMP:
-    HWCLogHandler::LogStrategy(enable);
+    HWCDebugHandler::DebugStrategy(enable);
+    HWCDebugHandler::DebugCompManager(enable);
     break;
 
   case qService::IQService::DEBUG_PIPE_LIFECYCLE:
-    HWCLogHandler::LogResources(enable);
+    HWCDebugHandler::DebugResources(enable);
+    break;
+
+  case qService::IQService::DEBUG_DRIVER_CONFIG:
+    HWCDebugHandler::DebugDriverConfig(enable);
+    break;
+
+  case qService::IQService::DEBUG_ROTATOR:
+    HWCDebugHandler::DebugResources(enable);
+    HWCDebugHandler::DebugDriverConfig(enable);
+    HWCDebugHandler::DebugBufferManager(enable);
+    HWCDebugHandler::DebugOfflineCtrl(enable);
     break;
 
   default:
     DLOGW("type = %d is not supported", type);
   }
 }
+
 void* HWCSession::HWCHotPlugThread(void *context) {
   if (context) {
     return reinterpret_cast<HWCSession *>(context)->HWCHotPlugThreadHandler();
@@ -532,7 +700,6 @@
   return -1;
 }
 
-
 int HWCSession::HotPlugHandler(bool connected) {
   if (!hwc_procs_) {
      DLOGW("Ignore hotplug - hwc_proc not registered");
@@ -540,7 +707,7 @@
   }
 
   if (connected) {
-    SCOPE_LOCK(locker_);
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_);
     if (display_external_) {
      DLOGE("HDMI already connected");
      return -1;
@@ -557,7 +724,7 @@
       return -1;
     }
   } else {
-    SCOPE_LOCK(locker_);
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_);
     if (!display_external_) {
      DLOGE("HDMI not connected");
      return -1;
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index 488da9d..4b8c8ce 100644
--- a/displayengine/libs/hwc/hwc_session.h
+++ b/displayengine/libs/hwc/hwc_session.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, 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:
@@ -32,6 +32,7 @@
 
 #include "hwc_display_primary.h"
 #include "hwc_display_external.h"
+#include "hwc_display_virtual.h"
 
 namespace sde {
 
@@ -72,6 +73,9 @@
   void* HWCHotPlugThreadHandler();
   int GetHDMIConnectedState(const char *uevent_data, int length);
   int HotPlugHandler(bool connected);
+  bool ValidateContentList(hwc_display_contents_1_t *content_list);
+  int CreateVirtualDisplay(HWCSession *hwc_session, hwc_display_contents_1_t *content_list);
+  int DestroyVirtualDisplay(HWCSession *hwc_session);
 
   // CoreEventHandler methods
   virtual DisplayError Hotplug(const CoreEventHotplug &hotplug);
@@ -80,15 +84,19 @@
   virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
                                            android::Parcel *output_parcel);
   void DynamicDebug(const android::Parcel *input_parcel);
+  void SetFrameDumpConfig(const android::Parcel *input_parcel);
 
   static Locker locker_;
   CoreInterface *core_intf_;
   hwc_procs_t const *hwc_procs_;
   HWCDisplayPrimary *display_primary_;
   HWCDisplayExternal *display_external_;
+  HWCDisplayVirtual *display_virtual_;
   pthread_t hotplug_thread_;
   bool hotplug_thread_exit_;
   const char *hotplug_thread_name_;
+  HWCBufferAllocator *buffer_allocator_;
+  HWCBufferSyncHandler *buffer_sync_handler_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/utils/debug_android.cpp b/displayengine/libs/utils/debug_android.cpp
index 447a88d..1b08fe9 100644
--- a/displayengine/libs/utils/debug_android.cpp
+++ b/displayengine/libs/utils/debug_android.cpp
@@ -1,25 +1,30 @@
 /*
 * Copyright (c) 2014 - 2015, 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.
+* 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.
+* 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 <stdlib.h>
@@ -31,7 +36,7 @@
 
 Debug Debug::debug_;
 
-Debug::Debug() : log_handler_(&default_log_handler_), virtual_driver_(false) {
+Debug::Debug() : debug_handler_(&default_debug_handler_), virtual_driver_(false) {
   char property[PROPERTY_VALUE_MAX];
   if (property_get("displaycore.virtualdriver", property, NULL) > 0) {
     virtual_driver_ = (atoi(property) == 1);
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 48da09e..df7be41 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -289,7 +289,9 @@
     //the usage bits, gralloc assigns a format.
     if(format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
        format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
-        if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
+        if (usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC)
+            grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+        else if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
             grallocFormat = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; //NV12
         else if((usage & GRALLOC_USAGE_HW_CAMERA_MASK)
                 == GRALLOC_USAGE_HW_CAMERA_ZSL)
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 546a67b..f1edf5d 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -131,6 +131,21 @@
     return renderArea;
 }
 
+bool CopyBit::isLayerChanging(hwc_display_contents_1_t *list, int k) {
+    if((mLayerCache.hnd[k] != list->hwLayers[k].handle) ||
+            (mLayerCache.displayFrame[k].left !=
+                         list->hwLayers[k].displayFrame.left) ||
+            (mLayerCache.displayFrame[k].top !=
+                         list->hwLayers[k].displayFrame.top) ||
+            (mLayerCache.displayFrame[k].right !=
+                         list->hwLayers[k].displayFrame.right) ||
+            (mLayerCache.displayFrame[k].bottom !=
+                         list->hwLayers[k].displayFrame.bottom)) {
+        return 1;
+    }
+    return 0;
+}
+
 int CopyBit::getLayersChanging(hwc_context_t *ctx,
                       hwc_display_contents_1_t *list,
                       int dpy){
@@ -146,7 +161,7 @@
     int updatingLayerCount = 0;
     for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
        //swap rect will kick in only for single updating layer
-       if(mLayerCache.hnd[k] != list->hwLayers[k].handle){
+       if(isLayerChanging(list, k)) {
            updatingLayerCount ++;
            if(updatingLayerCount == 1)
              changingLayerIndex = k;
@@ -163,19 +178,20 @@
        dirtyRect = list->hwLayers[changingLayerIndex].dirtyRect;
 #endif
 
-       for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
-            //disable swap rect for overlapping visible layer(s)
-            hwc_rect_t displayFrame = list->hwLayers[k].displayFrame;
-            hwc_rect_t result = getIntersection(displayFrame,dirtyRect);
-            if((k != changingLayerIndex) && isValidRect(result)){
-              return -1;
+       for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--) {
+           //disable swap rect in case of scaling and video .
+           private_handle_t *hnd =(private_handle_t *)list->hwLayers[k].handle;
+           if(needsScaling(&list->hwLayers[k])||( hnd && isYuvBuffer(hnd))) {
+               mFbCache.reset();
+               return -1;
            }
        }
-       mFbCache.insertAndUpdateFbCache(dirtyRect);
        if(mFbCache.getUnchangedFbDRCount(dirtyRect) <
-                                             NUM_RENDER_BUFFERS)
+                                             NUM_RENDER_BUFFERS) {
+               mFbCache.insertAndUpdateFbCache(dirtyRect);
               changingLayerIndex =  -1;
-    }else {
+       }
+    } else {
        mFbCache.reset();
        changingLayerIndex =  -1;
     }
@@ -189,23 +205,11 @@
 
    //dirty rect will enable only if
    //1.Only single layer is updating.
-   //2.No overlapping
-   //3.No scaling
-   //4.No video layer
+   //2.No scaling
+   //3.No video layer
    if(mSwapRectEnable == false)
       return -1;
-   int changingLayerIndex =  getLayersChanging(ctx, list, dpy);
-   //swap rect will kick in only for single updating layer
-   if(changingLayerIndex == -1){
-      return -1;
-   }
-   if(!needsScaling(&list->hwLayers[changingLayerIndex])){
-     private_handle_t *hnd =
-         (private_handle_t *)list->hwLayers[changingLayerIndex].handle;
-      if( hnd && !isYuvBuffer(hnd))
-           return  changingLayerIndex;
-   }
-   return -1;
+   return getLayersChanging(ctx, list, dpy);
 }
 
 bool CopyBit::prepareOverlap(hwc_context_t *ctx,
@@ -472,6 +476,7 @@
              list->hwLayers[abcRenderBufIdx].acquireFenceFd);
           }
           for(int i = abcRenderBufIdx + 1; i < layerCount; i++){
+             mDirtyLayerIndex = -1;
              int retVal = drawLayerUsingCopybit(ctx,
                &(list->hwLayers[i]),renderBuffer, 0);
              if(retVal < 0) {
@@ -480,8 +485,8 @@
           }
           // Get Release Fence FD of copybit for the App layer(s)
           copybit->flush_get_fence(copybit, copybitFd);
-          close(list->hwLayers[abcRenderBufIdx].acquireFenceFd);
-          list->hwLayers[abcRenderBufIdx].acquireFenceFd = -1;
+          close(list->hwLayers[last].acquireFenceFd);
+          list->hwLayers[last].acquireFenceFd = -1;
           return true;
        }
     }
@@ -533,19 +538,16 @@
     }
 
     mDirtyLayerIndex =  checkDirtyRect(ctx, list, dpy);
-    if( mDirtyLayerIndex != -1){
-          hwc_layer_1_t *layer = &list->hwLayers[mDirtyLayerIndex];
-#ifdef QCOM_BSP
-          clear(renderBuffer,layer->dirtyRect);
-#else
-          clear(renderBuffer,layer->displayFrame);
-#endif
-    } else {
-          hwc_rect_t clearRegion = {0,0,0,0};
-          if(CBUtils::getuiClearRegion(list, clearRegion, layerProp))
-             clear(renderBuffer, clearRegion);
-    }
+    ALOGD_IF (DEBUG_COPYBIT, "%s:Dirty Layer Index: %d",
+                                       __FUNCTION__, mDirtyLayerIndex);
+    hwc_rect_t clearRegion = {0,0,0,0};
+    mDirtyRect = list->hwLayers[last].displayFrame;
+    if (mDirtyLayerIndex != -1)
+        mDirtyRect = list->hwLayers[mDirtyLayerIndex].displayFrame;
 
+    if (CBUtils::getuiClearRegion(list, clearRegion, layerProp,
+                                                       mDirtyLayerIndex))
+             clear(renderBuffer, clearRegion);
     // numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
     for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
         if(!(layerProp[i].mFlags & HWC_COPYBIT)) {
@@ -555,9 +557,6 @@
         if(ctx->copybitDrop[i]) {
             continue;
         }
-        //skip non updating layers
-        if((mDirtyLayerIndex != -1) && (mDirtyLayerIndex != i) )
-            continue;
         int ret = -1;
         if (list->hwLayers[i].acquireFenceFd != -1
                 && ctx->mMDP.version >= qdutils::MDP_V4_0) {
@@ -857,11 +856,18 @@
 #ifdef QCOM_BSP
     //change src and dst with dirtyRect
     if(mDirtyLayerIndex != -1) {
-      srcRect.l = layer->dirtyRect.left;
-      srcRect.t = layer->dirtyRect.top;
-      srcRect.r = layer->dirtyRect.right;
-      srcRect.b = layer->dirtyRect.bottom;
-      dstRect = srcRect;
+      hwc_rect_t result = getIntersection(displayFrame, mDirtyRect);
+      if(!isValidRect(result))
+             return true;
+      dstRect.l = result.left;
+      dstRect.t = result.top;
+      dstRect.r = result.right;
+      dstRect.b = result.bottom;
+
+      srcRect.l += (result.left - displayFrame.left);
+      srcRect.t += (result.top - displayFrame.top);
+      srcRect.r -= (displayFrame.right - result.right);
+      srcRect.b -= (displayFrame.bottom - result.bottom);
     }
 #endif
     // Copybit dst
@@ -1213,6 +1219,7 @@
    layerCount = ctx->listStats[dpy].numAppLayers;
    for (int i=0; i<ctx->listStats[dpy].numAppLayers; i++){
       hnd[i] = list->hwLayers[i].handle;
+      displayFrame[i] = list->hwLayers[i].displayFrame;
    }
 }
 
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index a7ce43e..6ead4a7 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -60,6 +60,7 @@
     struct LayerCache {
       int layerCount;
       buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
+      hwc_rect_t displayFrame[MAX_NUM_APP_LAYERS];
       /* c'tor */
       LayerCache();
       /* clear caching info*/
@@ -129,10 +130,12 @@
     int mDirtyLayerIndex;
     LayerCache mLayerCache;
     FbCache mFbCache;
+    hwc_rect_t mDirtyRect;
     int getLayersChanging(hwc_context_t *ctx, hwc_display_contents_1_t *list,
                   int dpy);
     int checkDirtyRect(hwc_context_t *ctx, hwc_display_contents_1_t *list,
                   int dpy);
+    bool isLayerChanging(hwc_display_contents_1_t *list, int k);
 };
 
 }; //namespace qhwc
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index b17bdaf..caa1344 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -528,9 +528,11 @@
     return ret;
 }
 
-void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
+        hwc_rect &dst) {
     hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
-    fbRect = getIntersection(fbRect, roi);
+    dst = getIntersection(dst, roi);
+    crop = dst;
 }
 
 /* 1) Identify layers that are not visible or lying outside the updating ROI and
@@ -626,14 +628,20 @@
             ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
 }
 
-void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
-    hwc_rect l_roi = ctx->listStats[mDpy].lRoi;
-    hwc_rect r_roi = ctx->listStats[mDpy].rRoi;
-
-    hwc_rect_t l_fbRect = getIntersection(fbRect, l_roi);
-    hwc_rect_t r_fbRect = getIntersection(fbRect, r_roi);
-    fbRect = getUnion(l_fbRect, r_fbRect);
+void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
+        hwc_rect &dst) {
+    hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
+            ctx->listStats[mDpy].rRoi);
+    hwc_rect tmpDst = getIntersection(dst, roi);
+    if(!isSameRect(dst, tmpDst)) {
+        crop.left = crop.left + (tmpDst.left - dst.left);
+        crop.top = crop.top + (tmpDst.top - dst.top);
+        crop.right = crop.left + (tmpDst.right - tmpDst.left);
+        crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
+        dst = tmpDst;
+    }
 }
+
 /* 1) Identify layers that are not visible or lying outside BOTH the updating
  *    ROI's and drop them from composition. If a layer is spanning across both
  *    the halves of the screen but needed by only ROI, the non-contributing
@@ -1759,7 +1767,7 @@
             fbRect = getUnion(fbRect, dst);
         }
     }
-    trimAgainstROI(ctx, fbRect);
+    trimAgainstROI(ctx, fbRect, fbRect);
     return fbRect;
 }
 
@@ -2606,6 +2614,122 @@
 }
 
 //================MDPCompSrcSplit==============================================
+
+bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
+
+    for(int i = numAppLayers - 1; i >= 0; i--) {
+        if(!isValidRect(visibleRect)) {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+            continue;
+        }
+
+        const hwc_layer_1_t* layer =  &list->hwLayers[i];
+        hwc_rect_t dstRect = layer->displayFrame;
+        hwc_rect_t res  = getIntersection(visibleRect, dstRect);
+
+        if(!isValidRect(res)) {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+        } else {
+            /* Reset frame ROI when any layer which needs scaling also needs ROI
+             * cropping */
+            if(!isSameRect(res, dstRect) && needsScaling (layer)) {
+                ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
+                memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+                mCurrentFrame.dropCount = 0;
+                return false;
+            }
+
+            /* deduct any opaque region from visibleRect */
+            if (layer->blending == HWC_BLENDING_NONE &&
+                    layer->planeAlpha == 0xFF)
+                visibleRect = deductRect(visibleRect, res);
+        }
+    }
+    return true;
+}
+
+/*
+ * HW Limitation: ping pong split can always split the ping pong output
+ * equally across two DSI's. So the ROI programmed should be of equal width
+ * for both the halves
+ */
+void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+
+
+    if(!canPartialUpdate(ctx, list))
+        return;
+
+    struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
+    hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
+        (int)ctx->dpyAttr[mDpy].yres};
+
+    for(int index = 0; index < numAppLayers; index++ ) {
+        hwc_layer_1_t* layer = &list->hwLayers[index];
+
+        // If we have a RGB layer which needs rotation, no partial update
+        if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
+            return;
+
+        if ((mCachedFrame.hnd[index] != layer->handle) ||
+                isYuvBuffer((private_handle_t *)layer->handle)) {
+            hwc_rect_t dst = layer->displayFrame;
+            hwc_rect_t updatingRect = dst;
+
+#ifdef QCOM_BSP
+            if(!needsScaling(layer) && !layer->transform)
+            {
+                hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+                int x_off = dst.left - src.left;
+                int y_off = dst.top - src.top;
+                updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
+            }
+#endif
+
+            roi = getUnion(roi, updatingRect);
+        }
+    }
+
+    /* No layer is updating. Still SF wants a refresh.*/
+    if(!isValidRect(roi))
+        return;
+
+    roi = expandROIFromMidPoint(roi, fullFrame);
+
+    hwc_rect lFrame = fullFrame;
+    lFrame.right /= 2;
+    hwc_rect lRoi = getIntersection(roi, lFrame);
+
+    // Align ROI coordinates to panel restrictions
+    lRoi = getSanitizeROI(lRoi, lFrame);
+
+    hwc_rect rFrame = fullFrame;
+    rFrame.left = lFrame.right;
+    hwc_rect rRoi = getIntersection(roi, rFrame);
+
+    // Align ROI coordinates to panel restrictions
+    rRoi = getSanitizeROI(rRoi, rFrame);
+
+    roi = getUnion(lRoi, rRoi);
+
+    ctx->listStats[mDpy].lRoi = roi;
+    if(!validateAndApplyROI(ctx, list))
+        resetROI(ctx, mDpy);
+
+    ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
+            __FUNCTION__,
+            ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+            ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
+            ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
+            ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
+}
+
 bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
         MdpPipeInfoSplit& pipe_info) {
     private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -2614,6 +2738,9 @@
     pipe_info.lIndex = ovutils::OV_INVALID;
     pipe_info.rIndex = ovutils::OV_INVALID;
 
+    if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
+        trimAgainstROI(ctx,crop, dst);
+
     //If 2 pipes are staged on a single stage of a mixer, then the left pipe
     //should have a higher priority than the right one. Pipe priorities are
     //starting with VG0, VG1 ... , RGB0 ..., DMA1
@@ -2703,6 +2830,17 @@
     ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
              "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
 
+    if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
+        /* MDP driver crops layer coordinates against ROI in Non-Split
+         * and Split MDP comp. But HWC needs to crop them for source split.
+         * Reason: 1) Source split is efficient only when the final effective
+         *            load is distributed evenly across mixers.
+         *         2) We have to know the effective width of the layer that
+         *            the ROI needs to find the no. of pipes the layer needs.
+         */
+        trimAgainstROI(ctx, crop, dst);
+    }
+
     // Handle R/B swap
     if (layer->flags & HWC_FORMAT_RB_SWAP) {
         if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 302b047..7c46c1a 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -160,9 +160,9 @@
     /* validates the ROI generated for fallback conditions */
     virtual bool validateAndApplyROI(hwc_context_t *ctx,
             hwc_display_contents_1_t* list) = 0;
-    /* Trims fbRect calculated against ROI generated */
-    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) = 0;
-
+    /* Trims layer coordinates against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+            hwc_rect& dst) = 0;
     /* set/reset flags for MDPComp */
     void setMDPCompLayerFlags(hwc_context_t *ctx,
                               hwc_display_contents_1_t* list);
@@ -315,8 +315,9 @@
     /* validates the ROI generated for fallback conditions */
     virtual bool validateAndApplyROI(hwc_context_t *ctx,
             hwc_display_contents_1_t* list);
-    /* Trims fbRect calculated against ROI generated */
-    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
+    /* Trims layer coordinates against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+            hwc_rect& dst);
 };
 
 class MDPCompSplit : public MDPComp {
@@ -342,6 +343,9 @@
     /* allocates pipes to selected candidates */
     virtual bool allocLayerPipes(hwc_context_t *ctx,
                                  hwc_display_contents_1_t* list);
+    /* Trims layer coordinates against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+            hwc_rect& dst);
 private:
     /* Increments mdpCount if 4k2k yuv layer split is enabled.
      * updates framebuffer z order if fb lies above source-split layer */
@@ -357,8 +361,6 @@
     /* validates the ROI generated for fallback conditions */
     virtual bool validateAndApplyROI(hwc_context_t *ctx,
             hwc_display_contents_1_t* list);
-    /* Trims fbRect calculated against ROI generated */
-    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
 };
 
 class MDPCompSrcSplit : public MDPCompSplit {
@@ -371,6 +373,12 @@
 
     virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
             PipeLayerPair& pipeLayerPair);
+    /* generates ROI based on the modified area of the frame */
+    virtual void generateROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* validates the ROI generated for fallback conditions */
+    virtual bool validateAndApplyROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
 };
 
 }; //namespace
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index f53e8c4..8fb622f 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -74,7 +74,7 @@
 #endif
 #endif
 
-#define PROP_DEFAULT_APPBUFFER  "ro.sf.default_app_buffer"
+#define PROP_DEFAULT_APPBUFFER  "sf.default.app_buffer_count"
 #define MAX_RAM_SIZE  512*1024*1024
 #define qHD_WIDTH 540
 
@@ -2577,6 +2577,30 @@
     }
 }
 
+hwc_rect expandROIFromMidPoint(hwc_rect roi, hwc_rect fullFrame) {
+    int lRoiWidth = 0, rRoiWidth = 0;
+    int half_frame_width = fullFrame.right/2;
+
+    hwc_rect lFrame = fullFrame;
+    hwc_rect rFrame = fullFrame;
+    lFrame.right = (lFrame.right - lFrame.left)/2;
+    rFrame.left = lFrame.right;
+
+    hwc_rect lRoi = getIntersection(roi, lFrame);
+    hwc_rect rRoi = getIntersection(roi, rFrame);
+
+    lRoiWidth = lRoi.right - lRoi.left;
+    rRoiWidth = rRoi.right - rRoi.left;
+
+    if(lRoiWidth && rRoiWidth) {
+        if(lRoiWidth < rRoiWidth)
+            roi.left = half_frame_width - rRoiWidth;
+        else
+            roi.right = half_frame_width + lRoiWidth;
+    }
+    return roi;
+}
+
 void resetROI(hwc_context_t *ctx, const int dpy) {
     const int fbXRes = (int)ctx->dpyAttr[dpy].xres;
     const int fbYRes = (int)ctx->dpyAttr[dpy].yres;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 797f9b0..d419213 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -352,6 +352,9 @@
 // Resets display ROI to full panel resoluion
 void resetROI(hwc_context_t *ctx, const int dpy);
 
+// Modifies ROI even from middle of the screen
+hwc_rect expandROIFromMidPoint(hwc_rect roi, hwc_rect fullFrame);
+
 // Aligns updating ROI to panel restrictions
 hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary);
 
diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp
index 722916a..89f8044 100644
--- a/libhwcomposer/hwc_vsync.cpp
+++ b/libhwcomposer/hwc_vsync.cpp
@@ -157,7 +157,9 @@
                 }
             }
 
-            pread(pfd[dpy][ev].fd, vdata , MAX_DATA, 0);
+            memset(&vdata, '\0', sizeof(vdata));
+            // Read once from the fds to clear the first notify
+            pread(pfd[dpy][ev].fd, vdata , MAX_DATA - 1, 0);
             if (pfd[dpy][ev].fd >= 0)
                 pfd[dpy][ev].events = POLLPRI | POLLERR;
         }
@@ -170,7 +172,10 @@
                 for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
                     for(size_t ev = 0; ev < num_events; ev++) {
                         if (pfd[dpy][ev].revents & POLLPRI) {
-                            ssize_t len = pread(pfd[dpy][ev].fd, vdata, MAX_DATA, 0);
+                            // Clear vdata before writing into it
+                            memset(&vdata, '\0', sizeof(vdata));
+                            ssize_t len = pread(pfd[dpy][ev].fd, vdata,
+                                                MAX_DATA - 1, 0);
                             if (UNLIKELY(len < 0)) {
                                 // If the read was just interrupted - it is not
                                 // a fatal error. Just continue in this case
@@ -179,6 +184,7 @@
                                         __FUNCTION__, ev, dpy, strerror(errno));
                                 continue;
                             }
+                            vdata[len] = '\0';
                             event_list[ev].callback(ctx, dpy, vdata);
                         }
                     }
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index ca599ed..a34e599 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -306,14 +306,20 @@
         if(leftType == rightType) {
             //Safe. Onus on driver to assign correct pipes within same type
             return false;
-        } else if(leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG) {
-            //If we are here, right is definitely a higher prio type.
+        } else {
             //This check takes advantage of having only 3 types and avoids 3
             //different failure combination checks.
-            return true;
-        } else {
-            //Types are correct priority-wise
-            return false;
+            // Swap IF:
+            // ----------------
+            // | Left | Right |
+            // ================
+            // | DMA  | ViG   |
+            // ----------------
+            // | DMA  | RGB   |
+            // ----------------
+            // | RGB  | ViG   |
+            // ----------------
+            return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
         }
     } else if(pipe1Id < 0) {
         //LEFT needs new allocation.
@@ -321,8 +327,7 @@
             // If RIGHT has highest priority(lowest id), swap it.
             return (pipe2Id == PipeBook::pipeMinID[leftType]);
         } else {
-            // Swap if needs lowest priority type pipe.
-            return (leftType == OV_MDP_PIPE_DMA);
+            return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
         }
     } else { /* if (pipe2Id < 0) */
         // RIGHT needs new allocation.
@@ -330,8 +335,7 @@
             // If LEFT has lowest priority(highest id), swap it.
             return (pipe1Id == PipeBook::pipeMaxID[leftType]);
         } else {
-            // Swap if needs highest  priority type pipe.
-            return (rightType == OV_MDP_PIPE_VG);
+            return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
         }
     }
 }
diff --git a/libqdutils/cb_utils.cpp b/libqdutils/cb_utils.cpp
index ef66ac6..c17842a 100644
--- a/libqdutils/cb_utils.cpp
+++ b/libqdutils/cb_utils.cpp
@@ -41,13 +41,36 @@
 namespace qdutils {
 
 int CBUtils::getuiClearRegion(hwc_display_contents_1_t* list,
-          hwc_rect_t &clearWormholeRect, LayerProp *layerProp) {
+          hwc_rect_t &clearWormholeRect, LayerProp *layerProp, int dirtyIndex) {
 
     size_t last = list->numHwLayers - 1;
     hwc_rect_t fbFrame = list->hwLayers[last].displayFrame;
     Rect fbFrameRect(fbFrame.left,fbFrame.top,fbFrame.right,fbFrame.bottom);
     Region wormholeRegion(fbFrameRect);
 
+   if (dirtyIndex != -1) {
+#ifdef QCOM_BSP
+      /*
+       * 1. Map dirty rect of updating layer to its display frame.
+       * 2. Use this display frame as wormholeRegion instead of full Frame
+       * */
+      hwc_rect_t dirtyRect = list->hwLayers[dirtyIndex].dirtyRect;
+      hwc_rect_t displayFrame = list->hwLayers[dirtyIndex].displayFrame;
+      hwc_frect_t sCropF = list->hwLayers[dirtyIndex].sourceCropf;
+      hwc_rect_t srcRect = {int(ceilf(sCropF.left)), int(ceilf(sCropF.top)),
+                           int(ceilf(sCropF.right)), int(ceilf(sCropF.bottom))};
+
+      displayFrame.left += dirtyRect.left - srcRect.left;
+      displayFrame.top += dirtyRect.top - srcRect.top;
+      displayFrame.right -= srcRect.right - dirtyRect.right;
+      displayFrame.bottom -= srcRect.bottom - dirtyRect.bottom;
+
+      Rect tmpRect(displayFrame.left,displayFrame.top,displayFrame.right,
+            displayFrame.bottom);
+      Region tmpRegion(tmpRect);
+      wormholeRegion = wormholeRegion.intersect(tmpRegion);
+#endif
+   }
     if(cb_swap_rect::getInstance().checkSwapRectFeature_on() == true){
       wormholeRegion.set(0,0);
       for(size_t i = 0 ; i < last; i++) {
diff --git a/libqdutils/cb_utils.h b/libqdutils/cb_utils.h
index 85dd78f..59f452b 100644
--- a/libqdutils/cb_utils.h
+++ b/libqdutils/cb_utils.h
@@ -38,7 +38,7 @@
 public:
 static int getuiClearRegion(hwc_display_contents_1_t* list,
                               hwc_rect_t &clearWormholeRec,
-                                      LayerProp *layerProp);
+                              LayerProp *layerProp, int dirtyIndex = -1);
 };
 }//namespace qdutils
 #endif /* end of include guard: CB_UTIL_H*/
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index ef47475..cd2d116 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -59,6 +59,7 @@
         CONFIGURE_DYN_REFRESH_RATE = 18,
         SET_PARTIAL_UPDATE = 19,   // Preference on partial update feature
         TOGGLE_SCREEN_UPDATE = 20, // Provides ability to disable screen updates
+        SET_FRAME_DUMP_CONFIG = 21,  // Provides ability to set the frame dump config
         COMMAND_LIST_END = 400,
     };
 
@@ -73,6 +74,14 @@
         DEBUG_VSYNC,
         DEBUG_VD,
         DEBUG_PIPE_LIFECYCLE,
+        DEBUG_DRIVER_CONFIG,
+        DEBUG_ROTATOR,
+    };
+
+    enum {
+        DUMP_PRIMARY_DISPLAY,
+        DUMP_HDMI_DISPLAY,
+        DUMP_VIRTUAL_DISPLAY,
     };
 
     // Register a client that can be notified