sdm: Configure RMFB delay based on whether it is refcounted

Configure RMFB delay based on whether it is refcounted. If it is,
fb_id should be released immediately from userspace and driver will
free it when its usage is over. If not refcounted userspace needs
to defer freeing fb_id until a time where driver usage will be over.

Change-Id: I162723a5426c7e7c041d444ba50a73475858e96f
CRs-fixed: 1114808
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/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 9e99361..ff25295 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -216,6 +216,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());
@@ -276,7 +297,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;
@@ -290,7 +311,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 bbdd69d..c602bb6 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -128,7 +128,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
@@ -141,10 +142,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_ = {};
   };