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 "rsCpuCore.h"
18 #include "rsCpuScript.h"
19 
20 #ifdef RS_COMPATIBILITY_LIB
21     #include <set>
22     #include <string>
23     #include <dlfcn.h>
24     #include <stdio.h>
25     #include <stdlib.h>
26     #include <string.h>
27     #include <sys/stat.h>
28     #include <unistd.h>
29 #else
30     #include <bcc/BCCContext.h>
31     #include <bcc/Config/Config.h>
32     #include <bcc/Renderscript/RSCompilerDriver.h>
33     #include <bcc/Renderscript/RSExecutable.h>
34     #include <bcc/Renderscript/RSInfo.h>
35     #include <bcinfo/MetadataExtractor.h>
36     #include <cutils/properties.h>
37 
38     #include <sys/types.h>
39     #include <sys/wait.h>
40     #include <unistd.h>
41 
42     #include <string>
43     #include <vector>
44 #endif
45 
46 namespace {
47 #ifdef RS_COMPATIBILITY_LIB
48 
49 // Create a len length string containing random characters from [A-Za-z0-9].
getRandomString(size_t len)50 static std::string getRandomString(size_t len) {
51     char buf[len + 1];
52     for (size_t i = 0; i < len; i++) {
53         uint32_t r = arc4random() & 0xffff;
54         r %= 62;
55         if (r < 26) {
56             // lowercase
57             buf[i] = 'a' + r;
58         } else if (r < 52) {
59             // uppercase
60             buf[i] = 'A' + (r - 26);
61         } else {
62             // Use a number
63             buf[i] = '0' + (r - 52);
64         }
65     }
66     buf[len] = '\0';
67     return std::string(buf);
68 }
69 
70 // Check if a path exists and attempt to create it if it doesn't.
ensureCacheDirExists(const char * path)71 static bool ensureCacheDirExists(const char *path) {
72     if (access(path, R_OK | W_OK | X_OK) == 0) {
73         // Done if we can rwx the directory
74         return true;
75     }
76     if (mkdir(path, 0700) == 0) {
77         return true;
78     }
79     return false;
80 }
81 
82 // Attempt to load the shared library from origName, but then fall back to
83 // creating the symlinked shared library if necessary (to ensure instancing).
84 // This function returns the dlopen()-ed handle if successful.
loadSOHelper(const char * origName,const char * cacheDir,const char * resName)85 static void *loadSOHelper(const char *origName, const char *cacheDir,
86                           const char *resName) {
87     // Keep track of which .so libraries have been loaded. Once a library is
88     // in the set (per-process granularity), we must instead make a symlink to
89     // the original shared object (randomly named .so file) and load that one
90     // instead. If we don't do this, we end up aliasing global data between
91     // the various Script instances (which are supposed to be completely
92     // independent).
93     static std::set<std::string> LoadedLibraries;
94 
95     void *loaded = NULL;
96 
97     // Skip everything if we don't even have the original library available.
98     if (access(origName, F_OK) != 0) {
99         return NULL;
100     }
101 
102     // Common path is that we have not loaded this Script/library before.
103     if (LoadedLibraries.find(origName) == LoadedLibraries.end()) {
104         loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL);
105         if (loaded) {
106             LoadedLibraries.insert(origName);
107         }
108         return loaded;
109     }
110 
111     std::string newName(cacheDir);
112     newName.append("/com.android.renderscript.cache/");
113 
114     if (!ensureCacheDirExists(newName.c_str())) {
115         ALOGE("Could not verify or create cache dir: %s", cacheDir);
116         return NULL;
117     }
118 
119     // Construct an appropriately randomized filename for the symlink.
120     newName.append("librs.");
121     newName.append(resName);
122     newName.append("#");
123     newName.append(getRandomString(6));  // 62^6 potential filename variants.
124     newName.append(".so");
125 
126     int r = symlink(origName, newName.c_str());
127     if (r != 0) {
128         ALOGE("Could not create symlink %s -> %s", newName.c_str(), origName);
129         return NULL;
130     }
131     loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL);
132     r = unlink(newName.c_str());
133     if (r != 0) {
134         ALOGE("Could not unlink symlink %s", newName.c_str());
135     }
136     if (loaded) {
137         LoadedLibraries.insert(newName.c_str());
138     }
139 
140     return loaded;
141 }
142 
143 // Load the shared library referred to by cacheDir and resName. If we have
144 // already loaded this library, we instead create a new symlink (in the
145 // cache dir) and then load that. We then immediately destroy the symlink.
146 // This is required behavior to implement script instancing for the support
147 // library, since shared objects are loaded and de-duped by name only.
loadSharedLibrary(const char * cacheDir,const char * resName)148 static void *loadSharedLibrary(const char *cacheDir, const char *resName) {
149     void *loaded = NULL;
150     //arc4random_stir();
151 #ifndef RS_SERVER
152     std::string scriptSOName(cacheDir);
153     size_t cutPos = scriptSOName.rfind("cache");
154     if (cutPos != std::string::npos) {
155         scriptSOName.erase(cutPos);
156     } else {
157         ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir);
158     }
159     scriptSOName.append("/lib/librs.");
160 #else
161     std::string scriptSOName("lib");
162 #endif
163     scriptSOName.append(resName);
164     scriptSOName.append(".so");
165 
166     // We should check if we can load the library from the standard app
167     // location for shared libraries first.
168     loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName);
169 
170     if (loaded == NULL) {
171         ALOGE("Unable to open shared library (%s): %s",
172               scriptSOName.c_str(), dlerror());
173 
174         // One final attempt to find the library in "/system/lib".
175         // We do this to allow bundled applications to use the compatibility
176         // library fallback path. Those applications don't have a private
177         // library path, so they need to install to the system directly.
178         // Note that this is really just a testing path.
179         android::String8 scriptSONameSystem("/system/lib/librs.");
180         scriptSONameSystem.append(resName);
181         scriptSONameSystem.append(".so");
182         loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir,
183                               resName);
184         if (loaded == NULL) {
185             ALOGE("Unable to open system shared library (%s): %s",
186                   scriptSONameSystem.c_str(), dlerror());
187         }
188     }
189 
190     return loaded;
191 }
192 
193 #else  // RS_COMPATIBILITY_LIB is not defined
194 
195 static bool is_force_recompile() {
196 #ifdef RS_SERVER
197   return false;
198 #else
199   char buf[PROPERTY_VALUE_MAX];
200 
201   // Re-compile if floating point precision has been overridden.
202   property_get("debug.rs.precision", buf, "");
203   if (buf[0] != '\0') {
204     return true;
205   }
206 
207   // Re-compile if debug.rs.forcerecompile is set.
208   property_get("debug.rs.forcerecompile", buf, "0");
209   if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) {
210     return true;
211   } else {
212     return false;
213   }
214 #endif  // RS_SERVER
215 }
216 
217 const static char *BCC_EXE_PATH = "/system/bin/bcc";
218 
219 static void setCompileArguments(std::vector<const char*>* args, const android::String8& bcFileName,
220                                 const char* cacheDir, const char* resName, const char* core_lib,
221                                 bool useRSDebugContext, const char* bccPluginName) {
222     rsAssert(cacheDir && resName && core_lib);
223     args->push_back(BCC_EXE_PATH);
224     args->push_back("-o");
225     args->push_back(resName);
226     args->push_back("-output_path");
227     args->push_back(cacheDir);
228     args->push_back("-bclib");
229     args->push_back(core_lib);
230     args->push_back("-mtriple");
231     args->push_back(DEFAULT_TARGET_TRIPLE_STRING);
232 
233     // Enable workaround for A53 codegen by default.
234 #if defined(__aarch64__) && !defined(DISABLE_A53_WORKAROUND)
235     args->push_back("-aarch64-fix-cortex-a53-835769");
236 #endif
237 
238     // Execute the bcc compiler.
239     if (useRSDebugContext) {
240         args->push_back("-rs-debug-ctx");
241     } else {
242         // Only load additional libraries for compiles that don't use
243         // the debug context.
244         if (bccPluginName && strlen(bccPluginName) > 0) {
245             args->push_back("-load");
246             args->push_back(bccPluginName);
247         }
248     }
249 
250     args->push_back(bcFileName.string());
251     args->push_back(NULL);
252 }
253 
254 static bool compileBitcode(const android::String8& bcFileName,
255                            const char *bitcode,
256                            size_t bitcodeSize,
257                            const char** compileArguments,
258                            const std::string& compileCommandLine) {
259     rsAssert(bitcode && bitcodeSize);
260 
261     FILE *bcfile = fopen(bcFileName.string(), "w");
262     if (!bcfile) {
263         ALOGE("Could not write to %s", bcFileName.string());
264         return false;
265     }
266     size_t nwritten = fwrite(bitcode, 1, bitcodeSize, bcfile);
267     fclose(bcfile);
268     if (nwritten != bitcodeSize) {
269         ALOGE("Could not write %zu bytes to %s", bitcodeSize,
270               bcFileName.string());
271         return false;
272     }
273 
274     pid_t pid = fork();
275 
276     switch (pid) {
277     case -1: {  // Error occurred (we attempt no recovery)
278         ALOGE("Couldn't fork for bcc compiler execution");
279         return false;
280     }
281     case 0: {  // Child process
282         ALOGV("Invoking BCC with: %s", compileCommandLine.c_str());
283         execv(BCC_EXE_PATH, (char* const*)compileArguments);
284 
285         ALOGE("execv() failed: %s", strerror(errno));
286         abort();
287         return false;
288     }
289     default: {  // Parent process (actual driver)
290         // Wait on child process to finish compiling the source.
291         int status = 0;
292         pid_t w = waitpid(pid, &status, 0);
293         if (w == -1) {
294             ALOGE("Could not wait for bcc compiler");
295             return false;
296         }
297 
298         if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
299             return true;
300         }
301 
302         ALOGE("bcc compiler terminated unexpectedly");
303         return false;
304     }
305     }
306 }
307 
308 #endif  // !defined(RS_COMPATIBILITY_LIB)
309 }  // namespace
310 
311 namespace android {
312 namespace renderscript {
313 
314 #ifdef RS_COMPATIBILITY_LIB
315 #define MAXLINE 500
316 #define MAKE_STR_HELPER(S) #S
317 #define MAKE_STR(S) MAKE_STR_HELPER(S)
318 #define EXPORT_VAR_STR "exportVarCount: "
319 #define EXPORT_FUNC_STR "exportFuncCount: "
320 #define EXPORT_FOREACH_STR "exportForEachCount: "
321 #define OBJECT_SLOT_STR "objectSlotCount: "
322 
323 // Copy up to a newline or size chars from str -> s, updating str
324 // Returns s when successful and NULL when '\0' is finally reached.
strgets(char * s,int size,const char ** ppstr)325 static char* strgets(char *s, int size, const char **ppstr) {
326     if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
327         return NULL;
328     }
329 
330     int i;
331     for (i = 0; i < (size - 1); i++) {
332         s[i] = **ppstr;
333         (*ppstr)++;
334         if (s[i] == '\0') {
335             return s;
336         } else if (s[i] == '\n') {
337             s[i+1] = '\0';
338             return s;
339         }
340     }
341 
342     // size has been exceeded.
343     s[i] = '\0';
344 
345     return s;
346 }
347 #endif
348 
RsdCpuScriptImpl(RsdCpuReferenceImpl * ctx,const Script * s)349 RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) {
350     mCtx = ctx;
351     mScript = s;
352 
353 #ifdef RS_COMPATIBILITY_LIB
354     mScriptSO = NULL;
355     mInvokeFunctions = NULL;
356     mForEachFunctions = NULL;
357     mFieldAddress = NULL;
358     mFieldIsObject = NULL;
359     mForEachSignatures = NULL;
360 #else
361     mCompilerContext = NULL;
362     mCompilerDriver = NULL;
363     mExecutable = NULL;
364 #endif
365 
366 
367     mRoot = NULL;
368     mRootExpand = NULL;
369     mInit = NULL;
370     mFreeChildren = NULL;
371 
372 
373     mBoundAllocs = NULL;
374     mIntrinsicData = NULL;
375     mIsThreadable = true;
376 }
377 
378 
init(char const * resName,char const * cacheDir,uint8_t const * bitcode,size_t bitcodeSize,uint32_t flags,char const * bccPluginName)379 bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
380                             uint8_t const *bitcode, size_t bitcodeSize,
381                             uint32_t flags, char const *bccPluginName) {
382     //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
383     //ALOGE("rsdScriptInit %p %p", rsc, script);
384 
385     mCtx->lockMutex();
386 #ifndef RS_COMPATIBILITY_LIB
387     bool useRSDebugContext = false;
388 
389     mCompilerContext = NULL;
390     mCompilerDriver = NULL;
391     mExecutable = NULL;
392 
393     mCompilerContext = new bcc::BCCContext();
394     if (mCompilerContext == NULL) {
395         ALOGE("bcc: FAILS to create compiler context (out of memory)");
396         mCtx->unlockMutex();
397         return false;
398     }
399 
400     mCompilerDriver = new bcc::RSCompilerDriver();
401     if (mCompilerDriver == NULL) {
402         ALOGE("bcc: FAILS to create compiler driver (out of memory)");
403         mCtx->unlockMutex();
404         return false;
405     }
406 
407     // Configure symbol resolvers (via compiler-rt and the RS runtime).
408     mRSRuntime.setLookupFunction(lookupRuntimeStub);
409     mRSRuntime.setContext(this);
410     mResolver.chainResolver(mCompilerRuntime);
411     mResolver.chainResolver(mRSRuntime);
412 
413     // Run any compiler setup functions we have been provided with.
414     RSSetupCompilerCallback setupCompilerCallback =
415             mCtx->getSetupCompilerCallback();
416     if (setupCompilerCallback != NULL) {
417         setupCompilerCallback(mCompilerDriver);
418     }
419 
420     bcinfo::MetadataExtractor bitcodeMetadata((const char *) bitcode, bitcodeSize);
421     if (!bitcodeMetadata.extract()) {
422         ALOGE("Could not extract metadata from bitcode");
423         mCtx->unlockMutex();
424         return false;
425     }
426 
427     const char* core_lib = findCoreLib(bitcodeMetadata, (const char*)bitcode, bitcodeSize);
428 
429     if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
430         mCompilerDriver->setDebugContext(true);
431         useRSDebugContext = true;
432     }
433 
434     android::String8 bcFileName(cacheDir);
435     bcFileName.append("/");
436     bcFileName.append(resName);
437     bcFileName.append(".bc");
438 
439     std::vector<const char*> compileArguments;
440     setCompileArguments(&compileArguments, bcFileName, cacheDir, resName, core_lib,
441                         useRSDebugContext, bccPluginName);
442     // The last argument of compileArguments ia a NULL, so remove 1 from the size.
443     std::string compileCommandLine =
444                 bcc::getCommandLine(compileArguments.size() - 1, compileArguments.data());
445 
446     if (!is_force_recompile()) {
447         // Load the compiled script that's in the cache, if any.
448         mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode,
449                                                         bitcodeSize, compileCommandLine.c_str(),
450                                                         mResolver);
451     }
452 
453     // If we can't, it's either not there or out of date.  We compile the bit code and try loading
454     // again.
455     if (mExecutable == NULL) {
456         if (!compileBitcode(bcFileName, (const char*)bitcode, bitcodeSize, compileArguments.data(),
457                             compileCommandLine)) {
458             ALOGE("bcc: FAILS to compile '%s'", resName);
459             mCtx->unlockMutex();
460             return false;
461         }
462         mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode,
463                                                         bitcodeSize, compileCommandLine.c_str(),
464                                                         mResolver);
465         if (mExecutable == NULL) {
466             ALOGE("bcc: FAILS to load freshly compiled executable for '%s'", resName);
467             mCtx->unlockMutex();
468             return false;
469         }
470     }
471 
472     mExecutable->setThreadable(mIsThreadable);
473     if (!mExecutable->syncInfo()) {
474         ALOGW("bcc: FAILS to synchronize the RS info file to the disk");
475     }
476 
477     mRoot = reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root"));
478     mRootExpand =
479         reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root.expand"));
480     mInit = reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress("init"));
481     mFreeChildren =
482         reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress(".rs.dtor"));
483 
484 
485     if (bitcodeMetadata.getExportVarCount()) {
486         mBoundAllocs = new Allocation *[bitcodeMetadata.getExportVarCount()];
487         memset(mBoundAllocs, 0, sizeof(void *) * bitcodeMetadata.getExportVarCount());
488     }
489 
490     for (size_t i = 0; i < bitcodeMetadata.getExportForEachSignatureCount(); i++) {
491         char* name = new char[strlen(bitcodeMetadata.getExportForEachNameList()[i]) + 1];
492         mExportedForEachFuncList.push_back(
493                     std::make_pair(name, bitcodeMetadata.getExportForEachSignatureList()[i]));
494     }
495 
496 #else  // RS_COMPATIBILITY_LIB is defined
497 
498     mScriptSO = loadSharedLibrary(cacheDir, resName);
499 
500     if (mScriptSO) {
501         char line[MAXLINE];
502         mRoot = (RootFunc_t) dlsym(mScriptSO, "root");
503         if (mRoot) {
504             //ALOGE("Found root(): %p", mRoot);
505         }
506         mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand");
507         if (mRootExpand) {
508             //ALOGE("Found root.expand(): %p", mRootExpand);
509         }
510         mInit = (InvokeFunc_t) dlsym(mScriptSO, "init");
511         if (mInit) {
512             //ALOGE("Found init(): %p", mInit);
513         }
514         mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor");
515         if (mFreeChildren) {
516             //ALOGE("Found .rs.dtor(): %p", mFreeChildren);
517         }
518 
519         const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info");
520         if (rsInfo) {
521             //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo);
522         }
523 
524         size_t varCount = 0;
525         if (strgets(line, MAXLINE, &rsInfo) == NULL) {
526             goto error;
527         }
528         if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
529             ALOGE("Invalid export var count!: %s", line);
530             goto error;
531         }
532 
533         mExportedVariableCount = varCount;
534         //ALOGE("varCount: %zu", varCount);
535         if (varCount > 0) {
536             // Start by creating/zeroing this member, since we don't want to
537             // accidentally clean up invalid pointers later (if we error out).
538             mFieldIsObject = new bool[varCount];
539             if (mFieldIsObject == NULL) {
540                 goto error;
541             }
542             memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject));
543             mFieldAddress = new void*[varCount];
544             if (mFieldAddress == NULL) {
545                 goto error;
546             }
547             for (size_t i = 0; i < varCount; ++i) {
548                 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
549                     goto error;
550                 }
551                 char *c = strrchr(line, '\n');
552                 if (c) {
553                     *c = '\0';
554                 }
555                 mFieldAddress[i] = dlsym(mScriptSO, line);
556                 if (mFieldAddress[i] == NULL) {
557                     ALOGE("Failed to find variable address for %s: %s",
558                           line, dlerror());
559                     // Not a critical error if we don't find a global variable.
560                 }
561                 else {
562                     //ALOGE("Found variable %s at %p", line,
563                     //mFieldAddress[i]);
564                 }
565             }
566         }
567 
568         size_t funcCount = 0;
569         if (strgets(line, MAXLINE, &rsInfo) == NULL) {
570             goto error;
571         }
572         if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
573             ALOGE("Invalid export func count!: %s", line);
574             goto error;
575         }
576 
577         mExportedFunctionCount = funcCount;
578         //ALOGE("funcCount: %zu", funcCount);
579 
580         if (funcCount > 0) {
581             mInvokeFunctions = new InvokeFunc_t[funcCount];
582             if (mInvokeFunctions == NULL) {
583                 goto error;
584             }
585             for (size_t i = 0; i < funcCount; ++i) {
586                 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
587                     goto error;
588                 }
589                 char *c = strrchr(line, '\n');
590                 if (c) {
591                     *c = '\0';
592                 }
593 
594                 mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line);
595                 if (mInvokeFunctions[i] == NULL) {
596                     ALOGE("Failed to get function address for %s(): %s",
597                           line, dlerror());
598                     goto error;
599                 }
600                 else {
601                     //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]);
602                 }
603             }
604         }
605 
606         size_t forEachCount = 0;
607         if (strgets(line, MAXLINE, &rsInfo) == NULL) {
608             goto error;
609         }
610         if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
611             ALOGE("Invalid export forEach count!: %s", line);
612             goto error;
613         }
614 
615         if (forEachCount > 0) {
616 
617             mForEachSignatures = new uint32_t[forEachCount];
618             if (mForEachSignatures == NULL) {
619                 goto error;
620             }
621             mForEachFunctions = new ForEachFunc_t[forEachCount];
622             if (mForEachFunctions == NULL) {
623                 goto error;
624             }
625             for (size_t i = 0; i < forEachCount; ++i) {
626                 unsigned int tmpSig = 0;
627                 char tmpName[MAXLINE];
628 
629                 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
630                     goto error;
631                 }
632                 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
633                            &tmpSig, tmpName) != 2) {
634                     ALOGE("Invalid export forEach!: %s", line);
635                     goto error;
636                 }
637 
638                 // Lookup the expanded ForEach kernel.
639                 strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
640                 mForEachSignatures[i] = tmpSig;
641                 mForEachFunctions[i] =
642                         (ForEachFunc_t) dlsym(mScriptSO, tmpName);
643                 if (i != 0 && mForEachFunctions[i] == NULL) {
644                     // Ignore missing root.expand functions.
645                     // root() is always specified at location 0.
646                     ALOGE("Failed to find forEach function address for %s: %s",
647                           tmpName, dlerror());
648                     goto error;
649                 }
650                 else {
651                     //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]);
652                 }
653             }
654         }
655 
656         size_t objectSlotCount = 0;
657         if (strgets(line, MAXLINE, &rsInfo) == NULL) {
658             goto error;
659         }
660         if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
661             ALOGE("Invalid object slot count!: %s", line);
662             goto error;
663         }
664 
665         if (objectSlotCount > 0) {
666             rsAssert(varCount > 0);
667             for (size_t i = 0; i < objectSlotCount; ++i) {
668                 uint32_t varNum = 0;
669                 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
670                     goto error;
671                 }
672                 if (sscanf(line, "%u", &varNum) != 1) {
673                     ALOGE("Invalid object slot!: %s", line);
674                     goto error;
675                 }
676 
677                 if (varNum < varCount) {
678                     mFieldIsObject[varNum] = true;
679                 }
680             }
681         }
682 
683         if (varCount > 0) {
684             mBoundAllocs = new Allocation *[varCount];
685             memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs));
686         }
687 
688         if (mScriptSO == (void*)1) {
689             //rsdLookupRuntimeStub(script, "acos");
690         }
691     } else {
692         goto error;
693     }
694 #endif
695     mCtx->unlockMutex();
696     return true;
697 
698 #ifdef RS_COMPATIBILITY_LIB
699 error:
700 
701     mCtx->unlockMutex();
702     delete[] mInvokeFunctions;
703     delete[] mForEachFunctions;
704     delete[] mFieldAddress;
705     delete[] mFieldIsObject;
706     delete[] mForEachSignatures;
707     delete[] mBoundAllocs;
708     if (mScriptSO) {
709         dlclose(mScriptSO);
710     }
711     return false;
712 #endif
713 }
714 
715 #ifndef RS_COMPATIBILITY_LIB
716 
717 #ifdef __LP64__
718 #define SYSLIBPATH "/system/lib64"
719 #else
720 #define SYSLIBPATH "/system/lib"
721 #endif
722 
findCoreLib(const bcinfo::MetadataExtractor & ME,const char * bitcode,size_t bitcodeSize)723 const char* RsdCpuScriptImpl::findCoreLib(const bcinfo::MetadataExtractor& ME, const char* bitcode,
724                                           size_t bitcodeSize) {
725     const char* defaultLib = SYSLIBPATH"/libclcore.bc";
726 
727     // If we're debugging, use the debug library.
728     if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
729         return SYSLIBPATH"/libclcore_debug.bc";
730     }
731 
732     // If a callback has been registered to specify a library, use that.
733     RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback();
734     if (selectRTCallback != NULL) {
735         return selectRTCallback((const char*)bitcode, bitcodeSize);
736     }
737 
738     // Check for a platform specific library
739 #if defined(ARCH_ARM_HAVE_NEON) && !defined(DISABLE_CLCORE_NEON)
740     enum bcinfo::RSFloatPrecision prec = ME.getRSFloatPrecision();
741     if (prec == bcinfo::RS_FP_Relaxed) {
742         // NEON-capable ARMv7a devices can use an accelerated math library
743         // for all reduced precision scripts.
744         // ARMv8 does not use NEON, as ASIMD can be used with all precision
745         // levels.
746         return SYSLIBPATH"/libclcore_neon.bc";
747     } else {
748         return defaultLib;
749     }
750 #elif defined(__i386__) || defined(__x86_64__)
751     // x86 devices will use an optimized library.
752     return SYSLIBPATH"/libclcore_x86.bc";
753 #else
754     return defaultLib;
755 #endif
756 }
757 
758 #endif
759 
populateScript(Script * script)760 void RsdCpuScriptImpl::populateScript(Script *script) {
761 #ifndef RS_COMPATIBILITY_LIB
762     // Copy info over to runtime
763     script->mHal.info.exportedFunctionCount = mExecutable->getExportFuncAddrs().size();
764     script->mHal.info.exportedVariableCount = mExecutable->getExportVarAddrs().size();
765     script->mHal.info.exportedForeachFuncList = &mExportedForEachFuncList[0];
766     script->mHal.info.exportedPragmaCount = mExecutable->getPragmaKeys().size();
767     script->mHal.info.exportedPragmaKeyList =
768         const_cast<const char**>(mExecutable->getPragmaKeys().array());
769     script->mHal.info.exportedPragmaValueList =
770         const_cast<const char**>(mExecutable->getPragmaValues().array());
771 
772     if (mRootExpand) {
773         script->mHal.info.root = mRootExpand;
774     } else {
775         script->mHal.info.root = mRoot;
776     }
777 #else
778     // Copy info over to runtime
779     script->mHal.info.exportedFunctionCount = mExportedFunctionCount;
780     script->mHal.info.exportedVariableCount = mExportedVariableCount;
781     script->mHal.info.exportedPragmaCount = 0;
782     script->mHal.info.exportedPragmaKeyList = 0;
783     script->mHal.info.exportedPragmaValueList = 0;
784 
785     // Bug, need to stash in metadata
786     if (mRootExpand) {
787         script->mHal.info.root = mRootExpand;
788     } else {
789         script->mHal.info.root = mRoot;
790     }
791 #endif
792 }
793 
794 
795 typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
796 
forEachMtlsSetup(const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc,MTLaunchStruct * mtls)797 void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation * ain, Allocation * aout,
798                                         const void * usr, uint32_t usrLen,
799                                         const RsScriptCall *sc,
800                                         MTLaunchStruct *mtls) {
801 
802     memset(mtls, 0, sizeof(MTLaunchStruct));
803 
804     // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface
805     if (ain && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) {
806         mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null in allocations");
807         return;
808     }
809     if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) {
810         mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null out allocations");
811         return;
812     }
813 
814     if (ain != NULL) {
815         const Type *inType = ain->getType();
816 
817         mtls->fep.dimX = inType->getDimX();
818         mtls->fep.dimY = inType->getDimY();
819         mtls->fep.dimZ = inType->getDimZ();
820 
821     } else if (aout != NULL) {
822         const Type *outType = aout->getType();
823 
824         mtls->fep.dimX = outType->getDimX();
825         mtls->fep.dimY = outType->getDimY();
826         mtls->fep.dimZ = outType->getDimZ();
827 
828     } else {
829         mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
830         return;
831     }
832 
833     if (ain != NULL && aout != NULL) {
834         if (!ain->hasSameDims(aout)) {
835             mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
836               "Failed to launch kernel; dimensions of input and output allocations do not match.");
837 
838             return;
839         }
840     }
841 
842     if (!sc || (sc->xEnd == 0)) {
843         mtls->xEnd = mtls->fep.dimX;
844     } else {
845         rsAssert(sc->xStart < mtls->fep.dimX);
846         rsAssert(sc->xEnd <= mtls->fep.dimX);
847         rsAssert(sc->xStart < sc->xEnd);
848         mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
849         mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
850         if (mtls->xStart >= mtls->xEnd) return;
851     }
852 
853     if (!sc || (sc->yEnd == 0)) {
854         mtls->yEnd = mtls->fep.dimY;
855     } else {
856         rsAssert(sc->yStart < mtls->fep.dimY);
857         rsAssert(sc->yEnd <= mtls->fep.dimY);
858         rsAssert(sc->yStart < sc->yEnd);
859         mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
860         mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
861         if (mtls->yStart >= mtls->yEnd) return;
862     }
863 
864     if (!sc || (sc->zEnd == 0)) {
865         mtls->zEnd = mtls->fep.dimZ;
866     } else {
867         rsAssert(sc->zStart < mtls->fep.dimZ);
868         rsAssert(sc->zEnd <= mtls->fep.dimZ);
869         rsAssert(sc->zStart < sc->zEnd);
870         mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart);
871         mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd);
872         if (mtls->zStart >= mtls->zEnd) return;
873     }
874 
875     mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
876     mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
877     mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
878     mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
879 
880     rsAssert(!ain || (ain->getType()->getDimZ() == 0));
881 
882     mtls->rsc = mCtx;
883     mtls->ain = ain;
884     mtls->aout = aout;
885     mtls->fep.usr = usr;
886     mtls->fep.usrLen = usrLen;
887     mtls->mSliceSize = 1;
888     mtls->mSliceNum = 0;
889 
890     mtls->fep.ptrIn = NULL;
891     mtls->fep.eStrideIn = 0;
892     mtls->isThreadable = mIsThreadable;
893 
894     if (ain) {
895         mtls->fep.ptrIn = (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr;
896         mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes();
897         mtls->fep.yStrideIn = ain->mHal.drvState.lod[0].stride;
898     }
899 
900     mtls->fep.ptrOut = NULL;
901     mtls->fep.eStrideOut = 0;
902     if (aout) {
903         mtls->fep.ptrOut = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
904         mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes();
905         mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride;
906     }
907 }
908 
forEachMtlsSetup(const Allocation ** ains,uint32_t inLen,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc,MTLaunchStruct * mtls)909 void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation ** ains, uint32_t inLen,
910                                         Allocation * aout,
911                                         const void * usr, uint32_t usrLen,
912                                         const RsScriptCall *sc,
913                                         MTLaunchStruct *mtls) {
914 
915     memset(mtls, 0, sizeof(MTLaunchStruct));
916 
917     // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface
918     if (ains != NULL) {
919         for (int index = inLen; --index >= 0;) {
920             const Allocation* ain = ains[index];
921 
922             if (ain != NULL && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) {
923                 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null in allocations");
924                 return;
925             }
926         }
927     }
928 
929     if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) {
930         mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null out allocations");
931         return;
932     }
933 
934     if (ains != NULL) {
935         const Allocation *ain0   = ains[0];
936         const Type       *inType = ain0->getType();
937 
938         mtls->fep.dimX = inType->getDimX();
939         mtls->fep.dimY = inType->getDimY();
940         mtls->fep.dimZ = inType->getDimZ();
941 
942         for (int Index = inLen; --Index >= 1;) {
943             if (!ain0->hasSameDims(ains[Index])) {
944                 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
945                   "Failed to launch kernel; dimensions of input and output allocations do not match.");
946 
947                 return;
948             }
949         }
950 
951     } else if (aout != NULL) {
952         const Type *outType = aout->getType();
953 
954         mtls->fep.dimX = outType->getDimX();
955         mtls->fep.dimY = outType->getDimY();
956         mtls->fep.dimZ = outType->getDimZ();
957 
958     } else {
959         mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
960         return;
961     }
962 
963     if (ains != NULL && aout != NULL) {
964         if (!ains[0]->hasSameDims(aout)) {
965             mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
966               "Failed to launch kernel; dimensions of input and output allocations do not match.");
967 
968             return;
969         }
970     }
971 
972     if (!sc || (sc->xEnd == 0)) {
973         mtls->xEnd = mtls->fep.dimX;
974     } else {
975         rsAssert(sc->xStart < mtls->fep.dimX);
976         rsAssert(sc->xEnd <= mtls->fep.dimX);
977         rsAssert(sc->xStart < sc->xEnd);
978         mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
979         mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
980         if (mtls->xStart >= mtls->xEnd) return;
981     }
982 
983     if (!sc || (sc->yEnd == 0)) {
984         mtls->yEnd = mtls->fep.dimY;
985     } else {
986         rsAssert(sc->yStart < mtls->fep.dimY);
987         rsAssert(sc->yEnd <= mtls->fep.dimY);
988         rsAssert(sc->yStart < sc->yEnd);
989         mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
990         mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
991         if (mtls->yStart >= mtls->yEnd) return;
992     }
993 
994     if (!sc || (sc->zEnd == 0)) {
995         mtls->zEnd = mtls->fep.dimZ;
996     } else {
997         rsAssert(sc->zStart < mtls->fep.dimZ);
998         rsAssert(sc->zEnd <= mtls->fep.dimZ);
999         rsAssert(sc->zStart < sc->zEnd);
1000         mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart);
1001         mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd);
1002         if (mtls->zStart >= mtls->zEnd) return;
1003     }
1004 
1005     mtls->xEnd     = rsMax((uint32_t)1, mtls->xEnd);
1006     mtls->yEnd     = rsMax((uint32_t)1, mtls->yEnd);
1007     mtls->zEnd     = rsMax((uint32_t)1, mtls->zEnd);
1008     mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
1009 
1010     rsAssert(!ains || (ains[0]->getType()->getDimZ() == 0));
1011 
1012     mtls->rsc        = mCtx;
1013     mtls->ains       = ains;
1014     mtls->aout       = aout;
1015     mtls->fep.usr    = usr;
1016     mtls->fep.usrLen = usrLen;
1017     mtls->mSliceSize = 1;
1018     mtls->mSliceNum  = 0;
1019 
1020     mtls->fep.ptrIns    = NULL;
1021     mtls->fep.eStrideIn = 0;
1022     mtls->isThreadable  = mIsThreadable;
1023 
1024     if (ains) {
1025         mtls->fep.ptrIns    = new const uint8_t*[inLen];
1026         mtls->fep.inStrides = new StridePair[inLen];
1027 
1028         for (int index = inLen; --index >= 0;) {
1029             const Allocation *ain = ains[index];
1030 
1031             mtls->fep.ptrIns[index] =
1032               (const uint8_t*)ain->mHal.drvState.lod[0].mallocPtr;
1033 
1034             mtls->fep.inStrides[index].eStride =
1035               ain->getType()->getElementSizeBytes();
1036             mtls->fep.inStrides[index].yStride =
1037               ain->mHal.drvState.lod[0].stride;
1038         }
1039     }
1040 
1041     mtls->fep.ptrOut = NULL;
1042     mtls->fep.eStrideOut = 0;
1043     if (aout) {
1044         mtls->fep.ptrOut     = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
1045         mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes();
1046         mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride;
1047     }
1048 }
1049 
1050 
invokeForEach(uint32_t slot,const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc)1051 void RsdCpuScriptImpl::invokeForEach(uint32_t slot,
1052                                      const Allocation * ain,
1053                                      Allocation * aout,
1054                                      const void * usr,
1055                                      uint32_t usrLen,
1056                                      const RsScriptCall *sc) {
1057 
1058     MTLaunchStruct mtls;
1059     forEachMtlsSetup(ain, aout, usr, usrLen, sc, &mtls);
1060     forEachKernelSetup(slot, &mtls);
1061 
1062     RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
1063     mCtx->launchThreads(ain, aout, sc, &mtls);
1064     mCtx->setTLS(oldTLS);
1065 }
1066 
invokeForEachMulti(uint32_t slot,const Allocation ** ains,uint32_t inLen,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc)1067 void RsdCpuScriptImpl::invokeForEachMulti(uint32_t slot,
1068                                           const Allocation ** ains,
1069                                           uint32_t inLen,
1070                                           Allocation * aout,
1071                                           const void * usr,
1072                                           uint32_t usrLen,
1073                                           const RsScriptCall *sc) {
1074 
1075     MTLaunchStruct mtls;
1076 
1077     forEachMtlsSetup(ains, inLen, aout, usr, usrLen, sc, &mtls);
1078     forEachKernelSetup(slot, &mtls);
1079 
1080     RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
1081     mCtx->launchThreads(ains, inLen, aout, sc, &mtls);
1082     mCtx->setTLS(oldTLS);
1083 }
1084 
forEachKernelSetup(uint32_t slot,MTLaunchStruct * mtls)1085 void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) {
1086     mtls->script = this;
1087     mtls->fep.slot = slot;
1088 #ifndef RS_COMPATIBILITY_LIB
1089     rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size());
1090     mtls->kernel = reinterpret_cast<ForEachFunc_t>(
1091                       mExecutable->getExportForeachFuncAddrs()[slot]);
1092     rsAssert(mtls->kernel != NULL);
1093     mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second;
1094 #else
1095     mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]);
1096     rsAssert(mtls->kernel != NULL);
1097     mtls->sig = mForEachSignatures[slot];
1098 #endif
1099 }
1100 
invokeRoot()1101 int RsdCpuScriptImpl::invokeRoot() {
1102     RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
1103     int ret = mRoot();
1104     mCtx->setTLS(oldTLS);
1105     return ret;
1106 }
1107 
invokeInit()1108 void RsdCpuScriptImpl::invokeInit() {
1109     if (mInit) {
1110         mInit();
1111     }
1112 }
1113 
invokeFreeChildren()1114 void RsdCpuScriptImpl::invokeFreeChildren() {
1115     if (mFreeChildren) {
1116         mFreeChildren();
1117     }
1118 }
1119 
invokeFunction(uint32_t slot,const void * params,size_t paramLength)1120 void RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params,
1121                                       size_t paramLength) {
1122     //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
1123 
1124     RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
1125     reinterpret_cast<void (*)(const void *, uint32_t)>(
1126 #ifndef RS_COMPATIBILITY_LIB
1127         mExecutable->getExportFuncAddrs()[slot])(params, paramLength);
1128 #else
1129         mInvokeFunctions[slot])(params, paramLength);
1130 #endif
1131     mCtx->setTLS(oldTLS);
1132 }
1133 
setGlobalVar(uint32_t slot,const void * data,size_t dataLength)1134 void RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) {
1135     //rsAssert(!script->mFieldIsObject[slot]);
1136     //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
1137 
1138     //if (mIntrinsicID) {
1139         //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
1140         //return;
1141     //}
1142 
1143 #ifndef RS_COMPATIBILITY_LIB
1144     int32_t *destPtr = reinterpret_cast<int32_t *>(
1145                           mExecutable->getExportVarAddrs()[slot]);
1146 #else
1147     int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1148 #endif
1149     if (!destPtr) {
1150         //ALOGV("Calling setVar on slot = %i which is null", slot);
1151         return;
1152     }
1153 
1154     memcpy(destPtr, data, dataLength);
1155 }
1156 
getGlobalVar(uint32_t slot,void * data,size_t dataLength)1157 void RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) {
1158     //rsAssert(!script->mFieldIsObject[slot]);
1159     //ALOGE("getGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
1160 
1161 #ifndef RS_COMPATIBILITY_LIB
1162     int32_t *srcPtr = reinterpret_cast<int32_t *>(
1163                           mExecutable->getExportVarAddrs()[slot]);
1164 #else
1165     int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1166 #endif
1167     if (!srcPtr) {
1168         //ALOGV("Calling setVar on slot = %i which is null", slot);
1169         return;
1170     }
1171     memcpy(data, srcPtr, dataLength);
1172 }
1173 
1174 
setGlobalVarWithElemDims(uint32_t slot,const void * data,size_t dataLength,const Element * elem,const uint32_t * dims,size_t dimLength)1175 void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength,
1176                                                 const Element *elem,
1177                                                 const uint32_t *dims, size_t dimLength) {
1178 
1179 #ifndef RS_COMPATIBILITY_LIB
1180     int32_t *destPtr = reinterpret_cast<int32_t *>(
1181         mExecutable->getExportVarAddrs()[slot]);
1182 #else
1183     int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1184 #endif
1185     if (!destPtr) {
1186         //ALOGV("Calling setVar on slot = %i which is null", slot);
1187         return;
1188     }
1189 
1190     // We want to look at dimension in terms of integer components,
1191     // but dimLength is given in terms of bytes.
1192     dimLength /= sizeof(int);
1193 
1194     // Only a single dimension is currently supported.
1195     rsAssert(dimLength == 1);
1196     if (dimLength == 1) {
1197         // First do the increment loop.
1198         size_t stride = elem->getSizeBytes();
1199         const char *cVal = reinterpret_cast<const char *>(data);
1200         for (uint32_t i = 0; i < dims[0]; i++) {
1201             elem->incRefs(cVal);
1202             cVal += stride;
1203         }
1204 
1205         // Decrement loop comes after (to prevent race conditions).
1206         char *oldVal = reinterpret_cast<char *>(destPtr);
1207         for (uint32_t i = 0; i < dims[0]; i++) {
1208             elem->decRefs(oldVal);
1209             oldVal += stride;
1210         }
1211     }
1212 
1213     memcpy(destPtr, data, dataLength);
1214 }
1215 
setGlobalBind(uint32_t slot,Allocation * data)1216 void RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) {
1217 
1218     //rsAssert(!script->mFieldIsObject[slot]);
1219     //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
1220 
1221 #ifndef RS_COMPATIBILITY_LIB
1222     int32_t *destPtr = reinterpret_cast<int32_t *>(
1223                           mExecutable->getExportVarAddrs()[slot]);
1224 #else
1225     int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1226 #endif
1227     if (!destPtr) {
1228         //ALOGV("Calling setVar on slot = %i which is null", slot);
1229         return;
1230     }
1231 
1232     void *ptr = NULL;
1233     mBoundAllocs[slot] = data;
1234     if(data) {
1235         ptr = data->mHal.drvState.lod[0].mallocPtr;
1236     }
1237     memcpy(destPtr, &ptr, sizeof(void *));
1238 }
1239 
setGlobalObj(uint32_t slot,ObjectBase * data)1240 void RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) {
1241 
1242     //rsAssert(script->mFieldIsObject[slot]);
1243     //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
1244 
1245 #ifndef RS_COMPATIBILITY_LIB
1246     int32_t *destPtr = reinterpret_cast<int32_t *>(
1247                           mExecutable->getExportVarAddrs()[slot]);
1248 #else
1249     int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1250 #endif
1251 
1252     if (!destPtr) {
1253         //ALOGV("Calling setVar on slot = %i which is null", slot);
1254         return;
1255     }
1256 
1257     rsrSetObject(mCtx->getContext(), (rs_object_base *)destPtr, data);
1258 }
1259 
~RsdCpuScriptImpl()1260 RsdCpuScriptImpl::~RsdCpuScriptImpl() {
1261 #ifndef RS_COMPATIBILITY_LIB
1262     if (mExecutable) {
1263         Vector<void *>::const_iterator var_addr_iter =
1264             mExecutable->getExportVarAddrs().begin();
1265         Vector<void *>::const_iterator var_addr_end =
1266             mExecutable->getExportVarAddrs().end();
1267 
1268         bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter =
1269             mExecutable->getInfo().getObjectSlots().begin();
1270         bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end =
1271             mExecutable->getInfo().getObjectSlots().end();
1272 
1273         while ((var_addr_iter != var_addr_end) &&
1274                (is_object_iter != is_object_end)) {
1275             // The field address can be NULL if the script-side has optimized
1276             // the corresponding global variable away.
1277             rs_object_base *obj_addr =
1278                 reinterpret_cast<rs_object_base *>(*var_addr_iter);
1279             if (*is_object_iter) {
1280                 if (*var_addr_iter != NULL && mCtx->getContext() != NULL) {
1281                     rsrClearObject(mCtx->getContext(), obj_addr);
1282                 }
1283             }
1284             var_addr_iter++;
1285             is_object_iter++;
1286         }
1287     }
1288 
1289     if (mCompilerContext) {
1290         delete mCompilerContext;
1291     }
1292     if (mCompilerDriver) {
1293         delete mCompilerDriver;
1294     }
1295     if (mExecutable) {
1296         delete mExecutable;
1297     }
1298     if (mBoundAllocs) {
1299         delete[] mBoundAllocs;
1300     }
1301 
1302     for (size_t i = 0; i < mExportedForEachFuncList.size(); i++) {
1303         delete[] mExportedForEachFuncList[i].first;
1304     }
1305 #else
1306     if (mFieldIsObject) {
1307         for (size_t i = 0; i < mExportedVariableCount; ++i) {
1308             if (mFieldIsObject[i]) {
1309                 if (mFieldAddress[i] != NULL) {
1310                     rs_object_base *obj_addr =
1311                         reinterpret_cast<rs_object_base *>(mFieldAddress[i]);
1312                     rsrClearObject(mCtx->getContext(), obj_addr);
1313                 }
1314             }
1315         }
1316     }
1317 
1318     if (mInvokeFunctions) delete[] mInvokeFunctions;
1319     if (mForEachFunctions) delete[] mForEachFunctions;
1320     if (mFieldAddress) delete[] mFieldAddress;
1321     if (mFieldIsObject) delete[] mFieldIsObject;
1322     if (mForEachSignatures) delete[] mForEachSignatures;
1323     if (mBoundAllocs) delete[] mBoundAllocs;
1324     if (mScriptSO) {
1325         dlclose(mScriptSO);
1326     }
1327 #endif
1328 }
1329 
getAllocationForPointer(const void * ptr) const1330 Allocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const {
1331     if (!ptr) {
1332         return NULL;
1333     }
1334 
1335     for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) {
1336         Allocation *a = mBoundAllocs[ct];
1337         if (!a) continue;
1338         if (a->mHal.drvState.lod[0].mallocPtr == ptr) {
1339             return a;
1340         }
1341     }
1342     ALOGE("rsGetAllocation, failed to find %p", ptr);
1343     return NULL;
1344 }
1345 
preLaunch(uint32_t slot,const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc)1346 void RsdCpuScriptImpl::preLaunch(uint32_t slot, const Allocation * ain,
1347                        Allocation * aout, const void * usr,
1348                        uint32_t usrLen, const RsScriptCall *sc)
1349 {
1350 }
1351 
postLaunch(uint32_t slot,const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc)1352 void RsdCpuScriptImpl::postLaunch(uint32_t slot, const Allocation * ain,
1353                         Allocation * aout, const void * usr,
1354                         uint32_t usrLen, const RsScriptCall *sc)
1355 {
1356 }
1357 
1358 
1359 }
1360 }
1361