Line data Source code
1 : /**
2 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "XLTemporaryResource.h"
24 : #include "XLMeshIndex.h"
25 : #include "XLTexture.h"
26 : #include "XLCorePlatform.h"
27 : #include "XLCoreObject.h"
28 :
29 : namespace STAPPLER_VERSIONIZED stappler::xenolith {
30 :
31 : XL_DECLARE_EVENT_CLASS(TemporaryResource, onLoaded);
32 :
33 30 : TemporaryResource::~TemporaryResource() {
34 15 : if (_resource) {
35 0 : _resource->clear();
36 0 : _resource = nullptr;
37 : }
38 30 : }
39 :
40 15 : bool TemporaryResource::init(Rc<core::Resource> &&res, TimeInterval timeout, TemporaryResourceFlags flags) {
41 15 : _atime = platform::clock(core::ClockType::Monotonic);
42 15 : _timeout = timeout;
43 15 : _resource = move(res);
44 15 : _name = _resource->getName().str<Interface>();
45 :
46 15 : if ((flags & TemporaryResourceFlags::Loaded) != TemporaryResourceFlags::None) {
47 0 : setLoaded(true);
48 : }
49 :
50 15 : if ((flags & TemporaryResourceFlags::RemoveOnClear) != TemporaryResourceFlags::None) {
51 0 : _removeOnClear = true;
52 : }
53 :
54 15 : return true;
55 : }
56 :
57 15 : void TemporaryResource::invalidate() {
58 15 : for (auto &it : _textures) {
59 0 : it.second->invalidate();
60 : }
61 15 : for (auto &it : _meshIndexes) {
62 0 : it.second->invalidate();
63 : }
64 :
65 15 : _owners.clear();
66 15 : _resource = nullptr;
67 15 : }
68 :
69 6 : Rc<Texture> TemporaryResource::acquireTexture(StringView str) {
70 6 : if (auto v = _resource->getImage(str)) {
71 6 : auto it = _textures.find(v);
72 6 : if (it == _textures.end()) {
73 0 : it = _textures.emplace(v, Rc<Texture>::create(v, this)).first;
74 : }
75 6 : return it->second;
76 : }
77 0 : return nullptr;
78 : }
79 :
80 0 : Rc<MeshIndex> TemporaryResource::acquireMeshIndex(StringView str) {
81 0 : if (auto v = _resource->getBuffer(str)) {
82 0 : auto it = _meshIndexes.find(v);
83 0 : if (it == _meshIndexes.end()) {
84 0 : it = _meshIndexes.emplace(v, Rc<MeshIndex>::create(v, this)).first;
85 : }
86 0 : return it->second;
87 : }
88 0 : return nullptr;
89 : }
90 :
91 30 : void TemporaryResource::setLoaded(bool val) {
92 30 : if (val) {
93 15 : _requested = true;
94 15 : for (auto &it : _callbacks) {
95 0 : it.second(true);
96 0 : -- _users;
97 : }
98 15 : _callbacks.clear();
99 15 : if (_loaded != val) {
100 15 : _loaded = val;
101 15 : onLoaded(this, _loaded);
102 : }
103 : } else {
104 15 : _loaded = false;
105 15 : _requested = false;
106 15 : _resource->clear();
107 15 : onLoaded(this, _loaded);
108 : }
109 30 : _atime = platform::clock(core::ClockType::Monotonic);
110 30 : }
111 :
112 15 : void TemporaryResource::setRequested(bool val) {
113 15 : _requested = val;
114 15 : }
115 :
116 0 : void TemporaryResource::setTimeout(TimeInterval ival) {
117 0 : _timeout = ival;
118 0 : }
119 :
120 0 : bool TemporaryResource::load(Ref *ref, Function<void(bool)> &&cb) {
121 0 : _atime = platform::clock(core::ClockType::Monotonic);
122 0 : if (_loaded) {
123 0 : if (cb) {
124 0 : cb(false);
125 : }
126 0 : return false;
127 : } else {
128 0 : _callbacks.emplace_back(pair(ref, move(cb)));
129 0 : ++ _users;
130 0 : return true;
131 : }
132 : }
133 :
134 21 : void TemporaryResource::onEnter(ResourceOwner *owner, ResourceObject *res) {
135 21 : _owners.emplace(owner);
136 21 : _atime = platform::clock(core::ClockType::Monotonic);
137 :
138 21 : if (res->getType() == ResourceType::Texture) {
139 21 : auto tex = (Texture *)res;
140 21 : auto v = tex->getImageData();
141 21 : auto it = _textures.find(v);
142 21 : if (it == _textures.end()) {
143 15 : _textures.emplace(v, tex);
144 : }
145 0 : } else if (res->getType() == ResourceType::MeshIndex) {
146 0 : auto mesh = (MeshIndex *)res;
147 0 : auto v = mesh->getVertexData();
148 0 : auto it = _meshIndexes.find(v);
149 0 : if (it == _meshIndexes.end()) {
150 0 : _meshIndexes.emplace(v, mesh);
151 : }
152 : }
153 :
154 21 : ++ _users;
155 21 : }
156 :
157 21 : void TemporaryResource::onExit(ResourceOwner *, ResourceObject *) {
158 21 : _atime = platform::clock(core::ClockType::Monotonic);
159 21 : -- _users;
160 21 : }
161 :
162 15 : bool TemporaryResource::clear() {
163 15 : Vector<uint64_t> ids;
164 30 : for (auto &it : _textures) {
165 15 : if (it.first->image) {
166 15 : emplace_ordered(ids, it.first->image->getIndex());
167 : }
168 : }
169 :
170 15 : if (!ids.empty()) {
171 30 : for (auto &it : _owners) {
172 15 : it->revokeImages(ids);
173 : }
174 : }
175 15 : _textures.clear();
176 15 : _meshIndexes.clear();
177 15 : _owners.clear();
178 :
179 15 : setLoaded(false);
180 15 : return _removeOnClear;
181 15 : }
182 :
183 30 : StringView TemporaryResource::getName() const {
184 30 : return _resource->getName();
185 : }
186 :
187 1110 : bool TemporaryResource::isDeprecated(const UpdateTime &time) const {
188 1110 : if (_users > 0 || !_loaded) {
189 1005 : return false;
190 : }
191 :
192 105 : if (_timeout == TimeInterval()) {
193 0 : return true;
194 105 : } else if (_atime + _timeout.toMicroseconds() < time.global) {
195 15 : return true;
196 : }
197 :
198 90 : return false;
199 : }
200 :
201 : }
|