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 "XLCoreFrameRequest.h"
24 : #include "XLCoreFrameEmitter.h"
25 : #include "XLCoreFrameQueue.h"
26 : #include "XLCoreQueue.h"
27 : #include "XLCoreLoop.h"
28 :
29 : namespace STAPPLER_VERSIONIZED stappler::xenolith::core {
30 :
31 33892 : FrameOutputBinding::FrameOutputBinding(const AttachmentData *a, CompleteCallback &&cb, Rc<Ref> &&ref)
32 33892 : : attachment(a), callback(move(cb)), handle(move(ref)) { }
33 :
34 67784 : FrameOutputBinding::~FrameOutputBinding() { }
35 :
36 26554 : bool FrameOutputBinding::handleReady(FrameAttachmentData &data, bool success) {
37 26554 : if (callback) {
38 26554 : return callback(data, success, handle);
39 : }
40 0 : return false;
41 : }
42 :
43 56870 : FrameRequest::~FrameRequest() {
44 28435 : if (_queue) {
45 28435 : setQueue(nullptr);
46 : }
47 28435 : _renderTargets.clear();
48 28435 : _pool = nullptr;
49 56870 : }
50 :
51 7322 : bool FrameRequest::init(const Rc<FrameEmitter> &emitter, const FrameContraints &constraints) {
52 7322 : _pool = Rc<PoolRef>::alloc();
53 7322 : _emitter = emitter;
54 7322 : _constraints = constraints;
55 7322 : _readyForSubmit = false;
56 7322 : return true;
57 : }
58 :
59 21113 : bool FrameRequest::init(const Rc<Queue> &q) {
60 21113 : _pool = Rc<PoolRef>::alloc();
61 21113 : setQueue(q);
62 21113 : return true;
63 : }
64 :
65 19216 : bool FrameRequest::init(const Rc<Queue> &q, const FrameContraints &constraints) {
66 19216 : if (init(q)) {
67 19216 : _constraints = constraints;
68 19216 : return true;
69 : }
70 0 : return false;
71 : }
72 :
73 16 : bool FrameRequest::init(const Rc<Queue> &q, const Rc<FrameEmitter> &emitter, const FrameContraints &constraints) {
74 16 : if (init(q)) {
75 16 : _emitter = emitter;
76 16 : _constraints = constraints;
77 16 : _readyForSubmit = emitter->isReadyForSubmit();
78 16 : return true;
79 : }
80 0 : return false;
81 : }
82 :
83 796 : void FrameRequest::addSignalDependency(Rc<DependencyEvent> &&dep) {
84 796 : if (dep) {
85 796 : _signalDependencies.emplace_back(move(dep));
86 : }
87 796 : }
88 :
89 909 : void FrameRequest::addSignalDependencies(Vector<Rc<DependencyEvent>> &&deps) {
90 909 : if (_signalDependencies.empty()) {
91 909 : _signalDependencies = move(deps);
92 : } else {
93 0 : for (auto &it : deps) {
94 0 : _signalDependencies.emplace_back(move(it));
95 : }
96 : }
97 909 : }
98 :
99 7323 : void FrameRequest::addImageSpecialization(const ImageAttachment *image, ImageInfoData &&data) {
100 7323 : auto it = _imageSpecialization.find(image);
101 7323 : if (it != _imageSpecialization.end()) {
102 0 : it->second = move(data);
103 : } else {
104 7323 : _imageSpecialization.emplace(image, data);
105 : }
106 7323 : }
107 :
108 21998 : const ImageInfoData *FrameRequest::getImageSpecialization(const ImageAttachment *image) const {
109 21998 : auto it = _imageSpecialization.find(image);
110 21998 : if (it != _imageSpecialization.end()) {
111 7322 : return &it->second;
112 : }
113 14676 : return nullptr;
114 : }
115 :
116 0 : bool FrameRequest::addInput(const Attachment *a, Rc<AttachmentInputData> &&data) {
117 0 : return addInput(a->getData(), move(data));
118 : }
119 :
120 69648 : bool FrameRequest::addInput(const AttachmentData *a, Rc<AttachmentInputData> &&data) {
121 69648 : if (a && a->attachment->validateInput(data)) {
122 69647 : auto wIt = _waitForInputs.find(a);
123 69648 : if (wIt != _waitForInputs.end()) {
124 29292 : wIt->second.handle->submitInput(*wIt->second.queue, move(data), move(wIt->second.callback));
125 : } else {
126 40356 : _input.emplace(a, move(data));
127 : }
128 69647 : return true;
129 : }
130 0 : if (a) {
131 0 : log::error("FrameRequest", "Invalid input for attachment ", a->key);
132 : }
133 0 : return false;
134 : }
135 :
136 56885 : void FrameRequest::setQueue(const Rc<Queue> &q) {
137 56885 : if (_queue != q) {
138 56870 : if (_queue) {
139 28435 : _queue->endFrame(*this);
140 : }
141 56870 : _queue = q;
142 56870 : if (_queue) {
143 28435 : _queue->beginFrame(*this);
144 : }
145 : }
146 56886 : }
147 :
148 33892 : void FrameRequest::setOutput(Rc<FrameOutputBinding> &&binding) {
149 33892 : _output.emplace(binding->attachment, move(binding));
150 33892 : }
151 :
152 33892 : void FrameRequest::setOutput(const AttachmentData *a, CompleteCallback &&cb, Rc<Ref> &&ref) {
153 33892 : setOutput(Rc<FrameOutputBinding>::alloc(a, move(cb), move(ref)));
154 33892 : }
155 :
156 0 : void FrameRequest::setOutput(const Attachment *a, CompleteCallback &&cb, Rc<Ref> &&ref) {
157 0 : setOutput(a->getData(), move(cb));
158 0 : }
159 :
160 7322 : void FrameRequest::setRenderTarget(const AttachmentData *a, Rc<ImageStorage> &&img) {
161 7322 : _renderTargets.emplace(a, move(img));
162 7322 : }
163 :
164 28435 : void FrameRequest::attachFrame(FrameHandle *h) {
165 28435 : _frame = h;
166 28435 : if (_queue) {
167 28435 : _queue->attachFrame(_frame);
168 : }
169 28435 : }
170 :
171 28435 : void FrameRequest::detachFrame() {
172 28435 : if (_queue) {
173 28435 : _queue->detachFrame(_frame);
174 : }
175 28435 : _frame = nullptr;
176 28435 : }
177 :
178 28419 : bool FrameRequest::onOutputReady(Loop &loop, FrameAttachmentData &data) {
179 28419 : auto it = _output.find(data.handle->getAttachment()->getData());
180 28419 : if (it != _output.end()) {
181 26538 : if (it->second->handleReady(data, true)) {
182 19232 : _output.erase(it);
183 19232 : return true;
184 : }
185 7306 : return false;
186 : }
187 :
188 1881 : return false;
189 : }
190 :
191 16 : void FrameRequest::onOutputInvalidated(Loop &loop, FrameAttachmentData &data) {
192 16 : auto it = _output.find(data.handle->getAttachment()->getData());
193 16 : if (it != _output.end()) {
194 16 : if (it->second->handleReady(data, false)) {
195 16 : _output.erase(it);
196 16 : return;
197 : }
198 : }
199 : }
200 :
201 28435 : void FrameRequest::finalize(Loop &loop, HashMap<const AttachmentData *, FrameAttachmentData *> &attachments, bool success) {
202 28435 : _waitForInputs.clear();
203 :
204 28435 : if (!success) {
205 17 : for (auto &it : _output) {
206 1 : auto iit = attachments.find(it.second->attachment);
207 1 : if (iit != attachments.end()) {
208 0 : it.second->handleReady(*(iit->second), false);
209 : }
210 : }
211 16 : _output.clear();
212 : }
213 28435 : if (_emitter) {
214 7338 : _emitter = nullptr;
215 : }
216 28435 : }
217 :
218 30156 : void FrameRequest::signalDependencies(Loop &loop, Queue *q, bool success) {
219 30156 : if (!_signalDependencies.empty()) {
220 3346 : loop.signalDependencies(_signalDependencies, q, success);
221 : }
222 30156 : }
223 :
224 69649 : Rc<AttachmentInputData> FrameRequest::getInputData(const AttachmentData *attachment) {
225 69649 : auto it = _input.find(attachment);
226 69649 : if (it != _input.end()) {
227 40297 : auto ret = it->second;
228 40297 : _input.erase(it);
229 40297 : return ret;
230 40297 : }
231 29352 : return nullptr;
232 : }
233 :
234 29304 : Rc<ImageStorage> FrameRequest::getRenderTarget(const AttachmentData *a) {
235 29304 : auto it = _renderTargets.find(a);
236 29304 : if (it != _renderTargets.end()) {
237 7306 : return it->second;
238 : }
239 21998 : return nullptr;
240 : }
241 :
242 0 : Set<Rc<Queue>> FrameRequest::getQueueList() const {
243 0 : return Set<Rc<Queue>>{_queue};
244 : }
245 :
246 29352 : void FrameRequest::waitForInput(FrameQueue &queue, const Rc<AttachmentHandle> &a, Function<void(bool)> &&cb) {
247 29352 : auto it = _waitForInputs.find(a->getAttachment()->getData());
248 29352 : if (it != _waitForInputs.end()) {
249 0 : it->second.callback(false);
250 0 : it->second.callback = move(cb);
251 : } else {
252 29352 : _waitForInputs.emplace(a->getAttachment()->getData(), WaitInputData{&queue, a, move(cb)});
253 : }
254 29352 : }
255 :
256 31440 : const FrameOutputBinding *FrameRequest::getOutputBinding(const AttachmentData *a) const {
257 31440 : auto it = _output.find(a);
258 31440 : if (it != _output.end()) {
259 29559 : return it->second;
260 : }
261 1881 : return nullptr;
262 : }
263 :
264 : }
|