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