Merge "sdm: Remove LayerCache from HWC" into display.lnx.3.0-dev
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index 3d86fbe..9ef54d8 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -297,7 +297,7 @@
                                                    //!< applied to the layer buffer during
                                                    //!< composition.
 
-  uint8_t plane_alpha = 0;                         //!< Alpha value applied to the whole layer.
+  uint8_t plane_alpha = 0xff;                      //!< Alpha value applied to the whole layer.
                                                    //!< Value of each pixel is computed as:
                                                    //!<    if(kBlendingPremultiplied) {
                                                    //!<      pixel.RGB = pixel.RGB * planeAlpha/255
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index bc5361c..70d5b96 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -417,6 +417,7 @@
                                    // programmed on hardware.
   LayerRect updated_src_rect[kMaxSDELayers];  // Updated layer src rects in s3d mode
   LayerRect updated_dst_rect[kMaxSDELayers];  // Updated layer dst rects in s3d mode
+  bool updating[kMaxSDELayers] = {0};  // Updated by strategy, considering plane_alpha+updating
 
   uint32_t count = 0;              // Total number of layers which need to be set on hardware.
 
diff --git a/sdm/include/private/strategy_interface.h b/sdm/include/private/strategy_interface.h
index f175311..17acfed 100644
--- a/sdm/include/private/strategy_interface.h
+++ b/sdm/include/private/strategy_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, 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:
@@ -48,6 +48,7 @@
   virtual DisplayError Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts) = 0;
   virtual DisplayError GetNextStrategy(StrategyConstraints *constraints) = 0;
   virtual DisplayError Stop() = 0;
+  virtual DisplayError Reconfigure(HWDisplayMode mode, HWS3DMode s3d_mode) = 0;
 
  protected:
   virtual ~StrategyInterface() { }
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 4bd73d4..562186c 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -164,25 +164,14 @@
 
   DisplayError error = kErrorNone;
   if (display_comp_ctx->strategy) {
-    display_comp_ctx->strategy->Deinit();
-    delete display_comp_ctx->strategy;
-    display_comp_ctx->strategy = NULL;
-  }
-
-  Strategy *&new_strategy = display_comp_ctx->strategy;
-  display_comp_ctx->strategy = new Strategy(extension_intf_, display_comp_ctx->display_type,
-                                            hw_res_info_, hw_panel_info, attributes);
-  if (!display_comp_ctx->strategy) {
-    DLOGE("Unable to create strategy.");
-    return kErrorMemory;
-  }
-
-  error = new_strategy->Init();
-  if (error != kErrorNone) {
-    DLOGE("Unable to initialize strategy.");
-    delete display_comp_ctx->strategy;
-    display_comp_ctx->strategy = NULL;
-    return error;
+    error = display_comp_ctx->strategy->Reconfigure(hw_panel_info, attributes);
+    if (error != kErrorNone) {
+      DLOGE("Unable to Reconfigure strategy.");
+      display_comp_ctx->strategy->Deinit();
+      delete display_comp_ctx->strategy;
+      display_comp_ctx->strategy = NULL;
+      return error;
+    }
   }
 
   // For HDMI S3D mode, set max_layers_ to 0 so that primary display would fall back
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index 0531693..b8a499e 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -110,7 +110,7 @@
 }
 
 DisplayError Strategy::Stop() {
-  if (extn_start_success_) {
+  if (strategy_intf_) {
     return strategy_intf_->Stop();
   }
 
@@ -186,5 +186,26 @@
   }
 }
 
-}  // namespace sdm
+DisplayError Strategy::Reconfigure(const HWPanelInfo &hw_panel_info,
+                         const HWDisplayAttributes &hw_display_attributes) {
+  hw_panel_info_ = hw_panel_info;
+  hw_display_attributes_ = hw_display_attributes;
 
+  if (!extension_intf_) {
+    return kErrorNone;
+  }
+
+  // TODO(user): PU Intf will not be created for video mode panels, hence re-evaluate if
+  // reconfigure is needed.
+  if (partial_update_intf_) {
+    extension_intf_->DestroyPartialUpdate(partial_update_intf_);
+    partial_update_intf_ = NULL;
+  }
+
+  extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_,
+                                       hw_panel_info_, &partial_update_intf_);
+
+  return strategy_intf_->Reconfigure(hw_panel_info_.mode, hw_panel_info_.s3d_mode);
+}
+
+}  // namespace sdm
diff --git a/sdm/libs/core/strategy.h b/sdm/libs/core/strategy.h
index 71f45d8..5f14d28 100644
--- a/sdm/libs/core/strategy.h
+++ b/sdm/libs/core/strategy.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, 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:
@@ -43,11 +43,13 @@
                      bool partial_update_enable);
   DisplayError GetNextStrategy(StrategyConstraints *constraints);
   DisplayError Stop();
+  DisplayError Reconfigure(const HWPanelInfo &hw_panel_info,
+                           const HWDisplayAttributes &hw_display_attributes);
 
  private:
   void GenerateROI();
 
-  ExtensionInterface *extension_intf_;
+  ExtensionInterface *extension_intf_ = NULL;
   StrategyInterface *strategy_intf_ = NULL;
   PartialUpdateInterface *partial_update_intf_ = NULL;
   DisplayType display_type_;
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index 29e0c1a..f829f68 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -39,6 +39,7 @@
 #include <cutils/properties.h>
 #include <map>
 #include <utility>
+#include <vector>
 
 #include "hwc_display.h"
 #include "hwc_debugger.h"
@@ -522,7 +523,7 @@
     layer->flags.updating = true;
 
     if (num_hw_layers <= kMaxLayerCount) {
-      layer->flags.updating = IsLayerUpdating(content_list, INT32(i));
+      layer->flags.updating = IsLayerUpdating(content_list, layer);
     }
 #ifdef QTI_BSP
     if (hwc_layer.flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
@@ -593,13 +594,6 @@
     flush_ = true;
   }
 
-  // If current draw cycle has different set of layers updating in comparison to previous cycle,
-  // cache content using GPU again.
-  // If set of updating layers remains same, use cached buffer and replace layers marked for GPU
-  // composition with SDE so that SurfaceFlinger does not compose them. Set cache inuse here.
-  bool needs_fb_refresh = NeedsFrameBufferRefresh(content_list);
-  layer_stack_cache_.in_use = false;
-
   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.at(i);
@@ -609,16 +603,9 @@
         (composition == kCompositionBlit)) {
       hwc_layer.hints |= HWC_HINT_CLEAR_FB;
     }
-
-    if (!needs_fb_refresh && composition == kCompositionGPU) {
-      composition = kCompositionSDE;
-      layer_stack_cache_.in_use = true;
-    }
     SetComposition(composition, &hwc_layer.compositionType);
   }
 
-  CacheLayerStackInfo(content_list);
-
   return 0;
 }
 
@@ -712,7 +699,7 @@
       // framebuffer layer throughout animation and do not allow framework to do eglswapbuffer on
       // framebuffer target. So graphics doesn't close the release fence fd of framebuffer target,
       // Hence close the release fencefd of framebuffer target here.
-      if (layer->composition == kCompositionGPUTarget && layer_stack_cache_.animating) {
+      if (layer->composition == kCompositionGPUTarget && animating_) {
         close(hwc_layer.releaseFenceFd);
         hwc_layer.releaseFenceFd = -1;
       }
@@ -725,8 +712,7 @@
   }
 
   if (!flush_) {
-    layer_stack_cache_.animating = layer_stack_.flags.animating;
-
+    animating_ = layer_stack_.flags.animating;
     // if swapinterval property is set to 0 then close and reset the list retire fence
     if (swap_interval_zero_) {
       close(layer_stack_.retire_fence_fd);
@@ -745,98 +731,13 @@
   return status;
 }
 
-
-bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) {
-  uint32_t num_hw_layers = UINT32(content_list->numHwLayers);
-
-  // Handle ongoing animation and end here, start is handled below
-  if (layer_stack_cache_.animating) {
-      if (!layer_stack_.flags.animating) {
-        // Animation is ending.
-        return true;
-      } else {
-        // Animation is going on.
-        return false;
-      }
-  }
-
-  // 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_.flags.skip_present || layer_stack_.flags.geometry_changed) {
-    return true;
-  }
-
-  for (uint32_t i = 0; i < num_hw_layers; i++) {
-    Layer *layer = layer_stack_.layers.at(i);
-    LayerCache &layer_cache = layer_stack_cache_.layer_cache[i];
-
-    // need FB refresh for s3d case
-    if (layer->input_buffer->s3d_format != kS3dFormatNone) {
-        return true;
-    }
-
-    if (layer->composition == kCompositionGPUTarget ||
-        layer->composition == kCompositionBlitTarget) {
-      continue;
-    }
-
-    if (layer_cache.composition != layer->composition) {
-      return true;
-    }
-
-    if ((layer->composition == kCompositionGPU) && IsLayerUpdating(content_list, INT32(i))) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-bool HWCDisplay::IsLayerUpdating(hwc_display_contents_1_t *content_list, int layer_index) {
-  hwc_layer_1_t &hwc_layer = content_list->hwLayers[layer_index];
-  LayerCache &layer_cache = layer_stack_cache_.layer_cache[layer_index];
-
-  const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
-  const MetaData_t *meta_data = pvt_handle ?
-    reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata) : NULL;
-
+bool HWCDisplay::IsLayerUpdating(hwc_display_contents_1_t *content_list, const Layer *layer) {
   // Layer should be considered updating if
   //   a) layer is in single buffer mode, or
-  //   b) layer handle has changed, or
-  //   c) layer plane alpha has changed, or
-  //   d) layer stack geometry has changed
-  return ((meta_data && (meta_data->operation & SET_SINGLE_BUFFER_MODE) &&
-              meta_data->isSingleBufferMode) ||
-          (layer_cache.handle != hwc_layer.handle) ||
-          (layer_cache.plane_alpha != hwc_layer.planeAlpha) ||
-          (content_list->flags & HWC_GEOMETRY_CHANGED));
-}
-
-void HWCDisplay::CacheLayerStackInfo(hwc_display_contents_1_t *content_list) {
-  uint32_t layer_count = UINT32(layer_stack_.layers.size());
-
-  if (layer_count > kMaxLayerCount || layer_stack_.flags.animating) {
-    ResetLayerCacheStack();
-    return;
-  }
-
-  for (uint32_t i = 0; i < layer_count; i++) {
-    Layer *layer = layer_stack_.layers.at(i);
-    if (layer->composition == kCompositionGPUTarget ||
-        layer->composition == kCompositionBlitTarget) {
-      continue;
-    }
-
-    LayerCache &layer_cache = layer_stack_cache_.layer_cache[i];
-    layer_cache.handle = content_list->hwLayers[i].handle;
-    layer_cache.plane_alpha = content_list->hwLayers[i].planeAlpha;
-    layer_cache.composition = layer->composition;
-  }
-
-  layer_stack_cache_.layer_count = layer_count;
+  //   b) valid dirty_regions(android specific hint for updating status), or
+  //   c) layer stack geometry has changed
+  return (layer->flags.single_buffer || IsSurfaceUpdated(layer->dirty_regions) ||
+         (layer_stack_.flags.geometry_changed));
 }
 
 void HWCDisplay::SetRect(const hwc_rect_t &source, LayerRect *target) {
@@ -1447,16 +1348,6 @@
   return 0;
 }
 
-void HWCDisplay::ResetLayerCacheStack() {
-  uint32_t layer_count = layer_stack_cache_.layer_count;
-  for (uint32_t i = 0; i < layer_count; i++) {
-    layer_stack_cache_.layer_cache[i] = LayerCache();
-  }
-  layer_stack_cache_.layer_count = 0;
-  layer_stack_cache_.animating = false;
-  layer_stack_cache_.in_use = false;
-}
-
 void HWCDisplay::SetSecureDisplay(bool secure_display_active) {
   secure_display_active_ = secure_display_active;
   return;
@@ -1478,6 +1369,8 @@
   return display_intf_->GetConfig(UINT32(config), attributes) == kErrorNone ? 0 : -1;
 }
 
+// TODO(user): HWC needs to know updating for dyn_fps, cpu hint features,
+// once the features are moved to SDM, the two functions below can be removed.
 bool HWCDisplay::SingleLayerUpdating(uint32_t app_layer_count) {
   uint32_t updating_count = 0;
 
@@ -1548,4 +1441,12 @@
   }
 }
 
+bool HWCDisplay::IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions) {
+  // based on dirty_regions determine if its updating
+  // dirty_rect count = 0 - whole layer - updating.
+  // dirty_rect count = 1 or more valid rects - updating.
+  // dirty_rect count = 1 with (0,0,0,0) - not updating.
+  return (dirty_regions.empty() || IsValid(dirty_regions.at(0)));
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index 17db165..8bc7a91 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -31,6 +31,7 @@
 #include <QService.h>
 #include <private/color_params.h>
 #include <map>
+#include <vector>
 
 namespace sdm {
 
@@ -117,23 +118,6 @@
   // Maximum number of layers supported by display manager.
   static const uint32_t kMaxLayerCount = 32;
 
-  struct LayerCache {
-    buffer_handle_t handle;
-    uint8_t plane_alpha;
-    LayerComposition composition;
-
-    LayerCache() : handle(NULL), plane_alpha(0xff), composition(kCompositionGPU) { }
-  };
-
-  struct LayerStackCache {
-    LayerCache layer_cache[kMaxLayerCount];
-    uint32_t layer_count;
-    bool animating;
-    bool in_use;
-
-    LayerStackCache() : layer_count(0), animating(false), in_use(false) { }
-  };
-
   HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type, int id,
              bool needs_blit, qService::QService *qservice, DisplayClass display_class);
 
@@ -168,10 +152,10 @@
   DisplayError SetIGC(IGC_t source, LayerIGC *target);
   DisplayError SetMetaData(const private_handle_t *pvt_handle, Layer *layer);
   bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
-  void CacheLayerStackInfo(hwc_display_contents_1_t *content_list);
-  bool IsLayerUpdating(hwc_display_contents_1_t *content_list, int layer_index);
+  bool IsLayerUpdating(hwc_display_contents_1_t *content_list, const Layer *layer);
   bool SingleLayerUpdating(uint32_t app_layer_count);
   bool SingleVideoLayerUpdating(uint32_t app_layer_count);
+  bool IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions);
 
   enum {
     INPUT_LAYER_DUMP,
@@ -185,7 +169,6 @@
   bool needs_blit_ = false;
   DisplayInterface *display_intf_ = NULL;
   LayerStack layer_stack_;
-  LayerStackCache layer_stack_cache_;
   bool flush_on_error_ = false;
   bool flush_ = false;
   uint32_t dump_frame_count_ = 0;
@@ -210,13 +193,13 @@
   uint32_t solid_fill_color_ = 0;
   LayerRect display_rect_;
   std::map<int, LayerBufferS3DFormat> s3d_format_hwc_to_sdm_;
+  bool animating_ = false;
 
  private:
   bool IsFrameBufferScaled();
   void DumpInputBuffers(hwc_display_contents_1_t *content_list);
   int PrepareLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer);
   void CommitLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer);
-  void ResetLayerCacheStack();
   BlitEngine *blit_engine_ = NULL;
   qService::QService *qservice_ = NULL;
   DisplayClass display_class_;