| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/frame_sink/ui_resource_manager.h" |
| |
| #include <GLES2/gl2.h> |
| |
| #include <utility> |
| |
| #include "ash/frame_sink/ui_resource.h" |
| #include "base/check.h" |
| #include "components/viz/common/resources/resource_id.h" |
| #include "components/viz/common/resources/returned_resource.h" |
| #include "components/viz/common/resources/transferable_resource.h" |
| #include "ui/gfx/geometry/size.h" |
| |
| namespace ash { |
| |
| UiResourceManager::UiResourceManager() = default; |
| |
| UiResourceManager::~UiResourceManager() { |
| DCHECK(exported_resources_pool_.empty()) |
| << "We must reclaim all the exported resources before we can safely " |
| "delete the resource manager. "; |
| } |
| |
| viz::ResourceId UiResourceManager::FindResourceToReuse( |
| const gfx::Size& size, |
| viz::SharedImageFormat format, |
| UiSourceId ui_source_id) const { |
| // UiResourceManager is expected to handle a few resources at a given time ( |
| // less than 30), therefore just using a simple linear search to find the |
| // available resource. |
| for (const auto& iter : available_resources_pool_) { |
| const auto& resource = iter.second; |
| |
| if (resource->ui_source_id == ui_source_id && |
| resource->resource_size == size && resource->format == format) { |
| return iter.first; |
| } |
| } |
| |
| return viz::kInvalidResourceId; |
| } |
| |
| std::unique_ptr<UiResource> UiResourceManager::ReleaseAvailableResource( |
| viz::ResourceId resource_id) { |
| auto iter = available_resources_pool_.find(resource_id); |
| |
| if (iter == available_resources_pool_.end()) { |
| return nullptr; |
| } |
| |
| auto to_be_release_resource = std::move(iter->second); |
| available_resources_pool_.erase(iter); |
| |
| return to_be_release_resource; |
| } |
| |
| viz::ResourceId UiResourceManager::OfferResource( |
| std::unique_ptr<UiResource> resource) { |
| if (!resource) { |
| return viz::kInvalidResourceId; |
| } |
| |
| viz::ResourceId new_id = id_generator_.GenerateNextId(); |
| resource->resource_id = new_id; |
| available_resources_pool_[new_id] = std::move(resource); |
| |
| return new_id; |
| } |
| |
| const UiResource* UiResourceManager::PeekAvailableResource( |
| viz::ResourceId resource_id) const { |
| auto iter = available_resources_pool_.find(resource_id); |
| |
| if (iter != available_resources_pool_.end()) { |
| return iter->second.get(); |
| } |
| |
| return nullptr; |
| } |
| |
| const UiResource* UiResourceManager::PeekExportedResource( |
| viz::ResourceId resource_id) const { |
| auto iter = exported_resources_pool_.find(resource_id); |
| |
| if (iter != exported_resources_pool_.end()) { |
| return iter->second.get(); |
| } |
| |
| return nullptr; |
| } |
| |
| void UiResourceManager::ReclaimResources( |
| const std::vector<viz::ReturnedResource>& resources) { |
| for (const auto& entry : resources) { |
| auto it = exported_resources_pool_.find(entry.id); |
| DCHECK(it != exported_resources_pool_.end()); |
| |
| std::unique_ptr<UiResource> resource = std::move(it->second); |
| resource->sync_token = entry.sync_token; |
| |
| // Move the resource from exported pool to available resources pool. |
| exported_resources_pool_.erase(it); |
| |
| if (!entry.lost) { |
| available_resources_pool_[entry.id] = std::move(resource); |
| } |
| } |
| } |
| |
| viz::TransferableResource UiResourceManager::PrepareResourceForExport( |
| viz::ResourceId resource_id) { |
| auto resource_iter = available_resources_pool_.find(resource_id); |
| |
| if (resource_iter == available_resources_pool_.end()) { |
| return viz::TransferableResource(); |
| } |
| |
| auto to_be_exported_resource = std::move(resource_iter->second); |
| available_resources_pool_.erase(resource_iter); |
| |
| viz::TransferableResource transferable_resource = |
| viz::TransferableResource::MakeGpu( |
| to_be_exported_resource->mailbox, GL_TEXTURE_2D, |
| to_be_exported_resource->sync_token, |
| to_be_exported_resource->resource_size, |
| to_be_exported_resource->format, |
| to_be_exported_resource->is_overlay_candidate); |
| |
| transferable_resource.id = resource_id; |
| exported_resources_pool_[resource_id] = std::move(to_be_exported_resource); |
| |
| return transferable_resource; |
| } |
| |
| void UiResourceManager::DamageResources() { |
| for (auto& iter : exported_resources_pool_) { |
| iter.second->damaged = true; |
| } |
| |
| for (auto& iter : available_resources_pool_) { |
| iter.second->damaged = true; |
| } |
| } |
| |
| size_t UiResourceManager::exported_resources_count() const { |
| return exported_resources_pool_.size(); |
| } |
| |
| size_t UiResourceManager::available_resources_count() const { |
| return available_resources_pool_.size(); |
| } |
| |
| void UiResourceManager::ClearAvailableResources() { |
| available_resources_pool_.clear(); |
| } |
| |
| void UiResourceManager::LostExportedResources() { |
| exported_resources_pool_.clear(); |
| } |
| |
| } // namespace ash |