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