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