chromium/ash/frame_sink/ui_resource_manager.h

// 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.

#ifndef ASH_FRAME_SINK_UI_RESOURCE_MANAGER_H_
#define ASH_FRAME_SINK_UI_RESOURCE_MANAGER_H_

#include <memory>
#include <vector>

#include "ash/ash_export.h"
#include "ash/frame_sink/ui_resource.h"
#include "base/containers/flat_map.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "ui/gfx/geometry/size.h"

namespace ash {

// Responsible to keep track of resources that are currently in-use by display
// compositor and resources that are currently available to be reused.
// Once we offer a resource to the manager, UiResourceManager manages the
// lifetime of the resources and keep track if the resource is currently
// exported or is available to use. It is required that all the exported
// resources are reclaimed before we can delete the UiResourceManager.
class ASH_EXPORT UiResourceManager {
 public:
  UiResourceManager();

  UiResourceManager(const UiResourceManager&) = delete;
  UiResourceManager& operator=(const UiResourceManager&) = delete;

  ~UiResourceManager();

  // Returns the resource_id of an available resource of given `size`,
  // `format` and `ui_source_id`. If there is no matching resource available, we
  // return `viz::kInvalidResourceId`.
  viz::ResourceId FindResourceToReuse(const gfx::Size& size,
                                      viz::SharedImageFormat format,
                                      UiSourceId ui_source_id) const;

  const UiResource* PeekAvailableResource(viz::ResourceId resource_id) const;

  const UiResource* PeekExportedResource(viz::ResourceId resource_id) const;

  std::unique_ptr<UiResource> ReleaseAvailableResource(
      viz::ResourceId resource_id);

  void ReclaimResources(const std::vector<viz::ReturnedResource>& resources);

  // Give the `resourse` to be managed by the manager. The resource is
  // immediately available for use and can be exported.
  viz::ResourceId OfferResource(std::unique_ptr<UiResource> resource);

  // We take the available resource identified by `resource_id`, map it to a
  // transferable resource and mark it as an exported resource. Only a resource
  // that is currently being managed can be exported.
  viz::TransferableResource PrepareResourceForExport(
      viz::ResourceId resource_id);

  // Mark all the managed resources to be damaged.
  void DamageResources();

  void ClearAvailableResources();

  // Call the method when there is no way to reclaim back the exported
  // resources. i.e when the frame_sink is lost or deleted.
  void LostExportedResources();

  size_t exported_resources_count() const;

  size_t available_resources_count() const;

 private:
  // TODO(zoraiznaeem): If a feature ends up growing the size of pool past 40,
  // use a fixed size circular list as a pool and get rid of least recently used
  // resources.
  using ResourcePool =
      base::flat_map<viz::ResourceId, std::unique_ptr<UiResource>>;

  // The resources that are currently available to be used in a compositor
  // frame.
  ResourcePool available_resources_pool_;

  // The resources that are in-flight or will be exported to the display
  // compositor.
  ResourcePool exported_resources_pool_;

  // Generates transferable resource ids for transferable resources.
  viz::ResourceIdGenerator id_generator_;
};

}  // namespace ash

#endif  // ASH_FRAME_SINK_UI_RESOURCE_MANAGER_H_