1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140

gpu / command_buffer / service / service_discardable_manager.h [blame]

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef GPU_COMMAND_BUFFER_SERVICE_SERVICE_DISCARDABLE_MANAGER_H_
#define GPU_COMMAND_BUFFER_SERVICE_SERVICE_DISCARDABLE_MANAGER_H_

#include <vector>

#include "base/containers/lru_cache.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/raw_ptr.h"
#include "base/trace_event/memory_dump_provider.h"
#include "gpu/command_buffer/common/discardable_handle.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/gpu_gles2_export.h"

namespace gpu {
struct GpuPreferences;
namespace gles2 {
class TextureManager;
class TextureRef;
}

GPU_GLES2_EXPORT size_t DiscardableCacheSizeLimit();
GPU_GLES2_EXPORT size_t DiscardableCacheSizeLimitForPressure(
    size_t base_cache_limit,
    base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);

class GPU_GLES2_EXPORT ServiceDiscardableManager
    : public base::trace_event::MemoryDumpProvider {
 public:
  explicit ServiceDiscardableManager(const GpuPreferences& preferences);

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

  ~ServiceDiscardableManager() override;

  // base::trace_event::MemoryDumpProvider implementation.
  bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                    base::trace_event::ProcessMemoryDump* pmd) override;

  void InsertLockedTexture(uint32_t texture_id,
                           size_t texture_size,
                           gles2::TextureManager* texture_manager,
                           ServiceDiscardableHandle handle);

  // Unlocks the indicated texture. If *|texture_to_unbind| is not nullptr,
  // ServiceDiscardableManager has taken ownership of the given texture, and
  // it is the callers responsibility to unbind it from any other objects.
  // Returns false if the given texture_id has not been initialized for use
  // with discardable.
  bool UnlockTexture(uint32_t texture_id,
                     gles2::TextureManager* texture_manager,
                     gles2::TextureRef** texture_to_unbind);
  // Locks the indicated texture, allowing it to be used in future GL commands.
  // Returns false if the given texture_id has not been initialized for use
  // with discardable.
  bool LockTexture(uint32_t texture_id, gles2::TextureManager* texture_manager);

  // Returns all unlocked texture refs to the texture_manager for deletion.
  // After this point, this class will have no references to the given
  // |texture_manager|.
  void OnTextureManagerDestruction(gles2::TextureManager* texture_manager);

  // Called when a texture is deleted, to clean up state.
  void OnTextureDeleted(uint32_t texture_id,
                        gles2::TextureManager* texture_manager);

  // Called by the TextureManager when a texture's size changes.
  void OnTextureSizeChanged(uint32_t texture_id,
                            gles2::TextureManager* texture_manager,
                            size_t new_size);

  // Called when all contexts with cached textures in this manager are lost.
  void OnContextLost();

  // Test only functions:
  size_t NumCacheEntriesForTesting() const { return entries_.size(); }
  bool IsEntryLockedForTesting(uint32_t texture_id,
                               gles2::TextureManager* texture_manager) const;
  size_t TotalSizeForTesting() const { return total_size_; }
  gles2::TextureRef* UnlockedTextureRefForTesting(
      uint32_t texture_id,
      gles2::TextureManager* texture_manager) const;

  void SetCacheSizeLimitForTesting(size_t cache_size_limit) {
    cache_size_limit_ = cache_size_limit;
  }

  void HandleMemoryPressure(
      base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);

 private:
  void EnforceCacheSizeLimit(size_t limit);

  struct GpuDiscardableEntry {
   public:
    GpuDiscardableEntry(ServiceDiscardableHandle handle, size_t size);
    GpuDiscardableEntry(const GpuDiscardableEntry& other);
    GpuDiscardableEntry(GpuDiscardableEntry&& other);
    ~GpuDiscardableEntry();

    ServiceDiscardableHandle handle;
    scoped_refptr<gles2::TextureRef> unlocked_texture_ref;
    // The current ref count of this object with regards to command buffer
    // execution. May be out of sync with the handle's refcount, as the handle
    // can be locked out of band with the command buffer.
    uint32_t service_ref_count_ = 1;
    size_t size;
  };
  struct GpuDiscardableEntryKey {
    uint32_t texture_id;
    raw_ptr<gles2::TextureManager> texture_manager;
  };
  struct GpuDiscardableEntryKeyCompare {
    bool operator()(const GpuDiscardableEntryKey& lhs,
                    const GpuDiscardableEntryKey& rhs) const {
      return std::tie(lhs.texture_manager, lhs.texture_id) <
             std::tie(rhs.texture_manager, rhs.texture_id);
    }
  };
  using EntryCache = base::LRUCache<GpuDiscardableEntryKey,
                                    GpuDiscardableEntry,
                                    GpuDiscardableEntryKeyCompare>;
  EntryCache entries_;

  // Total size of all |entries_|. The same as summing
  // GpuDiscardableEntry::size for each entry.
  size_t total_size_ = 0;

  // The limit above which the cache will start evicting resources.
  size_t cache_size_limit_ = 0;
};

}  // namespace gpu

#endif  // GPU_COMMAND_BUFFER_SERVICE_SERVICE_DISCARDABLE_MANAGER_H_