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     // 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.
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   1101 int RsdCpuScriptImpl::invokeRoot() {
   1102     RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
   1103     int ret = mRoot();
   1104     mCtx->setTLS(oldTLS);
   1105     return ret;
   1106 }
   1107 
   1108 void RsdCpuScriptImpl::invokeInit() {
   1109     if (mInit) {
   1110         mInit();
   1111     }
   1112 }
   1113 
   1114 void RsdCpuScriptImpl::invokeFreeChildren() {
   1115     if (mFreeChildren) {
   1116         mFreeChildren();
   1117     }
   1118 }
   1119 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   1330 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 
   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 
   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