• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 #include "rsContext.h"
18 #include <time.h>
19 
20 using namespace android;
21 using namespace android::renderscript;
22 
ScriptGroup(Context * rsc)23 ScriptGroup::ScriptGroup(Context *rsc) : ObjectBase(rsc) {
24 }
25 
~ScriptGroup()26 ScriptGroup::~ScriptGroup() {
27     if (mRSC->mHal.funcs.scriptgroup.destroy) {
28         mRSC->mHal.funcs.scriptgroup.destroy(mRSC, this);
29     }
30 
31     for (size_t ct=0; ct < mLinks.size(); ct++) {
32         delete mLinks[ct];
33     }
34 }
35 
IO(const ScriptKernelID * kid)36 ScriptGroup::IO::IO(const ScriptKernelID *kid) {
37     mKernel = kid;
38 }
39 
Node(Script * s)40 ScriptGroup::Node::Node(Script *s) {
41     mScript = s;
42     mSeen = false;
43     mOrder = 0;
44 }
45 
findNode(Script * s) const46 ScriptGroup::Node * ScriptGroup::findNode(Script *s) const {
47     //ALOGE("find %p   %i", s, (int)mNodes.size());
48     for (size_t ct=0; ct < mNodes.size(); ct++) {
49         Node *n = mNodes[ct];
50         for (size_t ct2=0; ct2 < n->mKernels.size(); ct2++) {
51             if (n->mKernels[ct2]->mScript == s) {
52                 return n;
53             }
54         }
55     }
56     return NULL;
57 }
58 
calcOrderRecurse(Node * n,int depth)59 bool ScriptGroup::calcOrderRecurse(Node *n, int depth) {
60     n->mSeen = true;
61     if (n->mOrder < depth) {
62         n->mOrder = depth;
63     }
64     bool ret = true;
65     for (size_t ct=0; ct < n->mOutputs.size(); ct++) {
66         const Link *l = n->mOutputs[ct];
67         Node *nt = NULL;
68         if (l->mDstField.get()) {
69             nt = findNode(l->mDstField->mScript);
70         } else {
71             nt = findNode(l->mDstKernel->mScript);
72         }
73         if (nt->mSeen) {
74             return false;
75         }
76         ret &= calcOrderRecurse(nt, n->mOrder + 1);
77     }
78     return ret;
79 }
80 
81 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
CompareNodeForSort(ScriptGroup::Node * const * lhs,ScriptGroup::Node * const * rhs)82 static int CompareNodeForSort(ScriptGroup::Node *const* lhs,
83                               ScriptGroup::Node *const* rhs) {
84     if (lhs[0]->mOrder > rhs[0]->mOrder) {
85         return 1;
86     }
87     return 0;
88 }
89 #else
90 class NodeCompare {
91 public:
operator ()(const ScriptGroup::Node * lhs,const ScriptGroup::Node * rhs)92     bool operator() (const ScriptGroup::Node* lhs,
93                      const ScriptGroup::Node* rhs) {
94         if (lhs->mOrder > rhs->mOrder) {
95             return true;
96         }
97         return false;
98     }
99 };
100 #endif
101 
calcOrder()102 bool ScriptGroup::calcOrder() {
103     // Make nodes
104     for (size_t ct=0; ct < mKernels.size(); ct++) {
105         const ScriptKernelID *k = mKernels[ct].get();
106         //ALOGE(" kernel %i, %p  s=%p", (int)ct, k, mKernels[ct]->mScript);
107         Node *n = findNode(k->mScript);
108         //ALOGE("    n = %p", n);
109         if (n == NULL) {
110             n = new Node(k->mScript);
111             mNodes.add(n);
112         }
113         n->mKernels.add(k);
114     }
115 
116     // add links
117     //ALOGE("link count %i", (int)mLinks.size());
118     for (size_t ct=0; ct < mLinks.size(); ct++) {
119         Link *l = mLinks[ct];
120         //ALOGE("link  %i %p", (int)ct, l);
121         Node *n = findNode(l->mSource->mScript);
122         //ALOGE("link n %p", n);
123         n->mOutputs.add(l);
124 
125         if (l->mDstKernel.get()) {
126             //ALOGE("l->mDstKernel.get() %p", l->mDstKernel.get());
127             n = findNode(l->mDstKernel->mScript);
128             //ALOGE("  n1 %p", n);
129             n->mInputs.add(l);
130         } else {
131             n = findNode(l->mDstField->mScript);
132             //ALOGE("  n2 %p", n);
133             n->mInputs.add(l);
134         }
135     }
136 
137     //ALOGE("node count %i", (int)mNodes.size());
138     // Order nodes
139     bool ret = true;
140     for (size_t ct=0; ct < mNodes.size(); ct++) {
141         Node *n = mNodes[ct];
142         if (n->mInputs.size() == 0) {
143             for (size_t ct2=0; ct2 < mNodes.size(); ct2++) {
144                 mNodes[ct2]->mSeen = false;
145             }
146             ret &= calcOrderRecurse(n, 0);
147         }
148     }
149 
150     for (size_t ct=0; ct < mKernels.size(); ct++) {
151         const ScriptKernelID *k = mKernels[ct].get();
152         const Node *n = findNode(k->mScript);
153 
154         if (k->mHasKernelOutput) {
155             bool found = false;
156             for (size_t ct2=0; ct2 < n->mOutputs.size(); ct2++) {
157                 if (n->mOutputs[ct2]->mSource.get() == k) {
158                     found = true;
159                     break;
160                 }
161             }
162             if (!found) {
163                 //ALOGE("add io out %p", k);
164                 mOutputs.add(new IO(k));
165             }
166         }
167 
168         if (k->mHasKernelInput) {
169             bool found = false;
170             for (size_t ct2=0; ct2 < n->mInputs.size(); ct2++) {
171                 if (n->mInputs[ct2]->mDstKernel.get() == k) {
172                     found = true;
173                     break;
174                 }
175             }
176             if (!found) {
177                 //ALOGE("add io in %p", k);
178                 mInputs.add(new IO(k));
179             }
180         }
181     }
182 
183     // sort
184 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
185     mNodes.sort(&CompareNodeForSort);
186 #else
187     std::sort(mNodes.begin(), mNodes.end(), NodeCompare());
188 #endif
189 
190     return ret;
191 }
192 
create(Context * rsc,ScriptKernelID ** kernels,size_t kernelsSize,ScriptKernelID ** src,size_t srcSize,ScriptKernelID ** dstK,size_t dstKSize,ScriptFieldID ** dstF,size_t dstFSize,const Type ** type,size_t typeSize)193 ScriptGroup * ScriptGroup::create(Context *rsc,
194                            ScriptKernelID ** kernels, size_t kernelsSize,
195                            ScriptKernelID ** src, size_t srcSize,
196                            ScriptKernelID ** dstK, size_t dstKSize,
197                            ScriptFieldID  ** dstF, size_t dstFSize,
198                            const Type ** type, size_t typeSize) {
199 
200     size_t kernelCount = kernelsSize / sizeof(ScriptKernelID *);
201     size_t linkCount = typeSize / sizeof(Type *);
202 
203     //ALOGE("ScriptGroup::create kernels=%i  links=%i", (int)kernelCount, (int)linkCount);
204 
205 
206     // Start by counting unique kernel sources
207 
208     ScriptGroup *sg = new ScriptGroup(rsc);
209 
210     sg->mKernels.reserve(kernelCount);
211     for (size_t ct=0; ct < kernelCount; ct++) {
212         sg->mKernels.add(kernels[ct]);
213     }
214 
215     sg->mLinks.reserve(linkCount);
216     for (size_t ct=0; ct < linkCount; ct++) {
217         Link *l = new Link();
218         l->mType = type[ct];
219         l->mSource = src[ct];
220         l->mDstField = dstF[ct];
221         l->mDstKernel = dstK[ct];
222         sg->mLinks.add(l);
223     }
224 
225     sg->calcOrder();
226 
227     // allocate links
228     for (size_t ct=0; ct < sg->mNodes.size(); ct++) {
229         const Node *n = sg->mNodes[ct];
230         for (size_t ct2=0; ct2 < n->mOutputs.size(); ct2++) {
231             Link *l = n->mOutputs[ct2];
232             if (l->mAlloc.get()) {
233                 continue;
234             }
235             const ScriptKernelID *k = l->mSource.get();
236 
237             Allocation * alloc = Allocation::createAllocation(rsc,
238                     l->mType.get(), RS_ALLOCATION_USAGE_SCRIPT);
239             l->mAlloc = alloc;
240 
241             for (size_t ct3=ct2+1; ct3 < n->mOutputs.size(); ct3++) {
242                 if (n->mOutputs[ct3]->mSource.get() == l->mSource.get()) {
243                     n->mOutputs[ct3]->mAlloc = alloc;
244                 }
245             }
246         }
247     }
248 
249     if (rsc->mHal.funcs.scriptgroup.init) {
250         rsc->mHal.funcs.scriptgroup.init(rsc, sg);
251     }
252     sg->incUserRef();
253     return sg;
254 }
255 
setInput(Context * rsc,ScriptKernelID * kid,Allocation * a)256 void ScriptGroup::setInput(Context *rsc, ScriptKernelID *kid, Allocation *a) {
257     for (size_t ct=0; ct < mInputs.size(); ct++) {
258         if (mInputs[ct]->mKernel == kid) {
259             mInputs[ct]->mAlloc = a;
260 
261             if (rsc->mHal.funcs.scriptgroup.setInput) {
262                 rsc->mHal.funcs.scriptgroup.setInput(rsc, this, kid, a);
263             }
264             return;
265         }
266     }
267     rsAssert(!"ScriptGroup:setInput kid not found");
268 }
269 
setOutput(Context * rsc,ScriptKernelID * kid,Allocation * a)270 void ScriptGroup::setOutput(Context *rsc, ScriptKernelID *kid, Allocation *a) {
271     for (size_t ct=0; ct < mOutputs.size(); ct++) {
272         if (mOutputs[ct]->mKernel == kid) {
273             mOutputs[ct]->mAlloc = a;
274 
275             if (rsc->mHal.funcs.scriptgroup.setOutput) {
276                 rsc->mHal.funcs.scriptgroup.setOutput(rsc, this, kid, a);
277             }
278             return;
279         }
280     }
281     rsAssert(!"ScriptGroup:setOutput kid not found");
282 }
283 
validateInputAndOutput(Context * rsc)284 bool ScriptGroup::validateInputAndOutput(Context *rsc) {
285     for(size_t i = 0; i < mInputs.size(); i++) {
286         if (mInputs[i]->mAlloc.get() == NULL) {
287             rsc->setError(RS_ERROR_BAD_VALUE, "ScriptGroup missing input.");
288             return false;
289         }
290     }
291 
292     for(size_t i = 0; i < mOutputs.size(); i++) {
293         if (mOutputs[i]->mAlloc.get() == NULL) {
294             rsc->setError(RS_ERROR_BAD_VALUE, "ScriptGroup missing output.");
295             return false;
296         }
297     }
298 
299     return true;
300 }
301 
execute(Context * rsc)302 void ScriptGroup::execute(Context *rsc) {
303 
304     if (!validateInputAndOutput(rsc)) {
305         return;
306     }
307 
308     //ALOGE("ScriptGroup::execute");
309     if (rsc->mHal.funcs.scriptgroup.execute) {
310         rsc->mHal.funcs.scriptgroup.execute(rsc, this);
311         return;
312     }
313 
314     for (size_t ct=0; ct < mNodes.size(); ct++) {
315         Node *n = mNodes[ct];
316         //ALOGE("node %i, order %i, in %i out %i", (int)ct, n->mOrder, (int)n->mInputs.size(), (int)n->mOutputs.size());
317 
318         for (size_t ct2=0; ct2 < n->mKernels.size(); ct2++) {
319             const ScriptKernelID *k = n->mKernels[ct2];
320             Allocation *ain = NULL;
321             Allocation *aout = NULL;
322 
323             for (size_t ct3=0; ct3 < n->mInputs.size(); ct3++) {
324                 if (n->mInputs[ct3]->mDstKernel.get() == k) {
325                     ain = n->mInputs[ct3]->mAlloc.get();
326                     //ALOGE(" link in %p", ain);
327                 }
328             }
329             for (size_t ct3=0; ct3 < mInputs.size(); ct3++) {
330                 if (mInputs[ct3]->mKernel == k) {
331                     ain = mInputs[ct3]->mAlloc.get();
332                     //ALOGE(" io in %p", ain);
333                 }
334             }
335 
336             for (size_t ct3=0; ct3 < n->mOutputs.size(); ct3++) {
337                 if (n->mOutputs[ct3]->mSource.get() == k) {
338                     aout = n->mOutputs[ct3]->mAlloc.get();
339                     //ALOGE(" link out %p", aout);
340                 }
341             }
342             for (size_t ct3=0; ct3 < mOutputs.size(); ct3++) {
343                 if (mOutputs[ct3]->mKernel == k) {
344                     aout = mOutputs[ct3]->mAlloc.get();
345                     //ALOGE(" io out %p", aout);
346                 }
347             }
348 
349             n->mScript->runForEach(rsc, k->mSlot, ain, aout, NULL, 0);
350         }
351 
352     }
353 
354 }
355 
serialize(Context * rsc,OStream * stream) const356 void ScriptGroup::serialize(Context *rsc, OStream *stream) const {
357 }
358 
getClassId() const359 RsA3DClassID ScriptGroup::getClassId() const {
360     return RS_A3D_CLASS_ID_SCRIPT_GROUP;
361 }
362 
Link()363 ScriptGroup::Link::Link() {
364 }
365 
~Link()366 ScriptGroup::Link::~Link() {
367 }
368 
369 namespace android {
370 namespace renderscript {
371 
372 
rsi_ScriptGroupCreate(Context * rsc,RsScriptKernelID * kernels,size_t kernelsSize,RsScriptKernelID * src,size_t srcSize,RsScriptKernelID * dstK,size_t dstKSize,RsScriptFieldID * dstF,size_t dstFSize,const RsType * type,size_t typeSize)373 RsScriptGroup rsi_ScriptGroupCreate(Context *rsc,
374                            RsScriptKernelID * kernels, size_t kernelsSize,
375                            RsScriptKernelID * src, size_t srcSize,
376                            RsScriptKernelID * dstK, size_t dstKSize,
377                            RsScriptFieldID * dstF, size_t dstFSize,
378                            const RsType * type, size_t typeSize) {
379 
380 
381     return ScriptGroup::create(rsc,
382                                (ScriptKernelID **) kernels, kernelsSize,
383                                (ScriptKernelID **) src, srcSize,
384                                (ScriptKernelID **) dstK, dstKSize,
385                                (ScriptFieldID  **) dstF, dstFSize,
386                                (const Type **) type, typeSize);
387 }
388 
389 
rsi_ScriptGroupSetInput(Context * rsc,RsScriptGroup sg,RsScriptKernelID kid,RsAllocation alloc)390 void rsi_ScriptGroupSetInput(Context *rsc, RsScriptGroup sg, RsScriptKernelID kid,
391         RsAllocation alloc) {
392     //ALOGE("rsi_ScriptGroupSetInput");
393     ScriptGroup *s = (ScriptGroup *)sg;
394     s->setInput(rsc, (ScriptKernelID *)kid, (Allocation *)alloc);
395 }
396 
rsi_ScriptGroupSetOutput(Context * rsc,RsScriptGroup sg,RsScriptKernelID kid,RsAllocation alloc)397 void rsi_ScriptGroupSetOutput(Context *rsc, RsScriptGroup sg, RsScriptKernelID kid,
398         RsAllocation alloc) {
399     //ALOGE("rsi_ScriptGroupSetOutput");
400     ScriptGroup *s = (ScriptGroup *)sg;
401     s->setOutput(rsc, (ScriptKernelID *)kid, (Allocation *)alloc);
402 }
403 
rsi_ScriptGroupExecute(Context * rsc,RsScriptGroup sg)404 void rsi_ScriptGroupExecute(Context *rsc, RsScriptGroup sg) {
405     //ALOGE("rsi_ScriptGroupExecute");
406     ScriptGroup *s = (ScriptGroup *)sg;
407     s->execute(rsc);
408 }
409 
410 }
411 }
412 
413