• 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 
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