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
18
19 #include "rsCpuCore.h"
20
21 #include "rsCpuScript.h"
22 //#include "rsdRuntime.h"
23 //#include "rsdAllocation.h"
24 //#include "rsCpuIntrinsics.h"
25
26 #ifndef RS_SERVER
27 #include "utils/Vector.h"
28 #include "utils/Timers.h"
29 #include "utils/StopWatch.h"
30 #endif
31
32 #ifdef RS_COMPATIBILITY_LIB
33 #include <dlfcn.h>
34 #include <stdio.h>
35 #include <string.h>
36 #else
37 #include <bcc/BCCContext.h>
38 #include <bcc/Renderscript/RSCompilerDriver.h>
39 #include <bcc/Renderscript/RSExecutable.h>
40 #include <bcc/Renderscript/RSInfo.h>
41 #endif
42
43 namespace android {
44 namespace renderscript {
45
46
47 #ifdef RS_COMPATIBILITY_LIB
48 #define MAXLINE 500
49 #define MAKE_STR_HELPER(S) #S
50 #define MAKE_STR(S) MAKE_STR_HELPER(S)
51 #define EXPORT_VAR_STR "exportVarCount: "
52 #define EXPORT_VAR_STR_LEN strlen(EXPORT_VAR_STR)
53 #define EXPORT_FUNC_STR "exportFuncCount: "
54 #define EXPORT_FUNC_STR_LEN strlen(EXPORT_FUNC_STR)
55 #define EXPORT_FOREACH_STR "exportForEachCount: "
56 #define EXPORT_FOREACH_STR_LEN strlen(EXPORT_FOREACH_STR)
57 #define OBJECT_SLOT_STR "objectSlotCount: "
58 #define OBJECT_SLOT_STR_LEN strlen(OBJECT_SLOT_STR)
59
60 // Copy up to a newline or size chars from str -> s, updating str
61 // Returns s when successful and NULL when '\0' is finally reached.
strgets(char * s,int size,const char ** ppstr)62 static char* strgets(char *s, int size, const char **ppstr) {
63 if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
64 return NULL;
65 }
66
67 int i;
68 for (i = 0; i < (size - 1); i++) {
69 s[i] = **ppstr;
70 (*ppstr)++;
71 if (s[i] == '\0') {
72 return s;
73 } else if (s[i] == '\n') {
74 s[i+1] = '\0';
75 return s;
76 }
77 }
78
79 // size has been exceeded.
80 s[i] = '\0';
81
82 return s;
83 }
84 #endif
85
RsdCpuScriptImpl(RsdCpuReferenceImpl * ctx,const Script * s)86 RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) {
87 mCtx = ctx;
88 mScript = s;
89
90 #ifdef RS_COMPATIBILITY_LIB
91 mScriptSO = NULL;
92 mInvokeFunctions = NULL;
93 mForEachFunctions = NULL;
94 mFieldAddress = NULL;
95 mFieldIsObject = NULL;
96 mForEachSignatures = NULL;
97 #else
98 mCompilerContext = NULL;
99 mCompilerDriver = NULL;
100 mExecutable = NULL;
101 #endif
102
103 mRoot = NULL;
104 mRootExpand = NULL;
105 mInit = NULL;
106 mFreeChildren = NULL;
107
108
109 mBoundAllocs = NULL;
110 mIntrinsicData = NULL;
111 mIsThreadable = true;
112 }
113
114
init(char const * resName,char const * cacheDir,uint8_t const * bitcode,size_t bitcodeSize,uint32_t flags)115 bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
116 uint8_t const *bitcode, size_t bitcodeSize,
117 uint32_t flags) {
118 //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
119 //ALOGE("rsdScriptInit %p %p", rsc, script);
120
121 mCtx->lockMutex();
122
123 #ifndef RS_COMPATIBILITY_LIB
124 bcc::RSExecutable *exec;
125
126 mCompilerContext = NULL;
127 mCompilerDriver = NULL;
128 mExecutable = NULL;
129
130 mCompilerContext = new bcc::BCCContext();
131 if (mCompilerContext == NULL) {
132 ALOGE("bcc: FAILS to create compiler context (out of memory)");
133 mCtx->unlockMutex();
134 return false;
135 }
136
137 mCompilerDriver = new bcc::RSCompilerDriver();
138 if (mCompilerDriver == NULL) {
139 ALOGE("bcc: FAILS to create compiler driver (out of memory)");
140 mCtx->unlockMutex();
141 return false;
142 }
143
144 mCompilerDriver->setRSRuntimeLookupFunction(lookupRuntimeStub);
145 mCompilerDriver->setRSRuntimeLookupContext(this);
146
147 const char *core_lib = NULL;
148 RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback();
149 if (selectRTCallback != NULL) {
150 core_lib = selectRTCallback((const char *)bitcode, bitcodeSize);
151 }
152
153 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
154 // Use the libclcore_debug.bc instead of the default library.
155 core_lib = bcc::RSInfo::LibCLCoreDebugPath;
156 mCompilerDriver->setDebugContext(true);
157 }
158 exec = mCompilerDriver->build(*mCompilerContext, cacheDir, resName,
159 (const char *)bitcode, bitcodeSize, core_lib,
160 mCtx->getLinkRuntimeCallback());
161
162 if (exec == NULL) {
163 ALOGE("bcc: FAILS to prepare executable for '%s'", resName);
164 mCtx->unlockMutex();
165 return false;
166 }
167
168 mExecutable = exec;
169
170 exec->setThreadable(mIsThreadable);
171 if (!exec->syncInfo()) {
172 ALOGW("bcc: FAILS to synchronize the RS info file to the disk");
173 }
174
175 mRoot = reinterpret_cast<int (*)()>(exec->getSymbolAddress("root"));
176 mRootExpand =
177 reinterpret_cast<int (*)()>(exec->getSymbolAddress("root.expand"));
178 mInit = reinterpret_cast<void (*)()>(exec->getSymbolAddress("init"));
179 mFreeChildren =
180 reinterpret_cast<void (*)()>(exec->getSymbolAddress(".rs.dtor"));
181
182
183 const bcc::RSInfo *info = &mExecutable->getInfo();
184 if (info->getExportVarNames().size()) {
185 mBoundAllocs = new Allocation *[info->getExportVarNames().size()];
186 memset(mBoundAllocs, 0, sizeof(void *) * info->getExportVarNames().size());
187 }
188
189 #else
190
191 #ifndef RS_SERVER
192 String8 scriptSOName(cacheDir);
193 scriptSOName = scriptSOName.getPathDir();
194 scriptSOName.appendPath("lib");
195 scriptSOName.append("/librs.");
196 #else
197 String8 scriptSOName("lib");
198 #endif
199 scriptSOName.append(resName);
200 scriptSOName.append(".so");
201
202 //script->mHal.drv = drv;
203
204 //ALOGV("Opening up shared object: %s", scriptSOName.string());
205 mScriptSO = dlopen(scriptSOName.string(), RTLD_NOW | RTLD_LOCAL);
206 if (mScriptSO == NULL) {
207 ALOGE("Unable to open shared library (%s): %s",
208 scriptSOName.string(), dlerror());
209
210 // One final attempt to find the library in "/system/lib".
211 // We do this to allow bundled applications to use the compatibility
212 // library fallback path. Those applications don't have a private
213 // library path, so they need to install to the system directly.
214 String8 scriptSONameSystem("/system/lib/librs.");
215 scriptSONameSystem.append(resName);
216 scriptSONameSystem.append(".so");
217 mScriptSO = dlopen(scriptSONameSystem.string(), RTLD_NOW | RTLD_LOCAL);
218 if (mScriptSO == NULL) {
219 ALOGE("Unable to open system shared library (%s): %s",
220 scriptSONameSystem.string(), dlerror());
221 goto error;
222 }
223 }
224
225 if (mScriptSO) {
226 char line[MAXLINE];
227 mRoot = (RootFunc_t) dlsym(mScriptSO, "root");
228 if (mRoot) {
229 //ALOGE("Found root(): %p", mRoot);
230 }
231 mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand");
232 if (mRootExpand) {
233 //ALOGE("Found root.expand(): %p", mRootExpand);
234 }
235 mInit = (InvokeFunc_t) dlsym(mScriptSO, "init");
236 if (mInit) {
237 //ALOGE("Found init(): %p", mInit);
238 }
239 mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor");
240 if (mFreeChildren) {
241 //ALOGE("Found .rs.dtor(): %p", mFreeChildren);
242 }
243
244 const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info");
245 if (rsInfo) {
246 //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo);
247 }
248
249 size_t varCount = 0;
250 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
251 goto error;
252 }
253 if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
254 ALOGE("Invalid export var count!: %s", line);
255 goto error;
256 }
257
258 mExportedVariableCount = varCount;
259 //ALOGE("varCount: %zu", varCount);
260 if (varCount > 0) {
261 // Start by creating/zeroing this member, since we don't want to
262 // accidentally clean up invalid pointers later (if we error out).
263 mFieldIsObject = new bool[varCount];
264 if (mFieldIsObject == NULL) {
265 goto error;
266 }
267 memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject));
268 mFieldAddress = new void*[varCount];
269 if (mFieldAddress == NULL) {
270 goto error;
271 }
272 for (size_t i = 0; i < varCount; ++i) {
273 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
274 goto error;
275 }
276 char *c = strrchr(line, '\n');
277 if (c) {
278 *c = '\0';
279 }
280 mFieldAddress[i] = dlsym(mScriptSO, line);
281 if (mFieldAddress[i] == NULL) {
282 ALOGE("Failed to find variable address for %s: %s",
283 line, dlerror());
284 // Not a critical error if we don't find a global variable.
285 }
286 else {
287 //ALOGE("Found variable %s at %p", line,
288 //mFieldAddress[i]);
289 }
290 }
291 }
292
293 size_t funcCount = 0;
294 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
295 goto error;
296 }
297 if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
298 ALOGE("Invalid export func count!: %s", line);
299 goto error;
300 }
301
302 mExportedFunctionCount = funcCount;
303 //ALOGE("funcCount: %zu", funcCount);
304
305 if (funcCount > 0) {
306 mInvokeFunctions = new InvokeFunc_t[funcCount];
307 if (mInvokeFunctions == NULL) {
308 goto error;
309 }
310 for (size_t i = 0; i < funcCount; ++i) {
311 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
312 goto error;
313 }
314 char *c = strrchr(line, '\n');
315 if (c) {
316 *c = '\0';
317 }
318
319 mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line);
320 if (mInvokeFunctions[i] == NULL) {
321 ALOGE("Failed to get function address for %s(): %s",
322 line, dlerror());
323 goto error;
324 }
325 else {
326 //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]);
327 }
328 }
329 }
330
331 size_t forEachCount = 0;
332 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
333 goto error;
334 }
335 if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
336 ALOGE("Invalid export forEach count!: %s", line);
337 goto error;
338 }
339
340 if (forEachCount > 0) {
341
342 mForEachSignatures = new uint32_t[forEachCount];
343 if (mForEachSignatures == NULL) {
344 goto error;
345 }
346 mForEachFunctions = new ForEachFunc_t[forEachCount];
347 if (mForEachFunctions == NULL) {
348 goto error;
349 }
350 for (size_t i = 0; i < forEachCount; ++i) {
351 unsigned int tmpSig = 0;
352 char tmpName[MAXLINE];
353
354 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
355 goto error;
356 }
357 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
358 &tmpSig, tmpName) != 2) {
359 ALOGE("Invalid export forEach!: %s", line);
360 goto error;
361 }
362
363 // Lookup the expanded ForEach kernel.
364 strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
365 mForEachSignatures[i] = tmpSig;
366 mForEachFunctions[i] =
367 (ForEachFunc_t) dlsym(mScriptSO, tmpName);
368 if (i != 0 && mForEachFunctions[i] == NULL) {
369 // Ignore missing root.expand functions.
370 // root() is always specified at location 0.
371 ALOGE("Failed to find forEach function address for %s: %s",
372 tmpName, dlerror());
373 goto error;
374 }
375 else {
376 //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]);
377 }
378 }
379 }
380
381 size_t objectSlotCount = 0;
382 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
383 goto error;
384 }
385 if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
386 ALOGE("Invalid object slot count!: %s", line);
387 goto error;
388 }
389
390 if (objectSlotCount > 0) {
391 rsAssert(varCount > 0);
392 for (size_t i = 0; i < objectSlotCount; ++i) {
393 uint32_t varNum = 0;
394 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
395 goto error;
396 }
397 if (sscanf(line, "%u", &varNum) != 1) {
398 ALOGE("Invalid object slot!: %s", line);
399 goto error;
400 }
401
402 if (varNum < varCount) {
403 mFieldIsObject[varNum] = true;
404 }
405 }
406 }
407
408 if (varCount > 0) {
409 mBoundAllocs = new Allocation *[varCount];
410 memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs));
411 }
412
413 if (mScriptSO == (void*)1) {
414 //rsdLookupRuntimeStub(script, "acos");
415 }
416 }
417 #endif
418
419 mCtx->unlockMutex();
420 return true;
421
422 #ifdef RS_COMPATIBILITY_LIB
423 error:
424
425 mCtx->unlockMutex();
426 delete[] mInvokeFunctions;
427 delete[] mForEachFunctions;
428 delete[] mFieldAddress;
429 delete[] mFieldIsObject;
430 delete[] mForEachSignatures;
431 delete[] mBoundAllocs;
432 if (mScriptSO) {
433 dlclose(mScriptSO);
434 }
435 return false;
436 #endif
437 }
438
populateScript(Script * script)439 void RsdCpuScriptImpl::populateScript(Script *script) {
440 #ifndef RS_COMPATIBILITY_LIB
441 const bcc::RSInfo *info = &mExecutable->getInfo();
442
443 // Copy info over to runtime
444 script->mHal.info.exportedFunctionCount = info->getExportFuncNames().size();
445 script->mHal.info.exportedVariableCount = info->getExportVarNames().size();
446 script->mHal.info.exportedPragmaCount = info->getPragmas().size();
447 script->mHal.info.exportedPragmaKeyList =
448 const_cast<const char**>(mExecutable->getPragmaKeys().array());
449 script->mHal.info.exportedPragmaValueList =
450 const_cast<const char**>(mExecutable->getPragmaValues().array());
451
452 if (mRootExpand) {
453 script->mHal.info.root = mRootExpand;
454 } else {
455 script->mHal.info.root = mRoot;
456 }
457 #else
458 // Copy info over to runtime
459 script->mHal.info.exportedFunctionCount = mExportedFunctionCount;
460 script->mHal.info.exportedVariableCount = mExportedVariableCount;
461 script->mHal.info.exportedPragmaCount = 0;
462 script->mHal.info.exportedPragmaKeyList = 0;
463 script->mHal.info.exportedPragmaValueList = 0;
464
465 // Bug, need to stash in metadata
466 if (mRootExpand) {
467 script->mHal.info.root = mRootExpand;
468 } else {
469 script->mHal.info.root = mRoot;
470 }
471 #endif
472 }
473
474
475 typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
476
forEachMtlsSetup(const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc,MTLaunchStruct * mtls)477 void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation * ain, Allocation * aout,
478 const void * usr, uint32_t usrLen,
479 const RsScriptCall *sc,
480 MTLaunchStruct *mtls) {
481
482 memset(mtls, 0, sizeof(MTLaunchStruct));
483
484 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface
485 if (ain && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) {
486 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
487 return;
488 }
489 if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) {
490 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
491 return;
492 }
493
494 if (ain) {
495 mtls->fep.dimX = ain->getType()->getDimX();
496 mtls->fep.dimY = ain->getType()->getDimY();
497 mtls->fep.dimZ = ain->getType()->getDimZ();
498 //mtls->dimArray = ain->getType()->getDimArray();
499 } else if (aout) {
500 mtls->fep.dimX = aout->getType()->getDimX();
501 mtls->fep.dimY = aout->getType()->getDimY();
502 mtls->fep.dimZ = aout->getType()->getDimZ();
503 //mtls->dimArray = aout->getType()->getDimArray();
504 } else {
505 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
506 return;
507 }
508
509 if (!sc || (sc->xEnd == 0)) {
510 mtls->xEnd = mtls->fep.dimX;
511 } else {
512 rsAssert(sc->xStart < mtls->fep.dimX);
513 rsAssert(sc->xEnd <= mtls->fep.dimX);
514 rsAssert(sc->xStart < sc->xEnd);
515 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
516 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
517 if (mtls->xStart >= mtls->xEnd) return;
518 }
519
520 if (!sc || (sc->yEnd == 0)) {
521 mtls->yEnd = mtls->fep.dimY;
522 } else {
523 rsAssert(sc->yStart < mtls->fep.dimY);
524 rsAssert(sc->yEnd <= mtls->fep.dimY);
525 rsAssert(sc->yStart < sc->yEnd);
526 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
527 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
528 if (mtls->yStart >= mtls->yEnd) return;
529 }
530
531 if (!sc || (sc->zEnd == 0)) {
532 mtls->zEnd = mtls->fep.dimZ;
533 } else {
534 rsAssert(sc->zStart < mtls->fep.dimZ);
535 rsAssert(sc->zEnd <= mtls->fep.dimZ);
536 rsAssert(sc->zStart < sc->zEnd);
537 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart);
538 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd);
539 if (mtls->zStart >= mtls->zEnd) return;
540 }
541
542 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
543 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
544 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
545 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
546
547 rsAssert(!ain || (ain->getType()->getDimZ() == 0));
548
549 mtls->rsc = mCtx;
550 mtls->ain = ain;
551 mtls->aout = aout;
552 mtls->fep.usr = usr;
553 mtls->fep.usrLen = usrLen;
554 mtls->mSliceSize = 1;
555 mtls->mSliceNum = 0;
556
557 mtls->fep.ptrIn = NULL;
558 mtls->fep.eStrideIn = 0;
559 mtls->isThreadable = mIsThreadable;
560
561 if (ain) {
562 mtls->fep.ptrIn = (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr;
563 mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes();
564 mtls->fep.yStrideIn = ain->mHal.drvState.lod[0].stride;
565 }
566
567 mtls->fep.ptrOut = NULL;
568 mtls->fep.eStrideOut = 0;
569 if (aout) {
570 mtls->fep.ptrOut = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
571 mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes();
572 mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride;
573 }
574 }
575
576
invokeForEach(uint32_t slot,const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc)577 void RsdCpuScriptImpl::invokeForEach(uint32_t slot,
578 const Allocation * ain,
579 Allocation * aout,
580 const void * usr,
581 uint32_t usrLen,
582 const RsScriptCall *sc) {
583
584 MTLaunchStruct mtls;
585 forEachMtlsSetup(ain, aout, usr, usrLen, sc, &mtls);
586 forEachKernelSetup(slot, &mtls);
587
588 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
589 mCtx->launchThreads(ain, aout, sc, &mtls);
590 mCtx->setTLS(oldTLS);
591 }
592
forEachKernelSetup(uint32_t slot,MTLaunchStruct * mtls)593 void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) {
594 mtls->script = this;
595 mtls->fep.slot = slot;
596 #ifndef RS_COMPATIBILITY_LIB
597 rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size());
598 mtls->kernel = reinterpret_cast<ForEachFunc_t>(
599 mExecutable->getExportForeachFuncAddrs()[slot]);
600 rsAssert(mtls->kernel != NULL);
601 mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second;
602 #else
603 mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]);
604 rsAssert(mtls->kernel != NULL);
605 mtls->sig = mForEachSignatures[slot];
606 #endif
607 }
608
invokeRoot()609 int RsdCpuScriptImpl::invokeRoot() {
610 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
611 int ret = mRoot();
612 mCtx->setTLS(oldTLS);
613 return ret;
614 }
615
invokeInit()616 void RsdCpuScriptImpl::invokeInit() {
617 if (mInit) {
618 mInit();
619 }
620 }
621
invokeFreeChildren()622 void RsdCpuScriptImpl::invokeFreeChildren() {
623 if (mFreeChildren) {
624 mFreeChildren();
625 }
626 }
627
invokeFunction(uint32_t slot,const void * params,size_t paramLength)628 void RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params,
629 size_t paramLength) {
630 //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
631
632 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
633 reinterpret_cast<void (*)(const void *, uint32_t)>(
634 #ifndef RS_COMPATIBILITY_LIB
635 mExecutable->getExportFuncAddrs()[slot])(params, paramLength);
636 #else
637 mInvokeFunctions[slot])(params, paramLength);
638 #endif
639 mCtx->setTLS(oldTLS);
640 }
641
setGlobalVar(uint32_t slot,const void * data,size_t dataLength)642 void RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) {
643 //rsAssert(!script->mFieldIsObject[slot]);
644 //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
645
646 //if (mIntrinsicID) {
647 //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
648 //return;
649 //}
650
651 #ifndef RS_COMPATIBILITY_LIB
652 int32_t *destPtr = reinterpret_cast<int32_t *>(
653 mExecutable->getExportVarAddrs()[slot]);
654 #else
655 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
656 #endif
657 if (!destPtr) {
658 //ALOGV("Calling setVar on slot = %i which is null", slot);
659 return;
660 }
661
662 memcpy(destPtr, data, dataLength);
663 }
664
getGlobalVar(uint32_t slot,void * data,size_t dataLength)665 void RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) {
666 //rsAssert(!script->mFieldIsObject[slot]);
667 //ALOGE("getGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
668
669 #ifndef RS_COMPATIBILITY_LIB
670 int32_t *srcPtr = reinterpret_cast<int32_t *>(
671 mExecutable->getExportVarAddrs()[slot]);
672 #else
673 int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
674 #endif
675 if (!srcPtr) {
676 //ALOGV("Calling setVar on slot = %i which is null", slot);
677 return;
678 }
679 memcpy(data, srcPtr, dataLength);
680 }
681
682
setGlobalVarWithElemDims(uint32_t slot,const void * data,size_t dataLength,const Element * elem,const size_t * dims,size_t dimLength)683 void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength,
684 const Element *elem,
685 const size_t *dims, size_t dimLength) {
686
687 #ifndef RS_COMPATIBILITY_LIB
688 int32_t *destPtr = reinterpret_cast<int32_t *>(
689 mExecutable->getExportVarAddrs()[slot]);
690 #else
691 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
692 #endif
693 if (!destPtr) {
694 //ALOGV("Calling setVar on slot = %i which is null", slot);
695 return;
696 }
697
698 // We want to look at dimension in terms of integer components,
699 // but dimLength is given in terms of bytes.
700 dimLength /= sizeof(int);
701
702 // Only a single dimension is currently supported.
703 rsAssert(dimLength == 1);
704 if (dimLength == 1) {
705 // First do the increment loop.
706 size_t stride = elem->getSizeBytes();
707 const char *cVal = reinterpret_cast<const char *>(data);
708 for (size_t i = 0; i < dims[0]; i++) {
709 elem->incRefs(cVal);
710 cVal += stride;
711 }
712
713 // Decrement loop comes after (to prevent race conditions).
714 char *oldVal = reinterpret_cast<char *>(destPtr);
715 for (size_t i = 0; i < dims[0]; i++) {
716 elem->decRefs(oldVal);
717 oldVal += stride;
718 }
719 }
720
721 memcpy(destPtr, data, dataLength);
722 }
723
setGlobalBind(uint32_t slot,Allocation * data)724 void RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) {
725
726 //rsAssert(!script->mFieldIsObject[slot]);
727 //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
728
729 #ifndef RS_COMPATIBILITY_LIB
730 int32_t *destPtr = reinterpret_cast<int32_t *>(
731 mExecutable->getExportVarAddrs()[slot]);
732 #else
733 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
734 #endif
735 if (!destPtr) {
736 //ALOGV("Calling setVar on slot = %i which is null", slot);
737 return;
738 }
739
740 void *ptr = NULL;
741 mBoundAllocs[slot] = data;
742 if(data) {
743 ptr = data->mHal.drvState.lod[0].mallocPtr;
744 }
745 memcpy(destPtr, &ptr, sizeof(void *));
746 }
747
setGlobalObj(uint32_t slot,ObjectBase * data)748 void RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) {
749
750 //rsAssert(script->mFieldIsObject[slot]);
751 //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
752
753 //if (mIntrinsicID) {
754 //mIntrinsicFuncs.setVarObj(dc, script, drv->mIntrinsicData, slot, alloc);
755 //return;
756 //}
757
758 #ifndef RS_COMPATIBILITY_LIB
759 int32_t *destPtr = reinterpret_cast<int32_t *>(
760 mExecutable->getExportVarAddrs()[slot]);
761 #else
762 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
763 #endif
764 if (!destPtr) {
765 //ALOGV("Calling setVar on slot = %i which is null", slot);
766 return;
767 }
768
769 rsrSetObject(mCtx->getContext(), (ObjectBase **)destPtr, data);
770 }
771
~RsdCpuScriptImpl()772 RsdCpuScriptImpl::~RsdCpuScriptImpl() {
773 #ifndef RS_COMPATIBILITY_LIB
774 if (mExecutable) {
775 Vector<void *>::const_iterator var_addr_iter =
776 mExecutable->getExportVarAddrs().begin();
777 Vector<void *>::const_iterator var_addr_end =
778 mExecutable->getExportVarAddrs().end();
779
780 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter =
781 mExecutable->getInfo().getObjectSlots().begin();
782 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end =
783 mExecutable->getInfo().getObjectSlots().end();
784
785 while ((var_addr_iter != var_addr_end) &&
786 (is_object_iter != is_object_end)) {
787 // The field address can be NULL if the script-side has optimized
788 // the corresponding global variable away.
789 ObjectBase **obj_addr =
790 reinterpret_cast<ObjectBase **>(*var_addr_iter);
791 if (*is_object_iter) {
792 if (*var_addr_iter != NULL) {
793 rsrClearObject(mCtx->getContext(), obj_addr);
794 }
795 }
796 var_addr_iter++;
797 is_object_iter++;
798 }
799 }
800
801 if (mCompilerContext) {
802 delete mCompilerContext;
803 }
804 if (mCompilerDriver) {
805 delete mCompilerDriver;
806 }
807 if (mExecutable) {
808 delete mExecutable;
809 }
810 if (mBoundAllocs) {
811 delete[] mBoundAllocs;
812 }
813 #else
814 if (mFieldIsObject) {
815 for (size_t i = 0; i < mExportedVariableCount; ++i) {
816 if (mFieldIsObject[i]) {
817 if (mFieldAddress[i] != NULL) {
818 ObjectBase **obj_addr =
819 reinterpret_cast<ObjectBase **>(mFieldAddress[i]);
820 rsrClearObject(mCtx->getContext(), obj_addr);
821 }
822 }
823 }
824 }
825
826 if (mInvokeFunctions) delete[] mInvokeFunctions;
827 if (mForEachFunctions) delete[] mForEachFunctions;
828 if (mFieldAddress) delete[] mFieldAddress;
829 if (mFieldIsObject) delete[] mFieldIsObject;
830 if (mForEachSignatures) delete[] mForEachSignatures;
831 if (mBoundAllocs) delete[] mBoundAllocs;
832 if (mScriptSO) {
833 dlclose(mScriptSO);
834 }
835 #endif
836 }
837
getAllocationForPointer(const void * ptr) const838 Allocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const {
839 if (!ptr) {
840 return NULL;
841 }
842
843 for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) {
844 Allocation *a = mBoundAllocs[ct];
845 if (!a) continue;
846 if (a->mHal.drvState.lod[0].mallocPtr == ptr) {
847 return a;
848 }
849 }
850 ALOGE("rsGetAllocation, failed to find %p", ptr);
851 return NULL;
852 }
853
854
855 }
856 }
857