mediapipe/mediapipe/render/core/FramebufferCache.cpp
2022-07-28 14:19:01 +08:00

212 lines
8.2 KiB
C++
Executable File

/*
* GPUImage-x
*
* Copyright (C) 2017 Yijin Wang, Yiqian Wang
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "FramebufferCache.hpp"
#include "GPUImageUtil.h"
#if defined(__APPLE__)
#include "CVFramebuffer.hpp"
#endif
NS_GI_BEGIN
FramebufferCache::FramebufferCache(Context *context)
: _context(context) {
}
FramebufferCache::~FramebufferCache() {
purge();
}
Framebuffer* FramebufferCache::fetchFramebufferUseTextureId(Context *context,
int width,
int height,
int textureId,
bool onlyTexture,
const TextureAttributes textureAttributes,
bool useTextureCache) {
Framebuffer* framebufferFromCache = 0;
if (useTextureCache) {
#if defined(__APPLE__)
//分平台创建 TextureCache
framebufferFromCache = new CVFramebuffer(context,
width,
height,
textureAttributes,
textureId);
#elif defined(__ANDROID__) || defined(ANDROID)
assert("Android HardwareBuffer not support reuse now");
#endif
} else {
framebufferFromCache = new Framebuffer(context,
width,
height,
textureAttributes,
textureId);
}
return framebufferFromCache;
}
Framebuffer* FramebufferCache::fetchFramebuffer(Context *context,
int width,
int height,
bool onlyTexture/* = false*/,
const TextureAttributes textureAttributes/* = defaultTextureAttribure*/,
bool useTextureCache) {
Framebuffer* framebufferFromCache = 0;
std::string lookupHash = _getHash(width, height, onlyTexture, textureAttributes, useTextureCache);
auto matchFramebuffersHashCode = _framebufferTypeMap[lookupHash];
if (matchFramebuffersHashCode.size() > 0) {
for (const auto &framebufferHashCodeKey : matchFramebuffersHashCode) {
auto *framebuffer = _framebuffers[framebufferHashCodeKey.first];
if (framebuffer == NULL) {
framebuffer = 0;
break;
}
if (framebuffer->getWidth() != width || framebuffer->getHeight() != height) {
forceCleanFramebuffer(framebuffer);
framebuffer = 0;
} else if (framebuffer->framebufferRetainCount() == 0 && !framebuffer->isDealloc) {
Log("Framebuffer 【命中缓存】", "hashcode:%s count:%d",
framebufferHashCodeKey.first.c_str(),
framebuffer->framebufferRetainCount());
return framebuffer;
}
}
}
Log("Framebuffer 所有缓存【未命中】", "hashcode:%s count:%d",
lookupHash.c_str(),
matchFramebuffersHashCode.size());
// 如果都被占用了 或者找不到对应的Framebuffer 则需要创建一个新的
if (useTextureCache) {
#if defined(__APPLE__)
//分平台创建 TextureCache
framebufferFromCache = new CVFramebuffer(context,
width,
height,
onlyTexture,
textureAttributes);
#elif defined(__ANDROID__) || defined(ANDROID)
assert("Android HardwareBuffer not support reuse now");
#endif
} else {
framebufferFromCache = new Framebuffer(context,
width,
height,
onlyTexture,
textureAttributes);
}
std::string framebufferHash = str_format("%s-%ld", lookupHash.c_str(),
framebufferFromCache->getTexture());
Log("Framebuffer 创建新的Framebuffer", "hashcode:%s numberOfMatchingFramebuffers:%d",
framebufferHash.c_str(),
matchFramebuffersHashCode.size());
framebufferFromCache->_hashCode = framebufferHash;
framebufferFromCache->_typeCode = lookupHash;
_framebuffers[framebufferHash] = framebufferFromCache;
_framebufferTypeMap[lookupHash][framebufferHash] = 0;
return framebufferFromCache;
}
void FramebufferCache::forceCleanFramebuffer(Framebuffer *framebuffer) {
if (_framebuffers.find(framebuffer->_hashCode) != _framebuffers.end()) {
_framebuffers.erase(framebuffer->_hashCode);
}
if (_framebufferTypeMap[framebuffer->_typeCode].find(framebuffer->_hashCode) !=
_framebufferTypeMap[framebuffer->_typeCode].end()) {
_framebufferTypeMap[framebuffer->_typeCode].erase(framebuffer->_hashCode);
}
delete framebuffer;
framebuffer = 0;
}
void FramebufferCache::returnFramebuffer(Framebuffer* framebuffer, int maxCacheSize) {
if (framebuffer->framebufferRetainCount() == 0) {
Log("准备回收 retainCount == 0 的Framebuffer", "cacheHash:%s cacheReferenceCount:%d",
framebuffer->_hashCode.c_str(),
framebuffer->framebufferRetainCount());
if (_framebuffers.find(framebuffer->_hashCode) != _framebuffers.end()) {
if (_framebufferTypeMap[framebuffer->_typeCode].size() > maxCacheSize) {
_framebuffers.erase(framebuffer->_hashCode);
if (_framebufferTypeMap[framebuffer->_typeCode].find(framebuffer->_hashCode) !=
_framebufferTypeMap[framebuffer->_typeCode].end()) {
_framebufferTypeMap[framebuffer->_typeCode].erase(framebuffer->_hashCode);
}
delete framebuffer;
framebuffer = 0;
}
}
}
}
std::string FramebufferCache::_getHash(int width,
int height,
bool onlyTexture,
const TextureAttributes textureAttributes,
bool useTextureCache) const {
const char *formatStr = "";
if (onlyTexture) {
formatStr = "%.1dx%.1d-%d:%d:%d:%d:%d:%d:%d-NOFB";
} else {
formatStr = "%.1dx%.1d-%d:%d:%d:%d:%d:%d:%d";
}
return str_format(formatStr,
width, height,
textureAttributes.minFilter, textureAttributes.magFilter,
textureAttributes.wrapS, textureAttributes.wrapT,
textureAttributes.internalFormat, textureAttributes.format,
textureAttributes.type);
}
Framebuffer* FramebufferCache::_getFramebufferByHash(const std::string& hash) {
return _framebuffers[hash];
}
void FramebufferCache::purge(bool force) {
if (_framebuffers.size() == 0) {
return;
}
for(auto &kvp : _framebuffers) {
if (kvp.second && !kvp.second->isDealloc) {
delete kvp.second;
kvp.second = nullptr;
}
}
_framebuffers.clear();
_framebufferTypeMap.clear();
}
void FramebufferCache::clearCache() {
_framebuffers.clear();
_framebufferTypeMap.clear();
}
NS_GI_END