1 /* 2 * Copyright (C) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef RENDER_RESOURCE_CACHE_H 17 #define RENDER_RESOURCE_CACHE_H 18 19 #include "base/render_base.h" 20 #include "base/cache/render_fifo_cache.h" 21 #include "graphic/render_general_program.h" 22 #include "render_mesh.h" 23 #include "graphic/render_texture.h" 24 25 #define TEXTURE_CACHE_MAX_CAPACITY (800 * 1024 * 1024) 26 #define TEXTURE_CACHE_STABLE_CAPACITY (80 * 1024 * 1024) 27 28 namespace OHOS { 29 namespace Media { 30 namespace Effect { 31 class RenderFrameBuffer; 32 using RenderFrameBufferPtr = std::shared_ptr<RenderFrameBuffer>; 33 class RenderEffectBase; 34 using RenderEffectBasePtr = std::shared_ptr<RenderEffectBase>; 35 36 constexpr int TEX_WIDTH_TAG_POS = 48; 37 constexpr int TEX_HEIGHT_TAG_POS = 32; 38 constexpr int RESIZE_RATE = 2; 39 40 class ResourceCache { 41 public: ~ResourceCache()42 ~ResourceCache() 43 { 44 texReleaseFlag = true; 45 DeleteAllShader(); 46 DeleteAllMesh(); 47 } GetShader(const std::string name)48 RenderGeneralProgram *GetShader(const std::string name) 49 { 50 auto ite = shadersMap_.find(name); 51 if (ite == shadersMap_.end()) { 52 return nullptr; 53 } 54 return ite->second; 55 } 56 GetMesh(const std::string name)57 RenderMesh *GetMesh(const std::string name) 58 { 59 auto ite = meshesMap_.find(name); 60 if (ite == meshesMap_.end()) { 61 return nullptr; 62 } 63 return ite->second; 64 } 65 GetEffect(const std::string name)66 RenderEffectBasePtr GetEffect(const std::string name) 67 { 68 auto ite = effectMap_.find(name); 69 if (ite == effectMap_.end()) { 70 return nullptr; 71 } 72 return ite->second; 73 } 74 AddShader(std::string name,RenderGeneralProgram * shader)75 void AddShader(std::string name, RenderGeneralProgram *shader) 76 { 77 shadersMap_[name] = shader; 78 } 79 AddMesh(std::string name,RenderMesh * mesh)80 void AddMesh(std::string name, RenderMesh *mesh) 81 { 82 meshesMap_[name] = mesh; 83 } 84 AddEffect(std::string name,RenderEffectBasePtr effect)85 void AddEffect(std::string name, RenderEffectBasePtr effect) 86 { 87 effectMap_[name] = effect; 88 } 89 RemoveShader(std::string name)90 size_t RemoveShader(std::string name) 91 { 92 return shadersMap_.erase(name); 93 } 94 RemoveMesh(std::string name)95 size_t RemoveMesh(std::string name) 96 { 97 return meshesMap_.erase(name); 98 } 99 RemoveEffect(std::string name)100 size_t RemoveEffect(std::string name) 101 { 102 return effectMap_.erase(name); 103 } 104 RequestTexture(RenderContext * ctx,GLsizei w,GLsizei h,GLenum interFmt)105 RenderTexturePtr RequestTexture(RenderContext *ctx, GLsizei w, GLsizei h, GLenum interFmt) 106 { 107 UINT64 tag = GetTexTag(w, h, interFmt); 108 RenderTexture *rawTex; 109 RenderTexturePtr tex; 110 bool isGot = disuseTexCache_.Take(tag, tex); 111 if (isGot) { 112 rawTex = tex.get(); 113 tex.reset(); 114 } else { 115 rawTex = new RenderTexture(ctx, w, h, interFmt); 116 rawTex->Init(); 117 } 118 return RenderTexturePtr(rawTex, [this](auto *p) { 119 if (p) { 120 RecycleTexture(dynamic_cast<RenderTexture *>(p)); 121 } 122 }); 123 } 124 ResizeTexCache()125 void ResizeTexCache() 126 { 127 if (disuseTexCache_.Size() > TEXTURE_CACHE_STABLE_CAPACITY) { 128 texReleaseFlag = true; 129 disuseTexCache_.ReSize(disuseTexCache_.Size() / RESIZE_RATE, false); 130 texReleaseFlag = false; 131 } 132 } 133 AddTexStage(int id,RenderTexturePtr tex)134 void AddTexStage(int id, RenderTexturePtr tex) 135 { 136 namedTexCache_.insert_or_assign(id, tex); 137 } 138 GetTexStage(int id)139 RenderTexturePtr GetTexStage(int id) 140 { 141 auto ite = namedTexCache_.find(id); 142 if (ite != namedTexCache_.end()) { 143 return ite->second; 144 } 145 return nullptr; 146 } 147 RemoveTexStage(int id)148 void RemoveTexStage(int id) 149 { 150 auto ite = namedTexCache_.find(id); 151 if (ite != namedTexCache_.end()) { 152 namedTexCache_.erase(ite); 153 } 154 } 155 AddTexGlobalCache(std::string id,RenderTexturePtr tex)156 void AddTexGlobalCache(std::string id, RenderTexturePtr tex) 157 { 158 texGlobalCache_.insert_or_assign(id, tex); 159 } 160 GetTexGlobalCache(const std::string id)161 RenderTexturePtr GetTexGlobalCache(const std::string id) 162 { 163 auto ite = texGlobalCache_.find(id); 164 if (ite != texGlobalCache_.end()) { 165 return ite->second; 166 } 167 return nullptr; 168 } 169 RemoveTexGlobalCache(const std::string id)170 void RemoveTexGlobalCache(const std::string id) 171 { 172 auto ite = texGlobalCache_.find(id); 173 if (ite != texGlobalCache_.end()) { 174 texGlobalCache_.erase(ite); 175 } 176 } 177 178 private: RecycleTexture(RenderTexture * tex)179 void RecycleTexture(RenderTexture *tex) 180 { 181 UINT64 tag = GetTexTag(tex->Width(), tex->Height(), tex->Format()); 182 auto func = [this](RenderTexture *p) { 183 if (texReleaseFlag && p) { 184 p->Release(); 185 delete p; 186 } 187 }; 188 texReleaseFlag = true; 189 disuseTexCache_.Put(tag, RenderTexturePtr(tex, func)); 190 texReleaseFlag = false; 191 } 192 193 bool texReleaseFlag{ false }; 194 std::unordered_map<std::string, RenderGeneralProgram *> shadersMap_; 195 std::unordered_map<std::string, RenderMesh *> meshesMap_; 196 RenderFifoCache<UINT64, RenderTexturePtr, TextureSizeMeasurer> disuseTexCache_{TEXTURE_CACHE_MAX_CAPACITY}; 197 std::unordered_map<int, RenderTexturePtr> namedTexCache_; 198 std::unordered_map<std::string, RenderTexturePtr> texGlobalCache_; 199 std::unordered_map<std::string, RenderEffectBasePtr> effectMap_; 200 DeleteAllShader()201 void DeleteAllShader() 202 { 203 std::unordered_map<std::string, RenderGeneralProgram *>::iterator iter = shadersMap_.begin(); 204 while (iter != shadersMap_.end()) { 205 iter->second->Release(); 206 ++iter; 207 } 208 shadersMap_.clear(); 209 } 210 DeleteAllMesh()211 void DeleteAllMesh() 212 { 213 std::unordered_map<std::string, RenderMesh *>::iterator iter = meshesMap_.begin(); 214 while (iter != meshesMap_.end()) { 215 delete iter->second; 216 iter->second = nullptr; 217 meshesMap_.erase(iter++); 218 } 219 } 220 GetTexTag(GLsizei w,GLsizei h,GLenum interFmt)221 UINT64 GetTexTag(GLsizei w, GLsizei h, GLenum interFmt) 222 { 223 return ((UINT64)interFmt & 0xffffffff) | (((UINT64)h & 0xffff) << TEX_HEIGHT_TAG_POS) | 224 (((UINT64)w & 0xffff) << TEX_WIDTH_TAG_POS); 225 } 226 }; 227 } // namespace Effect 228 } // namespace Media 229 } // namespace OHOS 230 #endif