sde: Add support for layer caching

1. Pass layer updating flag to composition manager to mark those
   layers for SDE composition.
2. Compare cached layer stack info with current layer stack info.
   if it matches then set composition type to HWC_OVERLAY, so that
   surfaceflinger wont compose those cached layers into framebuffer
3. Cache current layer stack information for next frame composition.

Change-Id: I3485a8ac2242fa25b48e79b1549d37ef7638c9af
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
index e361ac7..74c1960 100644
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -111,8 +111,14 @@
   uint64_t geometry_changed : 1;  //!< This flag shall be set by client to indicate that the layer
                                   //!< set passed to Prepare() has changed by more than just the
                                   //!< buffer handles and acquire fences.
+  uint64_t skip_present : 1;      //!< This flag will be set to true, if the current layer stack
+                                  //!< contains skip layers
+  uint64_t video_present : 1;     //!< This flag will be set to true, if current layer stack
+                                  //!< contains video
+  uint64_t secure_present : 1;    //!< This flag will be set to true, if the current layer stack
+                                  //!< contains secure layers
 
-  LayerStackFlags() : geometry_changed(0) { }
+  LayerStackFlags() : geometry_changed(0), skip_present(0), video_present(0), secure_present(0) { }
 };
 
 /*! @brief This structure defines a rectanglular area inside a display layer.
diff --git a/displayengine/include/private/strategy_interface.h b/displayengine/include/private/strategy_interface.h
index f14fbfb..23dea8e 100644
--- a/displayengine/include/private/strategy_interface.h
+++ b/displayengine/include/private/strategy_interface.h
@@ -67,7 +67,7 @@
 
 /*! @brief Maximum number of layers that can be handled by hardware in a given layer stack.
 */
-const int kNumLayersMax = 16;
+const int kMaxSDELayers = 16;
 
 /*! @brief This structure defines constraints and device properties that shall be considered for
     deciding a composition strategy.
@@ -81,7 +81,7 @@
   uint32_t max_layers;    //!< Maximum number of layers that shall be programmed on hardware for the
                           //!< given layer stack.
 
-  StrategyConstraints() : safe_mode(false), max_layers(kNumLayersMax) { }
+  StrategyConstraints() : safe_mode(false), max_layers(kMaxSDELayers) { }
 };
 
 /*! @brief Flag to denote that GPU composition is performed for the given layer stack.
@@ -96,7 +96,7 @@
 struct HWLayersInfo {
   LayerStack *stack;        //!< Input layer stack. Set by the caller.
 
-  uint32_t index[kNumLayersMax];
+  uint32_t index[kMaxSDELayers];
                             //!< Indexes of the layers from the layer stack which need to be
                             //!< programmed on hardware.
   uint32_t count;           //!< Total number of layers which need to be set on hardware.
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index ddf631e..e55b5e7 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -89,7 +89,7 @@
 
 struct HWLayers {
   HWLayersInfo info;
-  HWLayerConfig config[kNumLayersMax];
+  HWLayerConfig config[kMaxSDELayers];
 };
 
 struct HWDeviceAttributes : DeviceConfigVariableInfo {
diff --git a/displayengine/libs/hwc/hwc_sink.cpp b/displayengine/libs/hwc/hwc_sink.cpp
index e5b07f5..0fb4b8c 100644
--- a/displayengine/libs/hwc/hwc_sink.cpp
+++ b/displayengine/libs/hwc/hwc_sink.cpp
@@ -226,6 +226,9 @@
     return 0;
   }
 
+  // Reset Layer stack flags
+  layer_stack_.flags = LayerStackFlags();
+
   // Configure each layer
   for (size_t i = 0; i < num_hw_layers; i++) {
     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
@@ -244,6 +247,12 @@
       layer_buffer->planes[0].fd = pvt_handle->fd;
       layer_buffer->planes[0].offset = pvt_handle->offset;
       layer_buffer->planes[0].stride = pvt_handle->width;
+      if (pvt_handle->bufferType == BUFFER_TYPE_VIDEO) {
+        layer_stack_.flags.video_present = true;
+      }
+      if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+        layer_stack_.flags.secure_present = true;
+      }
     }
 
     SetRect(&layer.dst_rect, hwc_layer.displayFrame);
@@ -252,7 +261,6 @@
         SetRect(&layer.visible_regions.rect[j], hwc_layer.visibleRegionScreen.rects[j]);
     }
     SetRect(&layer.dirty_regions.rect[0], hwc_layer.dirtyRect);
-
     SetComposition(&layer.composition, hwc_layer.compositionType);
     SetBlending(&layer.blending, hwc_layer.blending);
 
@@ -264,6 +272,11 @@
 
     layer.plane_alpha = hwc_layer.planeAlpha;
     layer.flags.skip = ((hwc_layer.flags & HWC_SKIP_LAYER) > 0);
+    layer.flags.updating = (layer_stack_cache_.layer_cache[i].handle != hwc_layer.handle);
+
+    if (layer.flags.skip) {
+      layer_stack_.flags.skip_present = true;
+    }
   }
 
   // Configure layer stack
@@ -275,15 +288,61 @@
     return -EINVAL;
   }
 
+  bool needs_fb_refresh = NeedsFrameBufferRefresh(content_list);
+
   for (size_t i = 0; i < num_hw_layers; i++) {
     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
     Layer &layer = layer_stack_.layers[i];
-    SetComposition(&hwc_layer.compositionType, layer.composition);
+    // if current frame does not need frame buffer redraw, then mark them for HWC_OVERLAY
+    LayerComposition composition = needs_fb_refresh ? layer.composition : kCompositionSDE;
+    SetComposition(&hwc_layer.compositionType, composition);
   }
+  // Cache the current layer stack information like layer_count, composition type and layer handle
+  // for the future.
+  CacheLayerStackInfo(content_list);
 
   return 0;
 }
 
+void HWCSink::CacheLayerStackInfo(hwc_display_contents_1_t *content_list) {
+  uint32_t layer_count = layer_stack_.layer_count;
+
+  for (size_t i = 0; i < layer_count; i++) {
+    Layer &layer = layer_stack_.layers[i];
+    layer_stack_cache_.layer_cache[i].handle = content_list->hwLayers[i].handle;
+    layer_stack_cache_.layer_cache[i].composition = layer.composition;
+  }
+  layer_stack_cache_.layer_count = layer_count;
+}
+
+bool HWCSink::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) {
+  uint32_t layer_count = layer_stack_.layer_count;
+
+  // Frame buffer needs to be refreshed for the following reasons:
+  // 1. Any layer is marked skip in the current layer stack.
+  // 2. Any layer is added/removed/layer properties changes in the current layer stack.
+  // 3. Any layer handle is changed and it is marked for GPU composition
+  // 4. Any layer's current composition is different from previous composition.
+  if ((layer_stack_cache_.layer_count != layer_count) || layer_stack_.flags.skip_present ||
+       layer_stack_.flags.geometry_changed) {
+    return true;
+  }
+
+  for (size_t i = 0; i < layer_count; i++) {
+    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+    Layer &layer = layer_stack_.layers[i];
+    LayerCache &layer_cache = layer_stack_cache_.layer_cache[i];
+    if (layer_cache.composition != layer.composition) {
+      return true;
+    }
+    if ((layer.composition == kCompositionGPU) && (layer_cache.handle != hwc_layer.handle)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 int HWCSink::CommitLayerStack(hwc_display_contents_1_t *content_list) {
   size_t num_hw_layers = content_list->numHwLayers;
   if (UNLIKELY(num_hw_layers <= 1)) {
diff --git a/displayengine/libs/hwc/hwc_sink.h b/displayengine/libs/hwc/hwc_sink.h
index 340aabd..551a77b 100644
--- a/displayengine/libs/hwc/hwc_sink.h
+++ b/displayengine/libs/hwc/hwc_sink.h
@@ -43,6 +43,18 @@
   int SetState(DeviceState state);
 
  protected:
+  // Maximum number of layers supported by display engine.
+  static const uint32_t kMaxLayerCount = 32;
+
+  // Structure to track memory allocation for layer stack (layers, rectangles) object.
+  struct LayerStackMemory : LayerStack {
+    static const size_t kSizeSteps = 4096;  // Default memory allocation.
+    uint8_t *raw;  // Pointer to byte array.
+    size_t size;  // Current number of allocated bytes.
+
+    LayerStackMemory() : raw(NULL), size(0) { }
+  };
+
   HWCSink(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DeviceType type, int id);
   virtual ~HWCSink() { }
 
@@ -60,18 +72,32 @@
   inline void SetBlending(LayerBlending *target, const int32_t &source);
   inline int SetFormat(LayerBufferFormat *target, const int &source);
 
-  // Structure to track memory allocation for layer stack (layers, rectangles) object.
-  struct LayerStackMemory : LayerStack {
-    static const size_t kSizeSteps = 4096;  // Default memory allocation.
-    uint8_t *raw;  // Pointer to byte array.
-    size_t size;  // Current number of allocated bytes.
-  } layer_stack_;
-
+  LayerStackMemory layer_stack_;
   CoreInterface *core_intf_;
   hwc_procs_t const **hwc_procs_;
   DeviceType type_;
   int id_;
   DeviceInterface *device_intf_;
+
+ private:
+  struct LayerCache {
+    buffer_handle_t handle;
+    LayerComposition composition;
+
+    LayerCache() : handle(NULL), composition(kCompositionGPU) { }
+  };
+
+  struct LayerStackCache {
+    LayerCache layer_cache[kMaxLayerCount];
+    uint32_t layer_count;
+
+    LayerStackCache() : layer_count(0) { }
+  };
+
+  bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
+  void CacheLayerStackInfo(hwc_display_contents_1_t *content_list);
+
+  LayerStackCache layer_stack_cache_;
 };
 
 }  // namespace sde