sdm: Avoid fb_id creation and removal in each frame
- Cache the <handle_id, fb_id> map in SDM layer.
- Registry finds the handle_id in layer map. If it is found, then
mapped fb_id is programmed to DRM driver. Else fb_id is created
and it is added in map for the given handle_id key. This map is
cleared and fb_ids are removed, when the SDM layer gets deleted.
- "vendor.display.disable_fbid_cache" system prop needs to be set
to disable the fb_id caching in SDM. So, fb_id will be removed
and created for each SDM layer in every draw cycle.
CRs-Fixed: 2235202
Change-Id: I1d6c7fbc1fc5c1f9afad36cf49f17bc8c5322fe5
diff --git a/include/display_properties.h b/include/display_properties.h
index 505235f..799eade 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -94,6 +94,7 @@
#define DISABLE_EXCL_RECT_PROP DISPLAY_PROP("disable_excl_rect")
#define ENABLE_PIPE_PRIORITY_PROP DISPLAY_PROP("enable_pipe_priority")
#define DISABLE_EXCl_RECT_PARTIAL_FB DISPLAY_PROP("disable_excl_rect_partial_fb")
+#define DISABLE_FBID_CACHE DISPLAY_PROP("disable_fbid_cache")
#define DISABLE_HDR_LUT_GEN DISPLAY_PROP("disable_hdr_lut_gen")
#define ENABLE_DEFAULT_COLOR_MODE DISPLAY_PROP("enable_default_color_mode")
diff --git a/sdm/include/core/buffer_allocator.h b/sdm/include/core/buffer_allocator.h
index e0c7136..a6a3cac 100644
--- a/sdm/include/core/buffer_allocator.h
+++ b/sdm/include/core/buffer_allocator.h
@@ -70,6 +70,7 @@
uint32_t aligned_height = 0; //!< Specifies aligned allocated buffer height in pixels.
LayerBufferFormat format = kFormatInvalid; // Specifies buffer format for allocated buffer.
uint32_t size = 0; //!< Specifies the size of the allocated buffer.
+ uint64_t id = 0; //!< Specifies the Id of the allocated buffer.
};
/*! @brief Holds the information about the input/output configuration of an output buffer.
diff --git a/sdm/include/core/layer_buffer.h b/sdm/include/core/layer_buffer.h
index 8f7f6fe..b5f1701 100644
--- a/sdm/include/core/layer_buffer.h
+++ b/sdm/include/core/layer_buffer.h
@@ -286,6 +286,8 @@
color_metadata.colorPrimaries = ColorPrimaries_BT709_5;
color_metadata.transfer = Transfer_sRGB;
}
+
+ uint64_t handle_id = 0;
};
// This enum represents buffer layout types.
@@ -295,6 +297,11 @@
kTPTiled //!< Tightly Packed data
};
+class LayerBufferObject {
+ public:
+ virtual ~LayerBufferObject() {}
+};
+
} // namespace sdm
#endif // __LAYER_BUFFER_H__
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index f85a337..699cb8b 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -36,6 +36,8 @@
#include <vector>
#include <utility>
+#include <unordered_map>
+#include <memory>
#include "layer_buffer.h"
#include "sdm_types.h"
@@ -310,6 +312,10 @@
uint32_t alpha = 0; //!< Alpha value
};
+struct LayerBufferMap {
+ std::unordered_map<uint64_t, std::shared_ptr<LayerBufferObject>> buffer_map;
+};
+
/*! @brief This structure defines display layer object which contains layer properties and a drawing
buffer.
@@ -382,6 +388,7 @@
Lut3d lut_3d = {}; //!< o/p - Populated by SDM when tone mapping is
//!< needed on this layer.
LayerSolidFill solid_fill_info = {}; //!< solid fill info along with depth.
+ std::shared_ptr<LayerBufferMap> buffer_map = nullptr; //!< Map of handle_id and fb_id.
};
/*! @brief This structure defines the color space + transfer of a given layer.
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 0554b4f..5b61523 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -177,6 +177,9 @@
hw_layers_info.stack = layer_stack;
for (auto &layer : layers) {
+ if (layer->buffer_map == nullptr) {
+ layer->buffer_map = std::make_shared<LayerBufferMap>();
+ }
if (layer->composition == kCompositionGPUTarget) {
hw_layers_info.gpu_target_index = hw_layers_info.app_layer_count;
break;
@@ -1403,6 +1406,7 @@
hw_layer.input_buffer.planes[0].stride = sdm_layer->input_buffer.planes[0].stride;
hw_layer.input_buffer.size = sdm_layer->input_buffer.size;
hw_layer.input_buffer.acquire_fence_fd = sdm_layer->input_buffer.acquire_fence_fd;
+ hw_layer.input_buffer.handle_id = sdm_layer->input_buffer.handle_id;
}
return;
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index c094681..3be82e1 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -258,25 +258,31 @@
}
}
-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;
+class FrameBufferObject : public LayerBufferObject {
+ public:
+ explicit FrameBufferObject(uint32_t fb_id) : fb_id_(fb_id) {
}
- // 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_];
-}
+ ~FrameBufferObject() {
+ DRMMaster *master;
+ DRMMaster::GetInstance(&master);
+ int ret = master->RemoveFbId(fb_id_);
+ if (ret < 0) {
+ DLOGE("Removing fb_id %d failed with error %d", fb_id_, errno);
+ }
+ }
+ uint32_t GetFbId() { return fb_id_; }
-HWDeviceDRM::Registry::~Registry() {
- delete [] hashmap_;
+ private:
+ uint32_t fb_id_;
+};
+
+HWDeviceDRM::Registry::Registry(BufferAllocator *buffer_allocator) :
+ buffer_allocator_(buffer_allocator) {
+ int value = 0;
+ if (Debug::GetProperty(DISABLE_FBID_CACHE, &value) == kErrorNone) {
+ disable_fbid_cache_ = (value == 1);
+ }
}
void HWDeviceDRM::Registry::Register(HWLayers *hw_layers) {
@@ -293,84 +299,111 @@
input_buffer = &hw_rotator_session->output_buffer;
}
- MapBufferToFbId(input_buffer);
+ // layer input buffer map to fb id also applies for inline rot
+ MapBufferToFbId(&layer, input_buffer);
if (hw_rotator_session->mode == kRotatorInline && hw_rotate_info->valid &&
hw_rotator_session->output_buffer.planes[0].fd >= 0) {
- MapBufferToFbId(&hw_rotator_session->output_buffer);
+ MapBufferToFbId(&layer, &hw_rotator_session->output_buffer);
}
}
}
-void HWDeviceDRM::Registry::MapBufferToFbId(LayerBuffer* buffer) {
- int fd = buffer->planes[0].fd;
+int HWDeviceDRM::Registry::CreateFbId(LayerBuffer *buffer, uint32_t *fb_id) {
DRMMaster *master = nullptr;
DRMMaster::GetInstance(&master);
+ int ret = -1;
if (!master) {
DLOGE("Failed to acquire DRM Master instance");
+ return ret;
+ }
+
+ DRMBuffer layout{};
+ AllocatedBufferInfo buf_info{};
+ buf_info.fd = layout.fd = buffer->planes[0].fd;
+ buf_info.aligned_width = layout.width = buffer->width;
+ buf_info.aligned_height = layout.height = buffer->height;
+ buf_info.format = buffer->format;
+ GetDRMFormat(buf_info.format, &layout.drm_format, &layout.drm_format_modifier);
+ buffer_allocator_->GetBufferLayout(buf_info, layout.stride, layout.offset, &layout.num_planes);
+ ret = master->CreateFbId(layout, fb_id);
+ if (ret < 0) {
+ DLOGE("CreateFbId failed. width %d, height %d, format: %s, stride %u, error %d",
+ layout.width, layout.height, GetFormatString(buf_info.format), layout.stride[0], errno);
+ }
+
+ return ret;
+}
+
+void HWDeviceDRM::Registry::MapBufferToFbId(Layer* layer, LayerBuffer* buffer) {
+ if (buffer->planes[0].fd < 0) {
return;
}
- if (fd >= 0 && hashmap_[current_index_].find(fd) == hashmap_[current_index_].end()) {
- AllocatedBufferInfo buf_info{};
- DRMBuffer layout{};
- buf_info.fd = layout.fd = fd;
- buf_info.aligned_width = layout.width = buffer->width;
- buf_info.aligned_height = layout.height = buffer->height;
- buf_info.format = buffer->format;
- GetDRMFormat(buf_info.format, &layout.drm_format, &layout.drm_format_modifier);
- buffer_allocator_->GetBufferLayout(buf_info, layout.stride, layout.offset,
- &layout.num_planes);
- uint32_t fb_id = 0;
- int ret = master->CreateFbId(layout, &fb_id);
- if (ret < 0) {
- DLOGE("CreateFbId failed. width %d, height %d, format: %s, stride %u, error %d",
- layout.width, layout.height, GetFormatString(buf_info.format), layout.stride[0],
- errno);
- } else {
- hashmap_[current_index_][fd] = fb_id;
- }
+ uint64_t handle_id = buffer->handle_id;
+
+ if (!handle_id || disable_fbid_cache_) {
+ // Legacy: Remove & Create fb_id in each frame
+ layer->buffer_map->buffer_map.clear();
}
- return;
-}
-void HWDeviceDRM::Registry::Next() {
- current_index_ = (current_index_ + 1) % rmfb_delay_;
-}
-
-void HWDeviceDRM::Registry::Unregister() {
- DRMMaster *master = nullptr;
- DRMMaster::GetInstance(&master);
-
- if (!master) {
- DLOGE("Failed to acquire DRM Master instance");
+ if (layer->buffer_map->buffer_map.find(handle_id) != layer->buffer_map->buffer_map.end()) {
+ // Found fb_id for given handle_id key
return;
}
- auto &curr_map = hashmap_[current_index_];
- for (auto &pair : curr_map) {
- uint32_t fb_id = pair.second;
- int ret = master->RemoveFbId(fb_id);
- if (ret < 0) {
- DLOGE("Removing fb_id %d failed with error %d", fb_id, errno);
- }
+ uint32_t fb_id = 0;
+ if (CreateFbId(buffer, &fb_id) >= 0) {
+ // Create and cache the fb_id in map
+ layer->buffer_map->buffer_map[handle_id] = std::make_shared<FrameBufferObject>(fb_id);
+ }
+}
+
+void HWDeviceDRM::Registry::MapOutputBufferToFbId(LayerBuffer *output_buffer) {
+ if (output_buffer->planes[0].fd < 0) {
+ return;
}
- curr_map.clear();
+ uint64_t handle_id = output_buffer->handle_id;
+
+ if (!handle_id || disable_fbid_cache_) {
+ // Legacy: Remove & Create fb_id in each frame
+ output_buffer_map_.clear();
+ }
+
+ if (output_buffer_map_.find(handle_id) != output_buffer_map_.end()) {
+ return;
+ }
+
+ uint32_t fb_id = 0;
+ if (CreateFbId(output_buffer, &fb_id) >= 0) {
+ output_buffer_map_[handle_id] = std::make_shared<FrameBufferObject>(fb_id);
+ }
}
void HWDeviceDRM::Registry::Clear() {
- for (int i = 0; i < rmfb_delay_; i++) {
- Unregister();
- Next();
- }
- current_index_ = 0;
+ output_buffer_map_.clear();
}
-uint32_t HWDeviceDRM::Registry::GetFbId(int fd) {
- auto it = hashmap_[current_index_].find(fd);
- return (it == hashmap_[current_index_].end()) ? 0 : it->second;
+uint32_t HWDeviceDRM::Registry::GetFbId(Layer *layer, uint64_t handle_id) {
+ auto it = layer->buffer_map->buffer_map.find(handle_id);
+ if (it != layer->buffer_map->buffer_map.end()) {
+ FrameBufferObject *fb_obj = static_cast<FrameBufferObject*>(it->second.get());
+ return fb_obj->GetFbId();
+ }
+
+ return 0;
+}
+
+uint32_t HWDeviceDRM::Registry::GetOutputFbId(uint64_t handle_id) {
+ auto it = output_buffer_map_.find(handle_id);
+ if (it != output_buffer_map_.end()) {
+ FrameBufferObject *fb_obj = static_cast<FrameBufferObject*>(it->second.get());
+ return fb_obj->GetFbId();
+ }
+
+ return 0;
}
HWDeviceDRM::HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator,
@@ -938,7 +971,8 @@
input_buffer = &hw_rotator_session->output_buffer;
}
- uint32_t fb_id = registry_.GetFbId(input_buffer->planes[0].fd);
+ uint32_t fb_id = registry_.GetFbId(&layer, input_buffer->handle_id);
+
if (pipe_info->valid && fb_id) {
uint32_t pipe_id = pipe_info->pipe_id;
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ALPHA, pipe_id, layer.plane_alpha);
@@ -955,7 +989,8 @@
SetRect(hw_rotate_info->dst_roi, &rot_dst);
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION_DST_RECT, pipe_id, rot_dst);
if (hw_rotator_session->output_buffer.planes[0].fd >= 0) {
- uint32_t rot_fb_id = registry_.GetFbId(hw_rotator_session->output_buffer.planes[0].fd);
+ uint32_t rot_fb_id = registry_.GetFbId(&layer,
+ hw_rotator_session->output_buffer.handle_id);
if (rot_fb_id) {
drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROT_FB_ID, pipe_id, rot_fb_id);
}
@@ -1125,7 +1160,6 @@
err = kErrorHardware;
}
- registry_.Unregister();
return err;
}
@@ -1141,9 +1175,6 @@
err = AtomicCommit(hw_layers);
}
- registry_.Next();
- registry_.Unregister();
-
return err;
}
@@ -1184,7 +1215,8 @@
drmModeModeInfo mode;
res_mgr->GetMode(&mode);
- uint32_t fb_id = registry_.GetFbId(hw_layer_info.hw_layers.at(0).input_buffer.planes[0].fd);
+ uint64_t handle_id = hw_layer_info.hw_layers.at(0).input_buffer.handle_id;
+ uint32_t fb_id = registry_.GetFbId(&hw_layer_info.hw_layers.at(0), handle_id);
ret = drmModeSetCrtc(dev_fd, crtc_id, fb_id, 0 /* x */, 0 /* y */, &connector_id,
1 /* num_connectors */, &mode);
if (ret < 0) {
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 718cc15..fe7b669 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -154,27 +154,24 @@
class Registry {
public:
explicit Registry(BufferAllocator *buffer_allocator);
- ~Registry();
- // Called on each Validate and Commit to register layer buffers fds to the slot pointed to by
- // current_index_
+ // Called on each Validate and Commit to map the handle_id to fb_id of each layer buffer.
void Register(HWLayers *hw_layers);
- // Clears the slot pointed to by current_index_
- void Unregister();
- // Moves current_index_ to the next position
- void Next();
- // Called on display disconnect to release all gem handles and fb_ids
+ // Called on display disconnect to clear output buffer map and remove fb_ids.
void Clear();
- // Maps given fd to FB ID
- void MapBufferToFbId(LayerBuffer* buffer);
- // Finds an fb_id corresponding to an fd in current map
- uint32_t GetFbId(int fd);
+ // Create the fd_id for the given buffer.
+ int CreateFbId(LayerBuffer *buffer, uint32_t *fb_id);
+ // Find handle_id in the layer map. Else create fb_id and add <handle_id,fb_id> in map.
+ void MapBufferToFbId(Layer* layer, LayerBuffer* buffer);
+ // Find handle_id in output buffer map. Else create fb_id and add <handle_id,fb_id> in map.
+ void MapOutputBufferToFbId(LayerBuffer* buffer);
+ // Find fb_id for given handle_id in the layer map.
+ uint32_t GetFbId(Layer *layer, uint64_t handle_id);
+ // Find fb_id for given handle_id in output buffer map.
+ uint32_t GetOutputFbId(uint64_t handle_id);
private:
- 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_ {};
- int current_index_ = 0;
+ bool disable_fbid_cache_ = false;
+ std::unordered_map<uint64_t, std::shared_ptr<LayerBufferObject>> output_buffer_map_ {};
BufferAllocator *buffer_allocator_ = {};
};
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index 340dc05..bac56ba 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -270,7 +270,7 @@
void HWPeripheralDRM::ConfigureConcurrentWriteback(LayerStack *layer_stack) {
LayerBuffer *output_buffer = layer_stack->output_buffer;
- registry_.MapBufferToFbId(output_buffer);
+ registry_.MapOutputBufferToFbId(output_buffer);
// Set the topology for Concurrent Writeback: [CRTC_PRIMARY_DISPLAY - CONNECTOR_VIRTUAL_DISPLAY].
drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, cwb_config_.token.conn_id, token_.crtc_id);
@@ -281,7 +281,7 @@
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CAPTURE_MODE, token_.crtc_id, capture_mode);
// Set Connector Output FB
- uint32_t fb_id = registry_.GetFbId(output_buffer->planes[0].fd);
+ uint32_t fb_id = registry_.GetOutputFbId(output_buffer->handle_id);
drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_FB_ID, cwb_config_.token.conn_id, fb_id);
// Set Connector Secure Mode
diff --git a/sdm/libs/core/drm/hw_virtual_drm.cpp b/sdm/libs/core/drm/hw_virtual_drm.cpp
index 20d27f9..a9c1c29 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.cpp
+++ b/sdm/libs/core/drm/hw_virtual_drm.cpp
@@ -126,8 +126,8 @@
DisplayError err = kErrorNone;
registry_.Register(hw_layers);
- registry_.MapBufferToFbId(output_buffer);
- uint32_t fb_id = registry_.GetFbId(output_buffer->planes[0].fd);
+ registry_.MapOutputBufferToFbId(output_buffer);
+ uint32_t fb_id = registry_.GetOutputFbId(output_buffer->handle_id);
ConfigureWbConnectorFbId(fb_id);
ConfigureWbConnectorDestRect();
@@ -138,17 +138,14 @@
DLOGE("Atomic commit failed for crtc_id %d conn_id %d", token_.crtc_id, token_.conn_id);
}
- registry_.Next();
- registry_.Unregister();
-
return(err);
}
DisplayError HWVirtualDRM::Validate(HWLayers *hw_layers) {
LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
- registry_.MapBufferToFbId(output_buffer);
- uint32_t fb_id = registry_.GetFbId(output_buffer->planes[0].fd);
+ registry_.MapOutputBufferToFbId(output_buffer);
+ uint32_t fb_id = registry_.GetOutputFbId(output_buffer->handle_id);
ConfigureWbConnectorFbId(fb_id);
ConfigureWbConnectorDestRect();
diff --git a/sdm/libs/hwc2/hwc_buffer_allocator.cpp b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
index c879e94..34db732 100644
--- a/sdm/libs/hwc2/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
@@ -144,6 +144,7 @@
alloc_buffer_info->aligned_width = UINT32(hnd->width);
alloc_buffer_info->aligned_height = UINT32(hnd->height);
alloc_buffer_info->size = hnd->size;
+ alloc_buffer_info->id = hnd->id;
buffer_info->private_data = reinterpret_cast<void *>(hnd);
return kErrorNone;
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index a645169..7aac16f 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -299,6 +299,7 @@
layer_buffer->planes[0].stride = UINT32(handle->width);
layer_buffer->size = handle->size;
layer_buffer->buffer_id = reinterpret_cast<uint64_t>(handle);
+ layer_buffer->handle_id = handle->id;
return HWC2::Error::None;
}