Extra2D/Easy2D/include/easy2d/graphics/texture_pool.h

195 lines
5.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <easy2d/core/types.h>
#include <easy2d/graphics/texture.h>
#include <string>
#include <unordered_map>
#include <list>
#include <functional>
#include <mutex>
namespace easy2d {
// ============================================================================
// 纹理池配置
// ============================================================================
struct TexturePoolConfig {
size_t maxCacheSize = 64 * 1024 * 1024; // 最大缓存大小 (64MB)
size_t maxTextureCount = 256; // 最大纹理数量
float unloadInterval = 30.0f; // 自动清理间隔 (秒)
bool enableAsyncLoad = true; // 启用异步加载
};
// ============================================================================
// 纹理池 - 使用LRU缓存策略管理纹理复用
// ============================================================================
class TexturePool {
public:
// ------------------------------------------------------------------------
// 单例访问
// ------------------------------------------------------------------------
static TexturePool& getInstance();
// ------------------------------------------------------------------------
// 初始化和关闭
// ------------------------------------------------------------------------
bool init(const TexturePoolConfig& config = TexturePoolConfig{});
void shutdown();
// ------------------------------------------------------------------------
// 纹理获取
// ------------------------------------------------------------------------
/**
* @brief 从文件获取纹理(带缓存)
* @param filepath 纹理文件路径
* @return 纹理对象失败返回nullptr
*/
Ptr<Texture> get(const std::string& filepath);
/**
* @brief 异步加载纹理
* @param filepath 纹理文件路径
* @param callback 加载完成回调
*/
void getAsync(const std::string& filepath,
std::function<void(Ptr<Texture>)> callback);
/**
* @brief 从内存数据创建纹理(自动缓存)
* @param name 纹理名称(用于缓存键)
* @param data 图像数据
* @param width 宽度
* @param height 高度
* @param format 像素格式
* @return 纹理对象
*/
Ptr<Texture> createFromData(const std::string& name,
const uint8_t* data,
int width,
int height,
PixelFormat format = PixelFormat::RGBA8);
// ------------------------------------------------------------------------
// 缓存管理
// ------------------------------------------------------------------------
/**
* @brief 手动添加纹理到缓存
*/
void add(const std::string& key, Ptr<Texture> texture);
/**
* @brief 从缓存移除纹理
*/
void remove(const std::string& key);
/**
* @brief 检查纹理是否在缓存中
*/
bool has(const std::string& key) const;
/**
* @brief 清空所有缓存
*/
void clear();
/**
* @brief 清理未使用的纹理LRU策略
* @param targetSize 目标缓存大小
*/
void trim(size_t targetSize);
// ------------------------------------------------------------------------
// 统计信息
// ------------------------------------------------------------------------
/**
* @brief 获取当前缓存的纹理数量
*/
size_t getTextureCount() const;
/**
* @brief 获取当前缓存的总大小(字节)
*/
size_t getCacheSize() const;
/**
* @brief 获取缓存命中率
*/
float getHitRate() const;
/**
* @brief 打印统计信息
*/
void printStats() const;
// ------------------------------------------------------------------------
// 自动清理
// ------------------------------------------------------------------------
/**
* @brief 更新(在主循环中调用,用于自动清理)
*/
void update(float dt);
/**
* @brief 设置自动清理间隔
*/
void setAutoUnloadInterval(float interval);
private:
TexturePool() = default;
~TexturePool() = default;
TexturePool(const TexturePool&) = delete;
TexturePool& operator=(const TexturePool&) = delete;
// 缓存项
struct CacheEntry {
Ptr<Texture> texture;
size_t size; // 纹理大小(字节)
float lastAccessTime; // 最后访问时间
uint32_t accessCount; // 访问次数
};
// LRU列表最近使用的在前面
using LRUList = std::list<std::string>;
using LRUIterator = LRUList::iterator;
mutable std::mutex mutex_;
TexturePoolConfig config_;
// 缓存存储
std::unordered_map<std::string, CacheEntry> cache_;
std::unordered_map<std::string, LRUIterator> lruMap_;
LRUList lruList_;
// 统计
size_t totalSize_ = 0;
uint64_t hitCount_ = 0;
uint64_t missCount_ = 0;
float autoUnloadTimer_ = 0.0f;
bool initialized_ = false;
// 异步加载队列
struct AsyncLoadTask {
std::string filepath;
std::function<void(Ptr<Texture>)> callback;
};
std::vector<AsyncLoadTask> asyncTasks_;
// 内部方法
void touch(const std::string& key);
void evict();
Ptr<Texture> loadTexture(const std::string& filepath);
size_t calculateTextureSize(int width, int height, PixelFormat format);
void processAsyncTasks();
};
// ============================================================================
// 便捷宏
// ============================================================================
#define E2D_TEXTURE_POOL() ::easy2d::TexturePool::getInstance()
} // namespace easy2d