From e1591472b9f413a88b87bcc4ea4972a1aeddbbf2 Mon Sep 17 00:00:00 2001 From: Sushil Chauhan Date: Wed, 2 May 2018 14:02:27 -0700 Subject: sdm: Avoid fb_id creation and removal in each frame - Cache the 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 --- sdm/libs/core/display_base.cpp | 4 + sdm/libs/core/drm/hw_device_drm.cpp | 168 +++++++++++++++++++------------- sdm/libs/core/drm/hw_device_drm.h | 31 +++--- sdm/libs/core/drm/hw_peripheral_drm.cpp | 4 +- sdm/libs/core/drm/hw_virtual_drm.cpp | 11 +-- 5 files changed, 123 insertions(+), 95 deletions(-) (limited to 'sdm/libs/core') diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp index a50dd944..0422b586 100644 --- a/sdm/libs/core/display_base.cpp +++ b/sdm/libs/core/display_base.cpp @@ -150,6 +150,9 @@ DisplayError DisplayBase::BuildLayerStackStats(LayerStack *layer_stack) { hw_layers_info.stack = layer_stack; for (auto &layer : layers) { + if (layer->buffer_map == nullptr) { + layer->buffer_map = std::make_shared(); + } if (layer->composition == kCompositionGPUTarget) { hw_layers_info.gpu_target_index = hw_layers_info.app_layer_count; break; @@ -1362,6 +1365,7 @@ void DisplayBase::CommitLayerParams(LayerStack *layer_stack) { 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 81237389..8c8faf3a 100644 --- a/sdm/libs/core/drm/hw_device_drm.cpp +++ b/sdm/libs/core/drm/hw_device_drm.cpp @@ -222,25 +222,31 @@ static void GetDRMFormat(LayerBufferFormat format, uint32_t *drm_format, } } -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: + 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[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_; } + + private: + uint32_t fb_id_; +}; -HWDeviceDRM::Registry::~Registry() { - delete [] hashmap_; +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) { @@ -257,79 +263,105 @@ void HWDeviceDRM::Registry::Register(HWLayers *hw_layers) { input_buffer = &hw_rotator_session->output_buffer; } - MapBufferToFbId(input_buffer); + MapBufferToFbId(&layer, input_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_; -} + if (layer->buffer_map->buffer_map.find(handle_id) != layer->buffer_map->buffer_map.end()) { + // Found fb_id for given handle_id key + return; + } -void HWDeviceDRM::Registry::Unregister() { - DRMMaster *master = nullptr; - DRMMaster::GetInstance(&master); + 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(fb_id); + } +} - if (!master) { - DLOGE("Failed to acquire DRM Master instance"); +void HWDeviceDRM::Registry::MapOutputBufferToFbId(LayerBuffer *output_buffer) { + if (output_buffer->planes[0].fd < 0) { 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); - } + 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; } - curr_map.clear(); + uint32_t fb_id = 0; + if (CreateFbId(output_buffer, &fb_id) >= 0) { + output_buffer_map_[handle_id] = std::make_shared(fb_id); + } } void HWDeviceDRM::Registry::Clear() { - for (int i = 0; i < rmfb_delay_; i++) { - Unregister(); - Next(); + output_buffer_map_.clear(); +} + +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(it->second.get()); + return fb_obj->GetFbId(); } - current_index_ = 0; + + return 0; } -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::GetOutputFbId(uint64_t handle_id) { + auto it = output_buffer_map_.find(handle_id); + if (it != output_buffer_map_.end()) { + FrameBufferObject *fb_obj = static_cast(it->second.get()); + return fb_obj->GetFbId(); + } + + return 0; } HWDeviceDRM::HWDeviceDRM(BufferSyncHandler *buffer_sync_handler, BufferAllocator *buffer_allocator, @@ -853,7 +885,8 @@ void HWDeviceDRM::SetupAtomic(HWLayers *hw_layers, bool validate) { 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); @@ -1020,7 +1053,6 @@ DisplayError HWDeviceDRM::Validate(HWLayers *hw_layers) { err = kErrorHardware; } - registry_.Unregister(); return err; } @@ -1036,9 +1068,6 @@ DisplayError HWDeviceDRM::Commit(HWLayers *hw_layers) { err = AtomicCommit(hw_layers); } - registry_.Next(); - registry_.Unregister(); - return err; } @@ -1079,7 +1108,8 @@ DisplayError HWDeviceDRM::DefaultCommit(HWLayers *hw_layers) { 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 1419d9fd..02389470 100644 --- a/sdm/libs/core/drm/hw_device_drm.h +++ b/sdm/libs/core/drm/hw_device_drm.h @@ -138,27 +138,24 @@ class HWDeviceDRM : public HWInterface { 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 in map. + void MapBufferToFbId(Layer* layer, LayerBuffer* buffer); + // Find handle_id in output buffer map. Else create fb_id and add 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 *hashmap_ {}; - int current_index_ = 0; + bool disable_fbid_cache_ = false; + std::unordered_map> 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 dbd707f9..87c99495 100644 --- a/sdm/libs/core/drm/hw_peripheral_drm.cpp +++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp @@ -200,7 +200,7 @@ DisplayError HWPeripheralDRM::SetupConcurrentWritebackModes() { 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); @@ -211,7 +211,7 @@ void HWPeripheralDRM::ConfigureConcurrentWriteback(LayerStack *layer_stack) { 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 29367fee..a2e84a29 100644 --- a/sdm/libs/core/drm/hw_virtual_drm.cpp +++ b/sdm/libs/core/drm/hw_virtual_drm.cpp @@ -126,8 +126,8 @@ DisplayError HWVirtualDRM::Commit(HWLayers *hw_layers) { 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 @@ DisplayError HWVirtualDRM::Commit(HWLayers *hw_layers) { 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(); -- cgit v1.2.3