Merge "sdm: Avoid duplicate BW config on crtc"
diff --git a/libdrmutils/drm_master.cpp b/libdrmutils/drm_master.cpp
index 09e0729..ff7770b 100644
--- a/libdrmutils/drm_master.cpp
+++ b/libdrmutils/drm_master.cpp
@@ -146,4 +146,11 @@
   return ret;
 }
 
+bool DRMMaster::IsRmFbRefCounted() {
+#ifdef DRM_IOCTL_MSM_RMFB2
+  return true;
+#endif
+  return false;
+}
+
 }  // namespace drm_utils
diff --git a/libdrmutils/drm_master.h b/libdrmutils/drm_master.h
index 52a8b02..18f51eb 100644
--- a/libdrmutils/drm_master.h
+++ b/libdrmutils/drm_master.h
@@ -71,6 +71,8 @@
    *   fd: Pointer to store master fd into
    */
   void GetHandle(int *fd) { *fd = dev_fd_; }
+  /* Returns true if the ref counted version of rmfb is being used */
+  bool IsRmFbRefCounted();
 
   /* Creates an instance of DRMMaster if it doesn't exist and initializes it. Threadsafe.
    * Input:
diff --git a/libgralloc1/gr_allocator.cpp b/libgralloc1/gr_allocator.cpp
index ee311f5..175603e 100644
--- a/libgralloc1/gr_allocator.cpp
+++ b/libgralloc1/gr_allocator.cpp
@@ -194,7 +194,11 @@
   if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
       format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
     if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_ALLOC_UBWC) {
-      gr_format = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+      if (prod_usage & GRALLOC1_PRODUCER_USAGE_PRIVATE_10BIT_TP) {
+        gr_format = HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC;
+      } else {
+        gr_format = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+      }
     } else if (cons_usage & GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER) {
       gr_format = HAL_PIXEL_FORMAT_NV12_ENCODEABLE;  // NV12
     } else if (cons_usage & GRALLOC1_CONSUMER_USAGE_CAMERA) {
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index 230aa4f..5390fee 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -404,14 +404,6 @@
 int BufferManager::GetHandleFlags(int format, gralloc1_producer_usage_t prod_usage,
                                   gralloc1_consumer_usage_t cons_usage) {
   int flags = 0;
-  if (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_EXTERNAL_ONLY) {
-    flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
-  }
-
-  if (cons_usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_INTERNAL_ONLY) {
-    flags |= private_handle_t::PRIV_FLAGS_INTERNAL_ONLY;
-  }
-
   if (cons_usage & GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER) {
     flags |= private_handle_t::PRIV_FLAGS_VIDEO_ENCODER;
   }
diff --git a/libgralloc1/gralloc_priv.h b/libgralloc1/gralloc_priv.h
index 1839d2f..d8dfbf3 100644
--- a/libgralloc1/gralloc_priv.h
+++ b/libgralloc1/gralloc_priv.h
@@ -54,6 +54,10 @@
 /* Use legacy ZSL definition until we know the correct usage on gralloc1 */
 #define GRALLOC1_PRODUCER_USAGE_PRIVATE_CAMERA_ZSL  GRALLOC_USAGE_HW_CAMERA_ZSL
 
+/* TODO(user): move these to use producer private bits once 64-bit support available */
+/* This flag is used to indicate 10-bit tight pack format (e.g. TP10) */
+#define GRALLOC1_PRODUCER_USAGE_PRIVATE_10BIT_TP  0x08000000
+
 
 /* Consumer flags */
 /* TODO(user): Fix when producer and consumer flags are actually separated */
@@ -63,11 +67,8 @@
 /* This flag is used for SECURE display usecase */
 #define GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY 0x00800000
 
-/* Buffer content should be displayed on a primary display only */
-#define GRALLOC1_CONSUMER_USAGE_PRIVATE_INTERNAL_ONLY  0x04000000
-
-/* Buffer content should be displayed on an external display only */
-#define GRALLOC1_CONSUMER_USAGE_PRIVATE_EXTERNAL_ONLY  0x08000000
+/* Unused flag */
+#define GRALLOC1_USAGE_PRIVATE_UNUSED1  0x04000000
 
 
 /* Legacy gralloc0.x definitions */
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index e5a4826..0837c99 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -120,11 +120,19 @@
         case SET_VT_TIMESTAMP:
             data->vtTimeStamp = *((uint64_t *)param);
             break;
-#ifdef USE_COLOR_METADATA
         case COLOR_METADATA:
+#ifdef USE_COLOR_METADATA
             data->color = *((ColorMetaData *)param);
 #endif
             break;
+        case SET_UBWC_CR_STATS_INFO: {
+             struct UBWCStats* stats = (struct UBWCStats*)param;
+             int numelems = sizeof(data->ubwcCRStats) / sizeof(struct UBWCStats);
+             for (int i = 0; i < numelems; i++) {
+                  data->ubwcCRStats[i] = stats[i];
+             }
+              break;
+          }
         default:
             ALOGE("Unknown paramType %d", paramType);
             break;
@@ -171,6 +179,8 @@
     int ret = -EINVAL;
     if (data == nullptr)
         return ret;
+    if (param == nullptr)
+        return ret;
 
     switch (paramType) {
         case GET_PP_PARAM_INTERLACED:
@@ -239,14 +249,24 @@
                 ret = 0;
             }
             break;
-#ifdef USE_COLOR_METADATA
         case GET_COLOR_METADATA:
+#ifdef USE_COLOR_METADATA
             if (data->operation & COLOR_METADATA) {
                 *((ColorMetaData *)param) = data->color;
                 ret = 0;
             }
 #endif
             break;
+        case GET_UBWC_CR_STATS_INFO:
+            if (data->operation & SET_UBWC_CR_STATS_INFO) {
+                struct UBWCStats* stats = (struct UBWCStats*)param;
+                int numelems = sizeof(data->ubwcCRStats) / sizeof(struct UBWCStats);
+                for (int i = 0; i < numelems; i++) {
+                    stats[i] = data->ubwcCRStats[i];
+                }
+                ret = 0;
+            }
+            break;
         default:
             ALOGE("Unknown paramType %d", paramType);
             break;
diff --git a/sdm/include/core/layer_buffer.h b/sdm/include/core/layer_buffer.h
index c86e020..c0e3305 100644
--- a/sdm/include/core/layer_buffer.h
+++ b/sdm/include/core/layer_buffer.h
@@ -31,11 +31,16 @@
 
 #include <stdint.h>
 #include <color_metadata.h>
+#include <utility>
+#include <vector>
 
 #include "sdm_types.h"
 
 namespace sdm {
 
+#define NUM_UBWC_CR_STATS_LAYERS 2
+typedef std::vector<std::pair<int, int>> UbwcCrStatsVector;
+
 /*! @brief This enum represents display layer inverse gamma correction (IGC) types.
 
   @sa Layer
@@ -268,6 +273,9 @@
                                 //!< could be modified by both client and SDM.
   uint64_t buffer_id __attribute__((aligned(8))) = 0;
                                 //!< Specifies the buffer id.
+  UbwcCrStatsVector  ubwc_crstats[NUM_UBWC_CR_STATS_LAYERS] = {};
+                                //! < UBWC Compression ratio,stats. Stored as a vector of pair of
+                                //! of (tile size, #of tiles)
 };
 
 // This enum represents buffer layout types.
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index 6f895c7..2bd6a5a 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -79,6 +79,7 @@
   static bool IsExtAnimDisabled();
   static bool IsPartialSplitDisabled();
   static DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+  static DisplayError GetReducedConfig(uint32_t *num_vig_pipes, uint32_t *num_dma_pipes);
   static int GetExtMaxlayers();
   static bool GetProperty(const char *property_name, char *value);
   static bool SetProperty(const char *property_name, const char *value);
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 0274248..29ac44e 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -218,6 +218,27 @@
   }
 }
 
+HWDeviceDRM::Registry::Registry(BufferAllocator *buffer_allocator) :
+  buffer_allocator_(buffer_allocator) {
+  DRMMaster *master = nullptr;
+  DRMMaster::GetInstance(&master);
+
+  if (!master) {
+    DLOGE("Failed to acquire DRM Master instance");
+    return;
+  }
+
+  // If RMFB is ref-counted, we should immediately make a call to clean up fb_id after commit.
+  // Driver will release fb_id after its usage. Otherwise speculatively free up fb_id after 3
+  // cycles assuming driver is done with it.
+  rmfb_delay_ = master->IsRmFbRefCounted() ? 1 : 3;
+  hashmap_ = new std::unordered_map<int, uint32_t>[rmfb_delay_];
+}
+
+HWDeviceDRM::Registry::~Registry() {
+  delete [] hashmap_;
+}
+
 void HWDeviceDRM::Registry::RegisterCurrent(HWLayers *hw_layers) {
   HWLayersInfo &hw_layer_info = hw_layers->info;
   uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
@@ -278,7 +299,7 @@
     return;
   }
 
-  current_index_ = (current_index_ + 1) % kCycleDelay;
+  current_index_ = (current_index_ + 1) % rmfb_delay_;
   auto &curr_map = hashmap_[current_index_];
   for (auto &pair : curr_map) {
     uint32_t fb_id = pair.second;
@@ -292,7 +313,7 @@
 }
 
 void HWDeviceDRM::Registry::Clear() {
-  for (int i = 0; i < kCycleDelay; i++) {
+  for (int i = 0; i < rmfb_delay_; i++) {
     UnregisterNext();
   }
   current_index_ = 0;
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 99af9f4..e754cfa 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -130,7 +130,8 @@
 
   class Registry {
    public:
-    explicit Registry(BufferAllocator *buffer_allocator) : buffer_allocator_(buffer_allocator) {}
+    explicit Registry(BufferAllocator *buffer_allocator);
+    ~Registry();
     // Call on each validate and commit to register layer buffers
     void RegisterCurrent(HWLayers *hw_layers);
     // Call at the end of draw cycle to clear the next slot for business
@@ -143,10 +144,10 @@
     uint32_t GetFbId(int fd);
 
    private:
-    static const int kCycleDelay = 3;  // N cycle delay before destroy
+    uint8_t rmfb_delay_ = 1;  // N cycle delay before destroy
     // fd to fb_id map. fd is used as key only for a single draw cycle between
     // prepare and commit. It should not be used for caching in future due to fd recycling
-    std::unordered_map<int, uint32_t> hashmap_[kCycleDelay] {};
+    std::unordered_map<int, uint32_t> *hashmap_ {};
     int current_index_ = 0;
     BufferAllocator *buffer_allocator_ = {};
   };
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index ae21342..7b632e8 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -219,6 +219,7 @@
   DLOGI("\tLinear = %d", hw_resource->linear_factor);
   DLOGI("\tScale = %d", hw_resource->scale_factor);
   DLOGI("\tFudge_factor = %d", hw_resource->extra_fudge_factor);
+  DLOGI("\tib_fudge_factor = %d", hw_resource->ib_fudge_factor);
 
   if (hw_resource->separate_rotator || hw_resource->num_dma_pipe) {
     GetHWRotatorInfo(hw_resource);
@@ -288,7 +289,42 @@
 void HWInfoDRM::GetHWPlanesInfo(HWResourceInfo *hw_resource) {
   DRMPlanesInfo planes;
   drm_mgr_intf_->GetPlanesInfo(&planes);
+
+  // To simulate reduced config.
+  uint32_t max_vig_pipes = 0;
+  uint32_t max_dma_pipes = 0;
+  Debug::GetReducedConfig(&max_vig_pipes, &max_dma_pipes);
+  uint32_t max_virtual_pipes = max_vig_pipes + max_dma_pipes;
+  uint32_t vig_pipe_count = 0;
+  uint32_t dma_pipe_count = 0;
+  uint32_t virtual_pipe_count = 0;
+
   for (auto &pipe_obj : planes) {
+    if (max_vig_pipes && max_dma_pipes) {
+      uint32_t master_plane_id = pipe_obj.second.master_plane_id;
+      if ((pipe_obj.second.type == DRMPlaneType::DMA) && (dma_pipe_count < max_dma_pipes)
+          && !master_plane_id) {
+        dma_pipe_count++;
+      } else if ((pipe_obj.second.type == DRMPlaneType::VIG) && (vig_pipe_count < max_vig_pipes)
+          && !master_plane_id) {
+        vig_pipe_count++;
+      } else if ((master_plane_id) && (virtual_pipe_count < max_virtual_pipes)) {
+        bool is_virtual = false;
+        for (auto &pipe_caps : hw_resource->hw_pipes) {
+          if (master_plane_id == pipe_caps.id) {
+            is_virtual = true;
+            virtual_pipe_count++;
+            break;
+          }
+        }
+        if (!is_virtual) {
+          continue;
+        }
+      } else {
+        continue;
+      }
+    }
+
     HWPipeCaps pipe_caps;
     string name = {};
     switch (pipe_obj.second.type) {
@@ -323,7 +359,8 @@
     }
     pipe_caps.id = pipe_obj.first;
     pipe_caps.master_pipe_id = pipe_obj.second.master_plane_id;
-    DLOGI("Adding %s Pipe : Id %d", name.c_str(), pipe_obj.first);
+    DLOGI("Adding %s Pipe : Id %d, master_pipe_id : Id %d",
+          name.c_str(), pipe_obj.first, pipe_obj.second.master_plane_id);
     hw_resource->hw_pipes.push_back(std::move(pipe_caps));
   }
 }
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 0887fbe..6b0af2c 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -832,7 +832,7 @@
 
   client_target_->SetLayerBuffer(target, acquire_fence);
   client_target_->SetLayerSurfaceDamage(damage);
-  // Ignoring dataspace for now
+  client_target_->SetLayerDataspace(dataspace);
   return HWC2::Error::None;
 }
 
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 015dc75..f485ac6 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -18,6 +18,7 @@
  */
 
 #include <stdint.h>
+#include <utility>
 #include <qdMetaData.h>
 
 #include "hwc_layers.h"
@@ -549,6 +550,27 @@
   return sdm_s3d_format;
 }
 
+void HWCLayer::GetUBWCStatsFromMetaData(UBWCStats *cr_stats, UbwcCrStatsVector *cr_vec) {
+  // TODO(user): Check if we can use UBWCStats directly
+  // in layer_buffer or copy directly to Vector
+  if (cr_stats->bDataValid) {
+    switch (cr_stats->version) {
+      case UBWC_2_0:
+        cr_vec->push_back(std::make_pair(32, cr_stats->ubwc_stats.nCRStatsTile32));
+        cr_vec->push_back(std::make_pair(64, cr_stats->ubwc_stats.nCRStatsTile64));
+        cr_vec->push_back(std::make_pair(96, cr_stats->ubwc_stats.nCRStatsTile96));
+        cr_vec->push_back(std::make_pair(128, cr_stats->ubwc_stats.nCRStatsTile128));
+        cr_vec->push_back(std::make_pair(160, cr_stats->ubwc_stats.nCRStatsTile160));
+        cr_vec->push_back(std::make_pair(192, cr_stats->ubwc_stats.nCRStatsTile192));
+        cr_vec->push_back(std::make_pair(256, cr_stats->ubwc_stats.nCRStatsTile256));
+        break;
+      default:
+        DLOGW("Invalid UBWC Version %d", cr_stats->version);
+        break;
+    }  // switch(cr_stats->version)
+  }  // if (cr_stats->bDatvalid)
+}
+
 DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *layer) {
   LayerBuffer *layer_buffer = &layer->input_buffer;
   bool use_color_metadata = true;
@@ -592,6 +614,18 @@
     layer_buffer->s3d_format = GetS3DFormat(s3d);
   }
 
+  // Check if metadata is set
+  struct UBWCStats cr_stats[NUM_UBWC_CR_STATS_LAYERS] = {};
+
+  for (int i = 0; i < NUM_UBWC_CR_STATS_LAYERS; i++) {
+    layer_buffer->ubwc_crstats[i].clear();
+  }
+
+  if (getMetaData(handle, GET_UBWC_CR_STATS_INFO, cr_stats) == 0) {
+  // Only copy top layer for now as only top field for interlaced is used
+    GetUBWCStatsFromMetaData(&cr_stats[0], &(layer_buffer->ubwc_crstats[0]));
+  }  // if (getMetaData)
+
   return kErrorNone;
 }
 
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index b42699d..c566655 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -112,6 +112,7 @@
   uint32_t GetUint32Color(const hwc_color_t &source);
   LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
   LayerBufferS3DFormat GetS3DFormat(uint32_t s3d_format);
+  void GetUBWCStatsFromMetaData(UBWCStats *cr_stats, UbwcCrStatsVector *cr_vec);
   DisplayError SetMetaData(const private_handle_t *pvt_handle, Layer *layer);
   DisplayError SetIGC(IGC_t source, LayerIGC *target);
   uint32_t RoundToStandardFPS(float fps);
diff --git a/sdm/libs/utils/debug.cpp b/sdm/libs/utils/debug.cpp
index 95b4e3b..592be68 100644
--- a/sdm/libs/utils/debug.cpp
+++ b/sdm/libs/utils/debug.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2017, 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
@@ -190,6 +190,22 @@
   return kErrorNone;
 }
 
+DisplayError Debug::GetReducedConfig(uint32_t *num_vig_pipes, uint32_t *num_dma_pipes) {
+  char value[64] = {};
+
+  DisplayError error = debug_.debug_handler_->GetProperty("sdm.debug.reduced_config", value);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  std::string str(value);
+
+  *num_vig_pipes = UINT32(stoi(str));
+  *num_dma_pipes = UINT32(stoi(str.substr(str.find('x') + 1)));
+
+  return kErrorNone;
+}
+
 int Debug::GetExtMaxlayers() {
   int max_external_layers = 0;
   debug_.debug_handler_->GetProperty("sdm.max_external_layers", &max_external_layers);