blob: 618c28c0813e137d0482a5d0ceaae68e9ac916f3 [file] [log] [blame]
Jason Samsdbe66d62012-09-17 13:54:41 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Chris Wailes93d6bc82014-07-28 16:54:38 -070017#include <algorithm>
18
Jason Samsdbe66d62012-09-17 13:54:41 -070019#include "rsContext.h"
20#include <time.h>
21
22using namespace android;
23using namespace android::renderscript;
24
25ScriptGroup::ScriptGroup(Context *rsc) : ObjectBase(rsc) {
26}
27
28ScriptGroup::~ScriptGroup() {
29 if (mRSC->mHal.funcs.scriptgroup.destroy) {
30 mRSC->mHal.funcs.scriptgroup.destroy(mRSC, this);
31 }
32
Chris Wailes93d6bc82014-07-28 16:54:38 -070033 for (auto link : mLinks) {
34 delete link;
Jason Samsdbe66d62012-09-17 13:54:41 -070035 }
36}
37
38ScriptGroup::IO::IO(const ScriptKernelID *kid) {
39 mKernel = kid;
40}
41
42ScriptGroup::Node::Node(Script *s) {
43 mScript = s;
44 mSeen = false;
45 mOrder = 0;
46}
47
48ScriptGroup::Node * ScriptGroup::findNode(Script *s) const {
Chris Wailes93d6bc82014-07-28 16:54:38 -070049 for (auto node : mNodes) {
50 for (auto kernelRef : node->mKernels) {
51 if (kernelRef->mScript == s) {
52 return node;
Jason Samsdbe66d62012-09-17 13:54:41 -070053 }
54 }
55 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070056
Chris Wailes44bef6f2014-08-12 13:51:10 -070057 return nullptr;
Jason Samsdbe66d62012-09-17 13:54:41 -070058}
59
Chris Wailes93d6bc82014-07-28 16:54:38 -070060bool ScriptGroup::calcOrderRecurse(Node *node0, int depth) {
61 node0->mSeen = true;
62 if (node0->mOrder < depth) {
63 node0->mOrder = depth;
Jason Samsdbe66d62012-09-17 13:54:41 -070064 }
65 bool ret = true;
Chris Wailes93d6bc82014-07-28 16:54:38 -070066
67 for (auto link : node0->mOutputs) {
Chris Wailes44bef6f2014-08-12 13:51:10 -070068 Node *node1 = nullptr;
Chris Wailes93d6bc82014-07-28 16:54:38 -070069 if (link->mDstField.get()) {
70 node1 = findNode(link->mDstField->mScript);
Jason Samsdbe66d62012-09-17 13:54:41 -070071 } else {
Chris Wailes93d6bc82014-07-28 16:54:38 -070072 node1 = findNode(link->mDstKernel->mScript);
Jason Samsdbe66d62012-09-17 13:54:41 -070073 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070074 if (node1->mSeen) {
Jason Samsdbe66d62012-09-17 13:54:41 -070075 return false;
76 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070077 ret &= calcOrderRecurse(node1, node0->mOrder + 1);
Jason Samsdbe66d62012-09-17 13:54:41 -070078 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070079
Jason Samsdbe66d62012-09-17 13:54:41 -070080 return ret;
81}
82
Jason Samsdbe66d62012-09-17 13:54:41 -070083bool ScriptGroup::calcOrder() {
84 // Make nodes
Chris Wailes93d6bc82014-07-28 16:54:38 -070085
86 for (auto kernelRef : mKernels) {
87 const ScriptKernelID *kernel = kernelRef.get();
88 Node *node = findNode(kernel->mScript);
Chris Wailes44bef6f2014-08-12 13:51:10 -070089 if (node == nullptr) {
Chris Wailes93d6bc82014-07-28 16:54:38 -070090 node = new Node(kernel->mScript);
91 mNodes.push_back(node);
Jason Samsdbe66d62012-09-17 13:54:41 -070092 }
Chris Wailes93d6bc82014-07-28 16:54:38 -070093 node->mKernels.push_back(kernel);
Jason Samsdbe66d62012-09-17 13:54:41 -070094 }
95
96 // add links
Chris Wailes93d6bc82014-07-28 16:54:38 -070097 for (auto link : mLinks) {
98 Node *node = findNode(link->mSource->mScript);
99 node->mOutputs.push_back(link);
Jason Samsdbe66d62012-09-17 13:54:41 -0700100
Chris Wailes93d6bc82014-07-28 16:54:38 -0700101 if (link->mDstKernel.get()) {
102 node = findNode(link->mDstKernel->mScript);
103 node->mInputs.push_back(link);
Jason Samsdbe66d62012-09-17 13:54:41 -0700104 } else {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700105 node = findNode(link->mDstField->mScript);
106 node->mInputs.push_back(link);
Jason Samsdbe66d62012-09-17 13:54:41 -0700107 }
108 }
109
Jason Samsdbe66d62012-09-17 13:54:41 -0700110 // Order nodes
111 bool ret = true;
Chris Wailes93d6bc82014-07-28 16:54:38 -0700112 for (auto n0 : mNodes) {
113 if (n0->mInputs.size() == 0) {
114 for (auto n1 : mNodes) {
115 n1->mSeen = false;
Jason Samsdbe66d62012-09-17 13:54:41 -0700116 }
Chris Wailes93d6bc82014-07-28 16:54:38 -0700117 ret &= calcOrderRecurse(n0, 1);
Jason Samsdbe66d62012-09-17 13:54:41 -0700118 }
119 }
120
Chris Wailes93d6bc82014-07-28 16:54:38 -0700121 for (auto kernelRef : mKernels) {
122 const ScriptKernelID *kernel = kernelRef.get();
123 const Node *node = findNode(kernel->mScript);
Jason Samsdbe66d62012-09-17 13:54:41 -0700124
Chris Wailes93d6bc82014-07-28 16:54:38 -0700125 if (kernel->mHasKernelOutput) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700126 bool found = false;
Chris Wailes93d6bc82014-07-28 16:54:38 -0700127 for (auto output : node->mOutputs) {
128 if (output->mSource.get() == kernel) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700129 found = true;
130 break;
131 }
132 }
Chris Wailes93d6bc82014-07-28 16:54:38 -0700133
Jason Samsdbe66d62012-09-17 13:54:41 -0700134 if (!found) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700135 mOutputs.push_back(new IO(kernel));
Jason Samsdbe66d62012-09-17 13:54:41 -0700136 }
137 }
138
Chris Wailes93d6bc82014-07-28 16:54:38 -0700139 if (kernel->mHasKernelInput) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700140 bool found = false;
Chris Wailes93d6bc82014-07-28 16:54:38 -0700141 for (auto input : node->mInputs) {
142 if (input->mDstKernel.get() == kernel) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700143 found = true;
144 break;
145 }
146 }
147 if (!found) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700148 mInputs.push_back(new IO(kernel));
Jason Samsdbe66d62012-09-17 13:54:41 -0700149 }
150 }
151 }
152
153 // sort
Chris Wailes93d6bc82014-07-28 16:54:38 -0700154 std::stable_sort(mNodes.begin(), mNodes.end(),
155 [](const ScriptGroup::Node* lhs,
156 const ScriptGroup::Node* rhs) {
157 return lhs->mOrder < rhs->mOrder;
158 });
Jason Samsdbe66d62012-09-17 13:54:41 -0700159
160 return ret;
161}
162
163ScriptGroup * ScriptGroup::create(Context *rsc,
164 ScriptKernelID ** kernels, size_t kernelsSize,
165 ScriptKernelID ** src, size_t srcSize,
166 ScriptKernelID ** dstK, size_t dstKSize,
167 ScriptFieldID ** dstF, size_t dstFSize,
168 const Type ** type, size_t typeSize) {
169
170 size_t kernelCount = kernelsSize / sizeof(ScriptKernelID *);
171 size_t linkCount = typeSize / sizeof(Type *);
172
173 //ALOGE("ScriptGroup::create kernels=%i links=%i", (int)kernelCount, (int)linkCount);
174
175
176 // Start by counting unique kernel sources
177
178 ScriptGroup *sg = new ScriptGroup(rsc);
179
180 sg->mKernels.reserve(kernelCount);
181 for (size_t ct=0; ct < kernelCount; ct++) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700182 sg->mKernels.push_back(kernels[ct]);
Jason Samsdbe66d62012-09-17 13:54:41 -0700183 }
184
185 sg->mLinks.reserve(linkCount);
186 for (size_t ct=0; ct < linkCount; ct++) {
187 Link *l = new Link();
188 l->mType = type[ct];
189 l->mSource = src[ct];
190 l->mDstField = dstF[ct];
191 l->mDstKernel = dstK[ct];
Chris Wailes93d6bc82014-07-28 16:54:38 -0700192 sg->mLinks.push_back(l);
Jason Samsdbe66d62012-09-17 13:54:41 -0700193 }
194
195 sg->calcOrder();
196
197 // allocate links
198 for (size_t ct=0; ct < sg->mNodes.size(); ct++) {
199 const Node *n = sg->mNodes[ct];
200 for (size_t ct2=0; ct2 < n->mOutputs.size(); ct2++) {
201 Link *l = n->mOutputs[ct2];
202 if (l->mAlloc.get()) {
203 continue;
204 }
205 const ScriptKernelID *k = l->mSource.get();
206
207 Allocation * alloc = Allocation::createAllocation(rsc,
208 l->mType.get(), RS_ALLOCATION_USAGE_SCRIPT);
209 l->mAlloc = alloc;
210
211 for (size_t ct3=ct2+1; ct3 < n->mOutputs.size(); ct3++) {
212 if (n->mOutputs[ct3]->mSource.get() == l->mSource.get()) {
213 n->mOutputs[ct3]->mAlloc = alloc;
214 }
215 }
216 }
217 }
218
219 if (rsc->mHal.funcs.scriptgroup.init) {
220 rsc->mHal.funcs.scriptgroup.init(rsc, sg);
221 }
Stephen Hines61c86952013-04-09 17:34:43 -0700222 sg->incUserRef();
Jason Samsdbe66d62012-09-17 13:54:41 -0700223 return sg;
224}
225
226void ScriptGroup::setInput(Context *rsc, ScriptKernelID *kid, Allocation *a) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700227 for (auto input : mInputs) {
228 if (input->mKernel == kid) {
229 input->mAlloc = a;
Jason Samsdbe66d62012-09-17 13:54:41 -0700230
231 if (rsc->mHal.funcs.scriptgroup.setInput) {
232 rsc->mHal.funcs.scriptgroup.setInput(rsc, this, kid, a);
233 }
234 return;
235 }
236 }
237 rsAssert(!"ScriptGroup:setInput kid not found");
238}
239
240void ScriptGroup::setOutput(Context *rsc, ScriptKernelID *kid, Allocation *a) {
Chris Wailes93d6bc82014-07-28 16:54:38 -0700241 for (auto output : mOutputs) {
242 if (output->mKernel == kid) {
243 output->mAlloc = a;
Jason Samsdbe66d62012-09-17 13:54:41 -0700244
245 if (rsc->mHal.funcs.scriptgroup.setOutput) {
246 rsc->mHal.funcs.scriptgroup.setOutput(rsc, this, kid, a);
247 }
248 return;
249 }
250 }
251 rsAssert(!"ScriptGroup:setOutput kid not found");
252}
253
Yang Ni5f6f16f2014-07-25 13:51:09 -0700254bool ScriptGroup::validateInputAndOutput(Context *rsc) {
255 for(size_t i = 0; i < mInputs.size(); i++) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700256 if (mInputs[i]->mAlloc.get() == nullptr) {
Yang Ni5f6f16f2014-07-25 13:51:09 -0700257 rsc->setError(RS_ERROR_BAD_VALUE, "ScriptGroup missing input.");
258 return false;
259 }
260 }
261
262 for(size_t i = 0; i < mOutputs.size(); i++) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700263 if (mOutputs[i]->mAlloc.get() == nullptr) {
Yang Ni5f6f16f2014-07-25 13:51:09 -0700264 rsc->setError(RS_ERROR_BAD_VALUE, "ScriptGroup missing output.");
265 return false;
266 }
267 }
268
269 return true;
270}
271
Jason Samsdbe66d62012-09-17 13:54:41 -0700272void ScriptGroup::execute(Context *rsc) {
Yang Ni5f6f16f2014-07-25 13:51:09 -0700273
274 if (!validateInputAndOutput(rsc)) {
275 return;
276 }
277
Jason Samsdbe66d62012-09-17 13:54:41 -0700278 //ALOGE("ScriptGroup::execute");
279 if (rsc->mHal.funcs.scriptgroup.execute) {
280 rsc->mHal.funcs.scriptgroup.execute(rsc, this);
281 return;
282 }
283
Chris Wailes93d6bc82014-07-28 16:54:38 -0700284 for (auto node : mNodes) {
285 for (auto kernel : node->mKernels) {
Chris Wailes44bef6f2014-08-12 13:51:10 -0700286 Allocation *ain = nullptr;
287 Allocation *aout = nullptr;
Jason Samsdbe66d62012-09-17 13:54:41 -0700288
Chris Wailes93d6bc82014-07-28 16:54:38 -0700289 for (auto nodeInput : node->mInputs) {
290 if (nodeInput->mDstKernel.get() == kernel) {
291 ain = nodeInput->mAlloc.get();
Jason Samsdbe66d62012-09-17 13:54:41 -0700292 }
293 }
294
Chris Wailes93d6bc82014-07-28 16:54:38 -0700295 for (auto sgInput : mInputs) {
296 if (sgInput->mKernel == kernel) {
297 ain = sgInput->mAlloc.get();
Jason Samsdbe66d62012-09-17 13:54:41 -0700298 }
299 }
Chris Wailes93d6bc82014-07-28 16:54:38 -0700300
301 for (auto nodeOutput : node->mOutputs) {
302 if (nodeOutput->mDstKernel.get() == kernel) {
303 aout = nodeOutput->mAlloc.get();
304 }
305 }
306
307 for (auto sgOutput : mOutputs) {
308 if (sgOutput->mKernel == kernel) {
309 aout = sgOutput->mAlloc.get();
Jason Samsdbe66d62012-09-17 13:54:41 -0700310 }
311 }
312
Chris Wailes44bef6f2014-08-12 13:51:10 -0700313 if (ain == nullptr) {
314 node->mScript->runForEach(rsc, kernel->mSlot, nullptr, 0, aout,
315 nullptr, 0);
Chris Wailesf3712132014-07-16 15:18:30 -0700316 } else {
317 const Allocation *ains[1] = {ain};
Chris Wailes93d6bc82014-07-28 16:54:38 -0700318 node->mScript->runForEach(rsc, kernel->mSlot, ains,
319 sizeof(ains) / sizeof(RsAllocation),
Chris Wailes44bef6f2014-08-12 13:51:10 -0700320 aout, nullptr, 0);
Chris Wailesf3712132014-07-16 15:18:30 -0700321 }
Jason Samsdbe66d62012-09-17 13:54:41 -0700322 }
Jason Samsdbe66d62012-09-17 13:54:41 -0700323 }
324
325}
326
327void ScriptGroup::serialize(Context *rsc, OStream *stream) const {
328}
329
330RsA3DClassID ScriptGroup::getClassId() const {
331 return RS_A3D_CLASS_ID_SCRIPT_GROUP;
332}
333
334ScriptGroup::Link::Link() {
335}
336
337ScriptGroup::Link::~Link() {
338}
339
340namespace android {
341namespace renderscript {
342
343
344RsScriptGroup rsi_ScriptGroupCreate(Context *rsc,
345 RsScriptKernelID * kernels, size_t kernelsSize,
346 RsScriptKernelID * src, size_t srcSize,
347 RsScriptKernelID * dstK, size_t dstKSize,
348 RsScriptFieldID * dstF, size_t dstFSize,
349 const RsType * type, size_t typeSize) {
350
351
352 return ScriptGroup::create(rsc,
353 (ScriptKernelID **) kernels, kernelsSize,
354 (ScriptKernelID **) src, srcSize,
355 (ScriptKernelID **) dstK, dstKSize,
356 (ScriptFieldID **) dstF, dstFSize,
357 (const Type **) type, typeSize);
358}
359
360
361void rsi_ScriptGroupSetInput(Context *rsc, RsScriptGroup sg, RsScriptKernelID kid,
362 RsAllocation alloc) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700363 ScriptGroup *s = (ScriptGroup *)sg;
364 s->setInput(rsc, (ScriptKernelID *)kid, (Allocation *)alloc);
365}
366
367void rsi_ScriptGroupSetOutput(Context *rsc, RsScriptGroup sg, RsScriptKernelID kid,
368 RsAllocation alloc) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700369 ScriptGroup *s = (ScriptGroup *)sg;
370 s->setOutput(rsc, (ScriptKernelID *)kid, (Allocation *)alloc);
371}
372
373void rsi_ScriptGroupExecute(Context *rsc, RsScriptGroup sg) {
Jason Samsdbe66d62012-09-17 13:54:41 -0700374 ScriptGroup *s = (ScriptGroup *)sg;
375 s->execute(rsc);
376}
377
378}
379}