• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011-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 "rsdCore.h"
18 #include "rsdBcc.h"
19 #include "rsdRuntime.h"
20 #include "rsdAllocation.h"
21 #include "rsdIntrinsics.h"
22 
23 #include "rsContext.h"
24 #include "rsElement.h"
25 #include "rsScriptC.h"
26 
27 #include "utils/Vector.h"
28 #include "utils/Timers.h"
29 #include "utils/StopWatch.h"
30 #include "utils/String8.h"
31 
32 #include <dlfcn.h>
33 #include <stdio.h>
34 #include <string.h>
35 
36 using namespace android;
37 using namespace android::renderscript;
38 
39 #define MAXLINE 500
40 #define MAKE_STR_HELPER(S) #S
41 #define MAKE_STR(S) MAKE_STR_HELPER(S)
42 #define EXPORT_VAR_STR "exportVarCount: "
43 #define EXPORT_VAR_STR_LEN strlen(EXPORT_VAR_STR)
44 #define EXPORT_FUNC_STR "exportFuncCount: "
45 #define EXPORT_FUNC_STR_LEN strlen(EXPORT_FUNC_STR)
46 #define EXPORT_FOREACH_STR "exportForEachCount: "
47 #define EXPORT_FOREACH_STR_LEN strlen(EXPORT_FOREACH_STR)
48 #define OBJECT_SLOT_STR "objectSlotCount: "
49 #define OBJECT_SLOT_STR_LEN strlen(OBJECT_SLOT_STR)
50 
51 
52 
setTLS(Script * sc)53 static Script * setTLS(Script *sc) {
54     ScriptTLSStruct * tls = (ScriptTLSStruct *)pthread_getspecific(rsdgThreadTLSKey);
55     rsAssert(tls);
56     Script *old = tls->mScript;
57     tls->mScript = sc;
58     return old;
59 }
60 
61 
rsdScriptInit(const Context * rsc,ScriptC * script,char const * resName,char const * cacheDir,uint8_t const * bitcode,size_t bitcodeSize,uint32_t flags)62 bool rsdScriptInit(const Context *rsc,
63                      ScriptC *script,
64                      char const *resName,
65                      char const *cacheDir,
66                      uint8_t const *bitcode,
67                      size_t bitcodeSize,
68                      uint32_t flags) {
69     //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
70     //ALOGE("rsdScriptInit %p %p", rsc, script);
71 
72     pthread_mutex_lock(&rsdgInitMutex);
73 
74     String8 scriptSOName(cacheDir);
75     scriptSOName = scriptSOName.getPathDir();
76     scriptSOName.appendPath("lib");
77     scriptSOName.append("/lib");
78     scriptSOName.append(resName);
79     scriptSOName.append(".so");
80 
81     String8 scriptInfoName(cacheDir);
82     scriptInfoName = scriptInfoName.getPathDir();
83     scriptInfoName.appendPath("lib/");
84     scriptInfoName.append(resName);
85     scriptInfoName.append(".bcinfo");
86 
87     void *scriptSO = NULL;
88     FILE *fp = NULL;
89     DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript));
90     if (drv == NULL) {
91         goto error;
92     }
93     script->mHal.drv = drv;
94 
95     ALOGE("Opening up info object: %s", scriptInfoName.string());
96 
97     fp = fopen(scriptInfoName.string(), "r");
98     if (!fp) {
99         ALOGE("Unable to open info file: %s", scriptInfoName.string());
100         goto error;
101     }
102 
103     ALOGE("Opening up shared object: %s", scriptSOName.string());
104     scriptSO = dlopen(scriptSOName.string(), RTLD_NOW | RTLD_LOCAL);
105     if (scriptSO == NULL) {
106         ALOGE("Unable to open shared library (%s): %s",
107               scriptSOName.string(), dlerror());
108         goto error;
109     }
110     drv->mScriptSO = scriptSO;
111 
112     if (scriptSO) {
113         char line[MAXLINE];
114         drv->mScriptSO = scriptSO;
115         drv->mRoot = (RootFunc_t) dlsym(scriptSO, "root");
116         if (drv->mRoot) {
117             ALOGE("Found root(): %p", drv->mRoot);
118         }
119         drv->mRootExpand = (RootFunc_t) dlsym(scriptSO, "root.expand");
120         if (drv->mRootExpand) {
121             ALOGE("Found root.expand(): %p", drv->mRootExpand);
122         }
123         drv->mInit = (InvokeFunc_t) dlsym(scriptSO, "init");
124         if (drv->mInit) {
125             ALOGE("Found init(): %p", drv->mInit);
126         }
127         drv->mFreeChildren = (InvokeFunc_t) dlsym(scriptSO, ".rs.dtor");
128         if (drv->mFreeChildren) {
129             ALOGE("Found .rs.dtor(): %p", drv->mFreeChildren);
130         }
131 
132         size_t varCount = 0;
133         if (fgets(line, MAXLINE, fp) == NULL) {
134             goto error;
135         }
136         if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
137             ALOGE("Invalid export var count!: %s", line);
138             goto error;
139         }
140 
141         script->mHal.info.exportedVariableCount = varCount;
142         ALOGE("varCount: %zu", varCount);
143         if (varCount > 0) {
144             // Start by creating/zeroing this member, since we don't want to
145             // accidentally clean up invalid pointers later (if we error out).
146             drv->mFieldIsObject = new bool[varCount];
147             if (drv->mFieldIsObject == NULL) {
148                 goto error;
149             }
150             memset(drv->mFieldIsObject, 0,
151                    varCount * sizeof(*drv->mFieldIsObject));
152             drv->mFieldAddress = new void*[varCount];
153             if (drv->mFieldAddress == NULL) {
154                 goto error;
155             }
156             for (size_t i = 0; i < varCount; ++i) {
157                 if (fgets(line, MAXLINE, fp) == NULL) {
158                     goto error;
159                 }
160                 char *c = strrchr(line, '\n');
161                 if (c) {
162                     *c = '\0';
163                 }
164                 drv->mFieldAddress[i] = dlsym(scriptSO, line);
165                 if (drv->mFieldAddress[i] == NULL) {
166                     ALOGE("Failed to find variable address for %s: %s",
167                           line, dlerror());
168                     // Not a critical error if we don't find a global variable.
169                 }
170                 else {
171                     ALOGE("Found variable %s at %p", line,
172                           drv->mFieldAddress[i]);
173                 }
174             }
175         }
176 
177         size_t funcCount = 0;
178         if (fgets(line, MAXLINE, fp) == NULL) {
179             goto error;
180         }
181         if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
182             ALOGE("Invalid export func count!: %s", line);
183             goto error;
184         }
185 
186         script->mHal.info.exportedFunctionCount = funcCount;
187         ALOGE("funcCount: %zu", funcCount);
188 
189         if (funcCount > 0) {
190             drv->mInvokeFunctions = new InvokeFunc_t[funcCount];
191             if (drv->mInvokeFunctions == NULL) {
192                 goto error;
193             }
194             for (size_t i = 0; i < funcCount; ++i) {
195                 if (fgets(line, MAXLINE, fp) == NULL) {
196                     goto error;
197                 }
198                 char *c = strrchr(line, '\n');
199                 if (c) {
200                     *c = '\0';
201                 }
202 
203                 drv->mInvokeFunctions[i] =
204                         (InvokeFunc_t) dlsym(scriptSO, line);
205                 if (drv->mInvokeFunctions[i] == NULL) {
206                     ALOGE("Failed to get function address for %s(): %s",
207                           line, dlerror());
208                     goto error;
209                 }
210                 else {
211                     ALOGE("Found InvokeFunc_t %s at %p", line,
212                           drv->mInvokeFunctions[i]);
213                 }
214             }
215         }
216 
217         size_t forEachCount = 0;
218         if (fgets(line, MAXLINE, fp) == NULL) {
219             goto error;
220         }
221         if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
222             ALOGE("Invalid export forEach count!: %s", line);
223             goto error;
224         }
225 
226         if (forEachCount > 0) {
227 
228             drv->mForEachSignatures = new uint32_t[forEachCount];
229             if (drv->mForEachSignatures == NULL) {
230                 goto error;
231             }
232             drv->mForEachFunctions = new ForEachFunc_t[forEachCount];
233             if (drv->mForEachFunctions == NULL) {
234                 goto error;
235             }
236             for (size_t i = 0; i < forEachCount; ++i) {
237                 unsigned int tmpSig = 0;
238                 char tmpName[MAXLINE];
239 
240                 if (fgets(line, MAXLINE, fp) == NULL) {
241                     goto error;
242                 }
243                 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
244                            &tmpSig, tmpName) != 2) {
245                     ALOGE("Invalid export forEach!: %s", line);
246                     goto error;
247                 }
248 
249                 drv->mForEachSignatures[i] = tmpSig;
250                 drv->mForEachFunctions[i] =
251                         (ForEachFunc_t) dlsym(scriptSO, tmpName);
252                 if (drv->mForEachFunctions[i] == NULL) {
253                     ALOGE("Failed to find forEach function address for %s: %s",
254                           tmpName, dlerror());
255                     goto error;
256                 }
257                 else {
258                     // TODO - Maybe add ForEachExpandPass to .so creation and
259                     // then lookup the ".expand" version of these kernels
260                     // instead.
261                     ALOGE("Found forEach %s at %p", tmpName,
262                           drv->mForEachFunctions[i]);
263                 }
264             }
265         }
266 
267         size_t objectSlotCount = 0;
268         if (fgets(line, MAXLINE, fp) == NULL) {
269             goto error;
270         }
271         if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
272             ALOGE("Invalid object slot count!: %s", line);
273             goto error;
274         }
275 
276         if (objectSlotCount > 0) {
277             rsAssert(varCount > 0);
278             for (size_t i = 0; i < objectSlotCount; ++i) {
279                 uint32_t varNum = 0;
280                 if (fgets(line, MAXLINE, fp) == NULL) {
281                     goto error;
282                 }
283                 if (sscanf(line, "%u", &varNum) != 1) {
284                     ALOGE("Invalid object slot!: %s", line);
285                     goto error;
286                 }
287 
288                 if (varNum < varCount) {
289                     drv->mFieldIsObject[varNum] = true;
290                 }
291             }
292         }
293 
294         script->mHal.info.exportedPragmaCount = 0;
295 
296         if (drv->mRootExpand) {
297             script->mHal.info.root = drv->mRootExpand;
298         } else {
299             script->mHal.info.root = drv->mRoot;
300         }
301 
302         if (varCount > 0) {
303             drv->mBoundAllocs = new Allocation *[varCount];
304             memset(drv->mBoundAllocs, 0, varCount * sizeof(*drv->mBoundAllocs));
305         }
306 
307         script->mHal.info.isThreadable = true;
308 
309         if (scriptSO == (void*)1) {
310             rsdLookupRuntimeStub(script, "acos");
311         }
312     }
313 
314     fclose(fp);
315     pthread_mutex_unlock(&rsdgInitMutex);
316     return true;
317 
318 error:
319 
320     fclose(fp);
321     pthread_mutex_unlock(&rsdgInitMutex);
322     if (drv) {
323         delete[] drv->mInvokeFunctions;
324         delete[] drv->mForEachFunctions;
325         delete[] drv->mFieldAddress;
326         delete[] drv->mFieldIsObject;
327         delete[] drv->mForEachSignatures;
328         delete[] drv->mBoundAllocs;
329         if (drv->mScriptSO) {
330             dlclose(drv->mScriptSO);
331         }
332         free(drv);
333     }
334     script->mHal.drv = NULL;
335     return false;
336 
337 }
338 
rsdInitIntrinsic(const Context * rsc,Script * s,RsScriptIntrinsicID iid,Element * e)339 bool rsdInitIntrinsic(const Context *rsc, Script *s, RsScriptIntrinsicID iid, Element *e) {
340     pthread_mutex_lock(&rsdgInitMutex);
341 
342     DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript));
343     if (drv == NULL) {
344         goto error;
345     }
346     s->mHal.drv = drv;
347     drv->mIntrinsicID = iid;
348     drv->mIntrinsicData = rsdIntrinsic_Init(rsc, s, iid, &drv->mIntrinsicFuncs);
349     s->mHal.info.isThreadable = true;
350 
351     pthread_mutex_unlock(&rsdgInitMutex);
352     return true;
353 
354 error:
355     pthread_mutex_unlock(&rsdgInitMutex);
356     return false;
357 }
358 
359 typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
360 
wc_xy(void * usr,uint32_t idx)361 static void wc_xy(void *usr, uint32_t idx) {
362     MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
363     RsForEachStubParamStruct p;
364     memcpy(&p, &mtls->fep, sizeof(p));
365     RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv;
366     uint32_t sig = mtls->sig;
367 
368     rs_t bare_fn = (rs_t) mtls->kernel;
369     while (1) {
370         uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
371         uint32_t yStart = mtls->yStart + slice * mtls->mSliceSize;
372         uint32_t yEnd = yStart + mtls->mSliceSize;
373         yEnd = rsMin(yEnd, mtls->yEnd);
374         if (yEnd <= yStart) {
375             return;
376         }
377 
378         //ALOGE("usr idx %i, x %i,%i  y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
379         //ALOGE("usr ptr in %p,  out %p", mtls->ptrIn, mtls->ptrOut);
380         for (p.y = yStart; p.y < yEnd; p.y++) {
381             p.out = mtls->fep.ptrOut + (mtls->fep.yStrideOut * p.y);
382             p.in = mtls->fep.ptrIn + (mtls->fep.yStrideIn * p.y);
383             for (uint32_t x = mtls->xStart; x < mtls->xEnd; ++x) {
384                 bare_fn(p.in, p.out, p.usr, x, p.y, 0, 0);
385                 p.in = (char *)(p.in) + mtls->fep.eStrideIn;
386                 p.out = (char *)(p.out) + mtls->fep.eStrideOut;
387             }
388         }
389     }
390 }
391 
wc_x(void * usr,uint32_t idx)392 static void wc_x(void *usr, uint32_t idx) {
393     MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
394     RsForEachStubParamStruct p;
395     memcpy(&p, &mtls->fep, sizeof(p));
396     RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv;
397     uint32_t sig = mtls->sig;
398 
399     rs_t bare_fn = (rs_t) mtls->kernel;
400     while (1) {
401         uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
402         uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize;
403         uint32_t xEnd = xStart + mtls->mSliceSize;
404         xEnd = rsMin(xEnd, mtls->xEnd);
405         if (xEnd <= xStart) {
406             return;
407         }
408 
409         //ALOGE("usr slice %i idx %i, x %i,%i", slice, idx, xStart, xEnd);
410         //ALOGE("usr ptr in %p,  out %p", mtls->ptrIn, mtls->ptrOut);
411 
412         p.out = mtls->fep.ptrOut + (mtls->fep.eStrideOut * xStart);
413         p.in = mtls->fep.ptrIn + (mtls->fep.eStrideIn * xStart);
414         for (uint32_t x = mtls->xStart; x < mtls->xEnd; ++x) {
415             bare_fn(p.in, p.out, p.usr, x, 0, 0, 0);
416             p.in = (char *)(p.in) + mtls->fep.eStrideIn;
417             p.out = (char *)(p.out) + mtls->fep.eStrideOut;
418         }
419     }
420 }
421 
rsdScriptInvokeForEachMtlsSetup(const Context * rsc,const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc,MTLaunchStruct * mtls)422 void rsdScriptInvokeForEachMtlsSetup(const Context *rsc,
423                                      const Allocation * ain,
424                                      Allocation * aout,
425                                      const void * usr,
426                                      uint32_t usrLen,
427                                      const RsScriptCall *sc,
428                                      MTLaunchStruct *mtls) {
429 
430     memset(mtls, 0, sizeof(MTLaunchStruct));
431 
432     if (ain) {
433         mtls->fep.dimX = ain->getType()->getDimX();
434         mtls->fep.dimY = ain->getType()->getDimY();
435         mtls->fep.dimZ = ain->getType()->getDimZ();
436         //mtls->dimArray = ain->getType()->getDimArray();
437     } else if (aout) {
438         mtls->fep.dimX = aout->getType()->getDimX();
439         mtls->fep.dimY = aout->getType()->getDimY();
440         mtls->fep.dimZ = aout->getType()->getDimZ();
441         //mtls->dimArray = aout->getType()->getDimArray();
442     } else {
443         rsc->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
444         return;
445     }
446 
447     if (!sc || (sc->xEnd == 0)) {
448         mtls->xEnd = mtls->fep.dimX;
449     } else {
450         rsAssert(sc->xStart < mtls->fep.dimX);
451         rsAssert(sc->xEnd <= mtls->fep.dimX);
452         rsAssert(sc->xStart < sc->xEnd);
453         mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
454         mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
455         if (mtls->xStart >= mtls->xEnd) return;
456     }
457 
458     if (!sc || (sc->yEnd == 0)) {
459         mtls->yEnd = mtls->fep.dimY;
460     } else {
461         rsAssert(sc->yStart < mtls->fep.dimY);
462         rsAssert(sc->yEnd <= mtls->fep.dimY);
463         rsAssert(sc->yStart < sc->yEnd);
464         mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
465         mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
466         if (mtls->yStart >= mtls->yEnd) return;
467     }
468 
469     mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
470     mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
471     mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
472     mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
473 
474     rsAssert(!ain || (ain->getType()->getDimZ() == 0));
475 
476     Context *mrsc = (Context *)rsc;
477     mtls->rsc = mrsc;
478     mtls->ain = ain;
479     mtls->aout = aout;
480     mtls->fep.usr = usr;
481     mtls->fep.usrLen = usrLen;
482     mtls->mSliceSize = 10;
483     mtls->mSliceNum = 0;
484 
485     mtls->fep.ptrIn = NULL;
486     mtls->fep.eStrideIn = 0;
487 
488     if (ain) {
489         DrvAllocation *aindrv = (DrvAllocation *)ain->mHal.drv;
490         mtls->fep.ptrIn = (const uint8_t *)aindrv->lod[0].mallocPtr;
491         mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes();
492         mtls->fep.yStrideIn = aindrv->lod[0].stride;
493     }
494 
495     mtls->fep.ptrOut = NULL;
496     mtls->fep.eStrideOut = 0;
497     if (aout) {
498         DrvAllocation *aoutdrv = (DrvAllocation *)aout->mHal.drv;
499         mtls->fep.ptrOut = (uint8_t *)aoutdrv->lod[0].mallocPtr;
500         mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes();
501         mtls->fep.yStrideOut = aoutdrv->lod[0].stride;
502     }
503 }
504 
rsdScriptLaunchThreads(const Context * rsc,Script * s,uint32_t slot,const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc,MTLaunchStruct * mtls)505 void rsdScriptLaunchThreads(const Context *rsc,
506                             Script *s,
507                             uint32_t slot,
508                             const Allocation * ain,
509                             Allocation * aout,
510                             const void * usr,
511                             uint32_t usrLen,
512                             const RsScriptCall *sc,
513                             MTLaunchStruct *mtls) {
514 
515     Script * oldTLS = setTLS(s);
516     Context *mrsc = (Context *)rsc;
517     RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv;
518 
519     if ((dc->mWorkers.mCount > 1) && s->mHal.info.isThreadable && !dc->mInForEach) {
520         dc->mInForEach = true;
521         if (mtls->fep.dimY > 1) {
522             mtls->mSliceSize = mtls->fep.dimY / (dc->mWorkers.mCount * 4);
523             if(mtls->mSliceSize < 1) {
524                 mtls->mSliceSize = 1;
525             }
526 
527             rsdLaunchThreads(mrsc, wc_xy, mtls);
528         } else {
529             mtls->mSliceSize = mtls->fep.dimX / (dc->mWorkers.mCount * 4);
530             if(mtls->mSliceSize < 1) {
531                 mtls->mSliceSize = 1;
532             }
533 
534             rsdLaunchThreads(mrsc, wc_x, mtls);
535         }
536         dc->mInForEach = false;
537 
538         //ALOGE("launch 1");
539     } else {
540         RsForEachStubParamStruct p;
541         memcpy(&p, &mtls->fep, sizeof(p));
542         uint32_t sig = mtls->sig;
543 
544         //ALOGE("launch 3");
545         outer_foreach_t fn = (outer_foreach_t) mtls->kernel;
546         for (p.ar[0] = mtls->arrayStart; p.ar[0] < mtls->arrayEnd; p.ar[0]++) {
547             for (p.z = mtls->zStart; p.z < mtls->zEnd; p.z++) {
548                 for (p.y = mtls->yStart; p.y < mtls->yEnd; p.y++) {
549                     uint32_t offset = mtls->fep.dimY * mtls->fep.dimZ * p.ar[0] +
550                                       mtls->fep.dimY * p.z + p.y;
551                     p.out = mtls->fep.ptrOut + (mtls->fep.yStrideOut * offset);
552                     p.in = mtls->fep.ptrIn + (mtls->fep.yStrideIn * offset);
553                     fn(&p, mtls->xStart, mtls->xEnd, mtls->fep.eStrideIn, mtls->fep.eStrideOut);
554                 }
555             }
556         }
557     }
558 
559     setTLS(oldTLS);
560 }
561 
rsdScriptInvokeForEach(const Context * rsc,Script * s,uint32_t slot,const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc)562 void rsdScriptInvokeForEach(const Context *rsc,
563                             Script *s,
564                             uint32_t slot,
565                             const Allocation * ain,
566                             Allocation * aout,
567                             const void * usr,
568                             uint32_t usrLen,
569                             const RsScriptCall *sc) {
570 
571     RsdHal * dc = (RsdHal *)rsc->mHal.drv;
572 
573     MTLaunchStruct mtls;
574     rsdScriptInvokeForEachMtlsSetup(rsc, ain, aout, usr, usrLen, sc, &mtls);
575     mtls.script = s;
576     mtls.fep.slot = slot;
577 
578     DrvScript *drv = (DrvScript *)s->mHal.drv;
579     if (drv->mIntrinsicID) {
580         mtls.kernel = (void (*)())drv->mIntrinsicFuncs.root;
581         mtls.fep.usr = drv->mIntrinsicData;
582     } else {
583 		mtls.kernel = drv->mForEachFunctions[slot];
584         rsAssert(mtls.kernel != NULL);
585         mtls.sig = drv->mForEachSignatures[slot];
586     }
587 
588 
589     rsdScriptLaunchThreads(rsc, s, slot, ain, aout, usr, usrLen, sc, &mtls);
590 }
591 
592 
rsdScriptInvokeRoot(const Context * dc,Script * script)593 int rsdScriptInvokeRoot(const Context *dc, Script *script) {
594     DrvScript *drv = (DrvScript *)script->mHal.drv;
595 
596     Script * oldTLS = setTLS(script);
597     int ret = drv->mRoot();
598     setTLS(oldTLS);
599 
600     return ret;
601 }
602 
rsdScriptInvokeInit(const Context * dc,Script * script)603 void rsdScriptInvokeInit(const Context *dc, Script *script) {
604     DrvScript *drv = (DrvScript *)script->mHal.drv;
605 
606     if (drv->mInit) {
607         drv->mInit();
608     }
609 }
610 
rsdScriptInvokeFreeChildren(const Context * dc,Script * script)611 void rsdScriptInvokeFreeChildren(const Context *dc, Script *script) {
612     DrvScript *drv = (DrvScript *)script->mHal.drv;
613 
614     if (drv->mFreeChildren) {
615         drv->mFreeChildren();
616     }
617 }
618 
rsdScriptInvokeFunction(const Context * dc,Script * script,uint32_t slot,const void * params,size_t paramLength)619 void rsdScriptInvokeFunction(const Context *dc, Script *script,
620                             uint32_t slot,
621                             const void *params,
622                             size_t paramLength) {
623     DrvScript *drv = (DrvScript *)script->mHal.drv;
624     //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
625 
626     Script * oldTLS = setTLS(script);
627     reinterpret_cast<void (*)(const void *, uint32_t)>(
628         drv->mInvokeFunctions[slot])(params, paramLength);
629     setTLS(oldTLS);
630 }
631 
rsdScriptSetGlobalVar(const Context * dc,const Script * script,uint32_t slot,void * data,size_t dataLength)632 void rsdScriptSetGlobalVar(const Context *dc, const Script *script,
633                            uint32_t slot, void *data, size_t dataLength) {
634     DrvScript *drv = (DrvScript *)script->mHal.drv;
635     //rsAssert(!script->mFieldIsObject[slot]);
636     //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
637 
638     if (drv->mIntrinsicID) {
639         drv->mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
640         return;
641     }
642 
643     int32_t *destPtr = reinterpret_cast<int32_t *>(drv->mFieldAddress[slot]);
644     if (!destPtr) {
645         //ALOGV("Calling setVar on slot = %i which is null", slot);
646         return;
647     }
648 
649     memcpy(destPtr, data, dataLength);
650 }
651 
rsdScriptSetGlobalVarWithElemDims(const android::renderscript::Context * dc,const android::renderscript::Script * script,uint32_t slot,void * data,size_t dataLength,const android::renderscript::Element * elem,const size_t * dims,size_t dimLength)652 void rsdScriptSetGlobalVarWithElemDims(
653         const android::renderscript::Context *dc,
654         const android::renderscript::Script *script,
655         uint32_t slot, void *data, size_t dataLength,
656         const android::renderscript::Element *elem,
657         const size_t *dims, size_t dimLength) {
658     DrvScript *drv = (DrvScript *)script->mHal.drv;
659 
660     int32_t *destPtr = reinterpret_cast<int32_t *>(drv->mFieldAddress[slot]);
661     if (!destPtr) {
662         //ALOGV("Calling setVar on slot = %i which is null", slot);
663         return;
664     }
665 
666     // We want to look at dimension in terms of integer components,
667     // but dimLength is given in terms of bytes.
668     dimLength /= sizeof(int);
669 
670     // Only a single dimension is currently supported.
671     rsAssert(dimLength == 1);
672     if (dimLength == 1) {
673         // First do the increment loop.
674         size_t stride = elem->getSizeBytes();
675         char *cVal = reinterpret_cast<char *>(data);
676         for (size_t i = 0; i < dims[0]; i++) {
677             elem->incRefs(cVal);
678             cVal += stride;
679         }
680 
681         // Decrement loop comes after (to prevent race conditions).
682         char *oldVal = reinterpret_cast<char *>(destPtr);
683         for (size_t i = 0; i < dims[0]; i++) {
684             elem->decRefs(oldVal);
685             oldVal += stride;
686         }
687     }
688 
689     memcpy(destPtr, data, dataLength);
690 }
691 
rsdScriptSetGlobalBind(const Context * dc,const Script * script,uint32_t slot,Allocation * data)692 void rsdScriptSetGlobalBind(const Context *dc, const Script *script, uint32_t slot, Allocation *data) {
693     DrvScript *drv = (DrvScript *)script->mHal.drv;
694 
695     //rsAssert(!script->mFieldIsObject[slot]);
696     //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
697 
698     if (drv->mIntrinsicID) {
699         drv->mIntrinsicFuncs.bind(dc, script, drv->mIntrinsicData, slot, data);
700         return;
701     }
702 
703     int32_t *destPtr = reinterpret_cast<int32_t *>(drv->mFieldAddress[slot]);
704     if (!destPtr) {
705         //ALOGV("Calling setVar on slot = %i which is null", slot);
706         return;
707     }
708 
709     void *ptr = NULL;
710     drv->mBoundAllocs[slot] = data;
711     if(data) {
712         DrvAllocation *allocDrv = (DrvAllocation *)data->mHal.drv;
713         ptr = allocDrv->lod[0].mallocPtr;
714     }
715     memcpy(destPtr, &ptr, sizeof(void *));
716 }
717 
rsdScriptSetGlobalObj(const Context * dc,const Script * script,uint32_t slot,ObjectBase * data)718 void rsdScriptSetGlobalObj(const Context *dc, const Script *script, uint32_t slot, ObjectBase *data) {
719     DrvScript *drv = (DrvScript *)script->mHal.drv;
720     //rsAssert(script->mFieldIsObject[slot]);
721     //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
722 
723     int32_t *destPtr = reinterpret_cast<int32_t *>(drv->mFieldAddress[slot]);
724     if (!destPtr) {
725         //ALOGV("Calling setVar on slot = %i which is null", slot);
726         return;
727     }
728 
729     rsrSetObject(dc, script, (ObjectBase **)destPtr, data);
730 }
731 
rsdScriptDestroy(const Context * dc,Script * script)732 void rsdScriptDestroy(const Context *dc, Script *script) {
733     DrvScript *drv = (DrvScript *)script->mHal.drv;
734 
735     if (drv == NULL) {
736         return;
737     }
738 
739     for (size_t i = 0; i < script->mHal.info.exportedVariableCount; ++i) {
740         if (drv->mFieldIsObject[i]) {
741             if (drv->mFieldAddress[i] != NULL) {
742                 ObjectBase **obj_addr =
743                     reinterpret_cast<ObjectBase **>(drv->mFieldAddress[i]);
744                 rsrClearObject(dc, script, obj_addr);
745             }
746         }
747     }
748 
749     delete[] drv->mInvokeFunctions;
750     delete[] drv->mForEachFunctions;
751     delete[] drv->mFieldAddress;
752     delete[] drv->mFieldIsObject;
753     delete[] drv->mForEachSignatures;
754     delete[] drv->mBoundAllocs;
755     if (drv->mScriptSO) {
756         dlclose(drv->mScriptSO);
757     }
758     free(drv);
759     script->mHal.drv = NULL;
760 }
761 
rsdScriptGetAllocationForPointer(const android::renderscript::Context * dc,const android::renderscript::Script * sc,const void * ptr)762 Allocation * rsdScriptGetAllocationForPointer(const android::renderscript::Context *dc,
763                                               const android::renderscript::Script *sc,
764                                               const void *ptr) {
765     DrvScript *drv = (DrvScript *)sc->mHal.drv;
766     if (!ptr) {
767         return NULL;
768     }
769 
770     for (uint32_t ct=0; ct < sc->mHal.info.exportedVariableCount; ct++) {
771         Allocation *a = drv->mBoundAllocs[ct];
772         if (!a) continue;
773         DrvAllocation *adrv = (DrvAllocation *)a->mHal.drv;
774         if (adrv->lod[0].mallocPtr == ptr) {
775             return a;
776         }
777     }
778     ALOGE("rsGetAllocation, failed to find %p", ptr);
779     return NULL;
780 }
781 
782