Home | History | Annotate | Download | only in driver
      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 "rsdCore.h"
     18 #include "rsdBcc.h"
     19 #include "rsdRuntime.h"
     20 #include "rsdAllocation.h"
     21 #include "rsdIntrinsics.h"
     22 
     23 #include "rsContext.h"
     24 #include "rsElement.h"
     25 #include "rsScriptC.h"
     26 
     27 #include "utils/Vector.h"
     28 #include "utils/Timers.h"
     29 #include "utils/StopWatch.h"
     30 #include "utils/String8.h"
     31 
     32 #include <dlfcn.h>
     33 #include <stdio.h>
     34 #include <string.h>
     35 
     36 using namespace android;
     37 using namespace android::renderscript;
     38 
     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 
     52 
     53 static Script * setTLS(Script *sc) {
     54     ScriptTLSStruct * tls = (ScriptTLSStruct *)pthread_getspecific(rsdgThreadTLSKey);
     55     rsAssert(tls);
     56     Script *old = tls->mScript;
     57     tls->mScript = sc;
     58     return old;
     59 }
     60 
     61 
     62 bool rsdScriptInit(const Context *rsc,
     63                      ScriptC *script,
     64                      char const *resName,
     65                      char const *cacheDir,
     66                      uint8_t const *bitcode,
     67                      size_t bitcodeSize,
     68                      uint32_t flags) {
     69     //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
     70     //ALOGE("rsdScriptInit %p %p", rsc, script);
     71 
     72     pthread_mutex_lock(&rsdgInitMutex);
     73 
     74     String8 scriptSOName(cacheDir);
     75     scriptSOName = scriptSOName.getPathDir();
     76     scriptSOName.appendPath("lib");
     77     scriptSOName.append("/lib");
     78     scriptSOName.append(resName);
     79     scriptSOName.append(".so");
     80 
     81     String8 scriptInfoName(cacheDir);
     82     scriptInfoName = scriptInfoName.getPathDir();
     83     scriptInfoName.appendPath("lib/");
     84     scriptInfoName.append(resName);
     85     scriptInfoName.append(".bcinfo");
     86 
     87     void *scriptSO = NULL;
     88     FILE *fp = NULL;
     89     DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript));
     90     if (drv == NULL) {
     91         goto error;
     92     }
     93     script->mHal.drv = drv;
     94 
     95     ALOGE("Opening up info object: %s", scriptInfoName.string());
     96 
     97     fp = fopen(scriptInfoName.string(), "r");
     98     if (!fp) {
     99         ALOGE("Unable to open info file: %s", scriptInfoName.string());
    100         goto error;
    101     }
    102 
    103     ALOGE("Opening up shared object: %s", scriptSOName.string());
    104     scriptSO = dlopen(scriptSOName.string(), RTLD_NOW | RTLD_LOCAL);
    105     if (scriptSO == NULL) {
    106         ALOGE("Unable to open shared library (%s): %s",
    107               scriptSOName.string(), dlerror());
    108         goto error;
    109     }
    110     drv->mScriptSO = scriptSO;
    111 
    112     if (scriptSO) {
    113         char line[MAXLINE];
    114         drv->mScriptSO = scriptSO;
    115         drv->mRoot = (RootFunc_t) dlsym(scriptSO, "root");
    116         if (drv->mRoot) {
    117             ALOGE("Found root(): %p", drv->mRoot);
    118         }
    119         drv->mRootExpand = (RootFunc_t) dlsym(scriptSO, "root.expand");
    120         if (drv->mRootExpand) {
    121             ALOGE("Found root.expand(): %p", drv->mRootExpand);
    122         }
    123         drv->mInit = (InvokeFunc_t) dlsym(scriptSO, "init");
    124         if (drv->mInit) {
    125             ALOGE("Found init(): %p", drv->mInit);
    126         }
    127         drv->mFreeChildren = (InvokeFunc_t) dlsym(scriptSO, ".rs.dtor");
    128         if (drv->mFreeChildren) {
    129             ALOGE("Found .rs.dtor(): %p", drv->mFreeChildren);
    130         }
    131 
    132         size_t varCount = 0;
    133         if (fgets(line, MAXLINE, fp) == NULL) {
    134             goto error;
    135         }
    136         if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
    137             ALOGE("Invalid export var count!: %s", line);
    138             goto error;
    139         }
    140 
    141         script->mHal.info.exportedVariableCount = varCount;
    142         ALOGE("varCount: %zu", varCount);
    143         if (varCount > 0) {
    144             // Start by creating/zeroing this member, since we don't want to
    145             // accidentally clean up invalid pointers later (if we error out).
    146             drv->mFieldIsObject = new bool[varCount];
    147             if (drv->mFieldIsObject == NULL) {
    148                 goto error;
    149             }
    150             memset(drv->mFieldIsObject, 0,
    151                    varCount * sizeof(*drv->mFieldIsObject));
    152             drv->mFieldAddress = new void*[varCount];
    153             if (drv->mFieldAddress == NULL) {
    154                 goto error;
    155             }
    156             for (size_t i = 0; i < varCount; ++i) {
    157                 if (fgets(line, MAXLINE, fp) == NULL) {
    158                     goto error;
    159                 }
    160                 char *c = strrchr(line, '\n');
    161                 if (c) {
    162                     *c = '\0';
    163                 }
    164                 drv->mFieldAddress[i] = dlsym(scriptSO, line);
    165                 if (drv->mFieldAddress[i] == NULL) {
    166                     ALOGE("Failed to find variable address for %s: %s",
    167                           line, dlerror());
    168                     // Not a critical error if we don't find a global variable.
    169                 }
    170                 else {
    171                     ALOGE("Found variable %s at %p", line,
    172                           drv->mFieldAddress[i]);
    173                 }
    174             }
    175         }
    176 
    177         size_t funcCount = 0;
    178         if (fgets(line, MAXLINE, fp) == NULL) {
    179             goto error;
    180         }
    181         if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
    182             ALOGE("Invalid export func count!: %s", line);
    183             goto error;
    184         }
    185 
    186         script->mHal.info.exportedFunctionCount = funcCount;
    187         ALOGE("funcCount: %zu", funcCount);
    188 
    189         if (funcCount > 0) {
    190             drv->mInvokeFunctions = new InvokeFunc_t[funcCount];
    191             if (drv->mInvokeFunctions == NULL) {
    192                 goto error;
    193             }
    194             for (size_t i = 0; i < funcCount; ++i) {
    195                 if (fgets(line, MAXLINE, fp) == NULL) {
    196                     goto error;
    197                 }
    198                 char *c = strrchr(line, '\n');
    199                 if (c) {
    200                     *c = '\0';
    201                 }
    202 
    203                 drv->mInvokeFunctions[i] =
    204                         (InvokeFunc_t) dlsym(scriptSO, line);
    205                 if (drv->mInvokeFunctions[i] == NULL) {
    206                     ALOGE("Failed to get function address for %s(): %s",
    207                           line, dlerror());
    208                     goto error;
    209                 }
    210                 else {
    211                     ALOGE("Found InvokeFunc_t %s at %p", line,
    212                           drv->mInvokeFunctions[i]);
    213                 }
    214             }
    215         }
    216 
    217         size_t forEachCount = 0;
    218         if (fgets(line, MAXLINE, fp) == NULL) {
    219             goto error;
    220         }
    221         if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
    222             ALOGE("Invalid export forEach count!: %s", line);
    223             goto error;
    224         }
    225 
    226         if (forEachCount > 0) {
    227 
    228             drv->mForEachSignatures = new uint32_t[forEachCount];
    229             if (drv->mForEachSignatures == NULL) {
    230                 goto error;
    231             }
    232             drv->mForEachFunctions = new ForEachFunc_t[forEachCount];
    233             if (drv->mForEachFunctions == NULL) {
    234                 goto error;
    235             }
    236             for (size_t i = 0; i < forEachCount; ++i) {
    237                 unsigned int tmpSig = 0;
    238                 char tmpName[MAXLINE];
    239 
    240                 if (fgets(line, MAXLINE, fp) == NULL) {
    241                     goto error;
    242                 }
    243                 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
    244                            &tmpSig, tmpName) != 2) {
    245                     ALOGE("Invalid export forEach!: %s", line);
    246                     goto error;
    247                 }
    248 
    249                 drv->mForEachSignatures[i] = tmpSig;
    250                 drv->mForEachFunctions[i] =
    251                         (ForEachFunc_t) dlsym(scriptSO, tmpName);
    252                 if (drv->mForEachFunctions[i] == NULL) {
    253                     ALOGE("Failed to find forEach function address for %s: %s",
    254                           tmpName, dlerror());
    255                     goto error;
    256                 }
    257                 else {
    258                     // TODO - Maybe add ForEachExpandPass to .so creation and
    259                     // then lookup the ".expand" version of these kernels
    260                     // instead.
    261                     ALOGE("Found forEach %s at %p", tmpName,
    262                           drv->mForEachFunctions[i]);
    263                 }
    264             }
    265         }
    266 
    267         size_t objectSlotCount = 0;
    268         if (fgets(line, MAXLINE, fp) == NULL) {
    269             goto error;
    270         }
    271         if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
    272             ALOGE("Invalid object slot count!: %s", line);
    273             goto error;
    274         }
    275 
    276         if (objectSlotCount > 0) {
    277             rsAssert(varCount > 0);
    278             for (size_t i = 0; i < objectSlotCount; ++i) {
    279                 uint32_t varNum = 0;
    280                 if (fgets(line, MAXLINE, fp) == NULL) {
    281                     goto error;
    282                 }
    283                 if (sscanf(line, "%u", &varNum) != 1) {
    284                     ALOGE("Invalid object slot!: %s", line);
    285                     goto error;
    286                 }
    287 
    288                 if (varNum < varCount) {
    289                     drv->mFieldIsObject[varNum] = true;
    290                 }
    291             }
    292         }
    293 
    294         script->mHal.info.exportedPragmaCount = 0;
    295 
    296         if (drv->mRootExpand) {
    297             script->mHal.info.root = drv->mRootExpand;
    298         } else {
    299             script->mHal.info.root = drv->mRoot;
    300         }
    301 
    302         if (varCount > 0) {
    303             drv->mBoundAllocs = new Allocation *[varCount];
    304             memset(drv->mBoundAllocs, 0, varCount * sizeof(*drv->mBoundAllocs));
    305         }
    306 
    307         script->mHal.info.isThreadable = true;
    308 
    309         if (scriptSO == (void*)1) {
    310             rsdLookupRuntimeStub(script, "acos");
    311         }
    312     }
    313 
    314     fclose(fp);
    315     pthread_mutex_unlock(&rsdgInitMutex);
    316     return true;
    317 
    318 error:
    319 
    320     fclose(fp);
    321     pthread_mutex_unlock(&rsdgInitMutex);
    322     if (drv) {
    323         delete[] drv->mInvokeFunctions;
    324         delete[] drv->mForEachFunctions;
    325         delete[] drv->mFieldAddress;
    326         delete[] drv->mFieldIsObject;
    327         delete[] drv->mForEachSignatures;
    328         delete[] drv->mBoundAllocs;
    329         if (drv->mScriptSO) {
    330             dlclose(drv->mScriptSO);
    331         }
    332         free(drv);
    333     }
    334     script->mHal.drv = NULL;
    335     return false;
    336 
    337 }
    338 
    339 bool rsdInitIntrinsic(const Context *rsc, Script *s, RsScriptIntrinsicID iid, Element *e) {
    340     pthread_mutex_lock(&rsdgInitMutex);
    341 
    342     DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript));
    343     if (drv == NULL) {
    344         goto error;
    345     }
    346     s->mHal.drv = drv;
    347     drv->mIntrinsicID = iid;
    348     drv->mIntrinsicData = rsdIntrinsic_Init(rsc, s, iid, &drv->mIntrinsicFuncs);
    349     s->mHal.info.isThreadable = true;
    350 
    351     pthread_mutex_unlock(&rsdgInitMutex);
    352     return true;
    353 
    354 error:
    355     pthread_mutex_unlock(&rsdgInitMutex);
    356     return false;
    357 }
    358 
    359 typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
    360 
    361 static void wc_xy(void *usr, uint32_t idx) {
    362     MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
    363     RsForEachStubParamStruct p;
    364     memcpy(&p, &mtls->fep, sizeof(p));
    365     RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv;
    366     uint32_t sig = mtls->sig;
    367 
    368     rs_t bare_fn = (rs_t) mtls->kernel;
    369     while (1) {
    370         uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
    371         uint32_t yStart = mtls->yStart + slice * mtls->mSliceSize;
    372         uint32_t yEnd = yStart + mtls->mSliceSize;
    373         yEnd = rsMin(yEnd, mtls->yEnd);
    374         if (yEnd <= yStart) {
    375             return;
    376         }
    377 
    378         //ALOGE("usr idx %i, x %i,%i  y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
    379         //ALOGE("usr ptr in %p,  out %p", mtls->ptrIn, mtls->ptrOut);
    380         for (p.y = yStart; p.y < yEnd; p.y++) {
    381             p.out = mtls->fep.ptrOut + (mtls->fep.yStrideOut * p.y);
    382             p.in = mtls->fep.ptrIn + (mtls->fep.yStrideIn * p.y);
    383             for (uint32_t x = mtls->xStart; x < mtls->xEnd; ++x) {
    384                 bare_fn(p.in, p.out, p.usr, x, p.y, 0, 0);
    385                 p.in = (char *)(p.in) + mtls->fep.eStrideIn;
    386                 p.out = (char *)(p.out) + mtls->fep.eStrideOut;
    387             }
    388         }
    389     }
    390 }
    391 
    392 static void wc_x(void *usr, uint32_t idx) {
    393     MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
    394     RsForEachStubParamStruct p;
    395     memcpy(&p, &mtls->fep, sizeof(p));
    396     RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv;
    397     uint32_t sig = mtls->sig;
    398 
    399     rs_t bare_fn = (rs_t) mtls->kernel;
    400     while (1) {
    401         uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
    402         uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize;
    403         uint32_t xEnd = xStart + mtls->mSliceSize;
    404         xEnd = rsMin(xEnd, mtls->xEnd);
    405         if (xEnd <= xStart) {
    406             return;
    407         }
    408 
    409         //ALOGE("usr slice %i idx %i, x %i,%i", slice, idx, xStart, xEnd);
    410         //ALOGE("usr ptr in %p,  out %p", mtls->ptrIn, mtls->ptrOut);
    411 
    412         p.out = mtls->fep.ptrOut + (mtls->fep.eStrideOut * xStart);
    413         p.in = mtls->fep.ptrIn + (mtls->fep.eStrideIn * xStart);
    414         for (uint32_t x = mtls->xStart; x < mtls->xEnd; ++x) {
    415             bare_fn(p.in, p.out, p.usr, x, 0, 0, 0);
    416             p.in = (char *)(p.in) + mtls->fep.eStrideIn;
    417             p.out = (char *)(p.out) + mtls->fep.eStrideOut;
    418         }
    419     }
    420 }
    421 
    422 void rsdScriptInvokeForEachMtlsSetup(const Context *rsc,
    423                                      const Allocation * ain,
    424                                      Allocation * aout,
    425                                      const void * usr,
    426                                      uint32_t usrLen,
    427                                      const RsScriptCall *sc,
    428                                      MTLaunchStruct *mtls) {
    429 
    430     memset(mtls, 0, sizeof(MTLaunchStruct));
    431 
    432     if (ain) {
    433         mtls->fep.dimX = ain->getType()->getDimX();
    434         mtls->fep.dimY = ain->getType()->getDimY();
    435         mtls->fep.dimZ = ain->getType()->getDimZ();
    436         //mtls->dimArray = ain->getType()->getDimArray();
    437     } else if (aout) {
    438         mtls->fep.dimX = aout->getType()->getDimX();
    439         mtls->fep.dimY = aout->getType()->getDimY();
    440         mtls->fep.dimZ = aout->getType()->getDimZ();
    441         //mtls->dimArray = aout->getType()->getDimArray();
    442     } else {
    443         rsc->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
    444         return;
    445     }
    446 
    447     if (!sc || (sc->xEnd == 0)) {
    448         mtls->xEnd = mtls->fep.dimX;
    449     } else {
    450         rsAssert(sc->xStart < mtls->fep.dimX);
    451         rsAssert(sc->xEnd <= mtls->fep.dimX);
    452         rsAssert(sc->xStart < sc->xEnd);
    453         mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
    454         mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
    455         if (mtls->xStart >= mtls->xEnd) return;
    456     }
    457 
    458     if (!sc || (sc->yEnd == 0)) {
    459         mtls->yEnd = mtls->fep.dimY;
    460     } else {
    461         rsAssert(sc->yStart < mtls->fep.dimY);
    462         rsAssert(sc->yEnd <= mtls->fep.dimY);
    463         rsAssert(sc->yStart < sc->yEnd);
    464         mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
    465         mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
    466         if (mtls->yStart >= mtls->yEnd) return;
    467     }
    468 
    469     mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
    470     mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
    471     mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
    472     mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
    473 
    474     rsAssert(!ain || (ain->getType()->getDimZ() == 0));
    475 
    476     Context *mrsc = (Context *)rsc;
    477     mtls->rsc = mrsc;
    478     mtls->ain = ain;
    479     mtls->aout = aout;
    480     mtls->fep.usr = usr;
    481     mtls->fep.usrLen = usrLen;
    482     mtls->mSliceSize = 10;
    483     mtls->mSliceNum = 0;
    484 
    485     mtls->fep.ptrIn = NULL;
    486     mtls->fep.eStrideIn = 0;
    487 
    488     if (ain) {
    489         DrvAllocation *aindrv = (DrvAllocation *)ain->mHal.drv;
    490         mtls->fep.ptrIn = (const uint8_t *)aindrv->lod[0].mallocPtr;
    491         mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes();
    492         mtls->fep.yStrideIn = aindrv->lod[0].stride;
    493     }
    494 
    495     mtls->fep.ptrOut = NULL;
    496     mtls->fep.eStrideOut = 0;
    497     if (aout) {
    498         DrvAllocation *aoutdrv = (DrvAllocation *)aout->mHal.drv;
    499         mtls->fep.ptrOut = (uint8_t *)aoutdrv->lod[0].mallocPtr;
    500         mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes();
    501         mtls->fep.yStrideOut = aoutdrv->lod[0].stride;
    502     }
    503 }
    504 
    505 void rsdScriptLaunchThreads(const Context *rsc,
    506                             Script *s,
    507                             uint32_t slot,
    508                             const Allocation * ain,
    509                             Allocation * aout,
    510                             const void * usr,
    511                             uint32_t usrLen,
    512                             const RsScriptCall *sc,
    513                             MTLaunchStruct *mtls) {
    514 
    515     Script * oldTLS = setTLS(s);
    516     Context *mrsc = (Context *)rsc;
    517     RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv;
    518 
    519     if ((dc->mWorkers.mCount > 1) && s->mHal.info.isThreadable && !dc->mInForEach) {
    520         dc->mInForEach = true;
    521         if (mtls->fep.dimY > 1) {
    522             mtls->mSliceSize = mtls->fep.dimY / (dc->mWorkers.mCount * 4);
    523             if(mtls->mSliceSize < 1) {
    524                 mtls->mSliceSize = 1;
    525             }
    526 
    527             rsdLaunchThreads(mrsc, wc_xy, mtls);
    528         } else {
    529             mtls->mSliceSize = mtls->fep.dimX / (dc->mWorkers.mCount * 4);
    530             if(mtls->mSliceSize < 1) {
    531                 mtls->mSliceSize = 1;
    532             }
    533 
    534             rsdLaunchThreads(mrsc, wc_x, mtls);
    535         }
    536         dc->mInForEach = false;
    537 
    538         //ALOGE("launch 1");
    539     } else {
    540         RsForEachStubParamStruct p;
    541         memcpy(&p, &mtls->fep, sizeof(p));
    542         uint32_t sig = mtls->sig;
    543 
    544         //ALOGE("launch 3");
    545         outer_foreach_t fn = (outer_foreach_t) mtls->kernel;
    546         for (p.ar[0] = mtls->arrayStart; p.ar[0] < mtls->arrayEnd; p.ar[0]++) {
    547             for (p.z = mtls->zStart; p.z < mtls->zEnd; p.z++) {
    548                 for (p.y = mtls->yStart; p.y < mtls->yEnd; p.y++) {
    549                     uint32_t offset = mtls->fep.dimY * mtls->fep.dimZ * p.ar[0] +
    550                                       mtls->fep.dimY * p.z + p.y;
    551                     p.out = mtls->fep.ptrOut + (mtls->fep.yStrideOut * offset);
    552                     p.in = mtls->fep.ptrIn + (mtls->fep.yStrideIn * offset);
    553                     fn(&p, mtls->xStart, mtls->xEnd, mtls->fep.eStrideIn, mtls->fep.eStrideOut);
    554                 }
    555             }
    556         }
    557     }
    558 
    559     setTLS(oldTLS);
    560 }
    561 
    562 void rsdScriptInvokeForEach(const Context *rsc,
    563                             Script *s,
    564                             uint32_t slot,
    565                             const Allocation * ain,
    566                             Allocation * aout,
    567                             const void * usr,
    568                             uint32_t usrLen,
    569                             const RsScriptCall *sc) {
    570 
    571     RsdHal * dc = (RsdHal *)rsc->mHal.drv;
    572 
    573     MTLaunchStruct mtls;
    574     rsdScriptInvokeForEachMtlsSetup(rsc, ain, aout, usr, usrLen, sc, &mtls);
    575     mtls.script = s;
    576     mtls.fep.slot = slot;
    577 
    578     DrvScript *drv = (DrvScript *)s->mHal.drv;
    579     if (drv->mIntrinsicID) {
    580         mtls.kernel = (void (*)())drv->mIntrinsicFuncs.root;
    581         mtls.fep.usr = drv->mIntrinsicData;
    582     } else {
    583 		mtls.kernel = drv->mForEachFunctions[slot];
    584         rsAssert(mtls.kernel != NULL);
    585         mtls.sig = drv->mForEachSignatures[slot];
    586     }
    587 
    588 
    589     rsdScriptLaunchThreads(rsc, s, slot, ain, aout, usr, usrLen, sc, &mtls);
    590 }
    591 
    592 
    593 int rsdScriptInvokeRoot(const Context *dc, Script *script) {
    594     DrvScript *drv = (DrvScript *)script->mHal.drv;
    595 
    596     Script * oldTLS = setTLS(script);
    597     int ret = drv->mRoot();
    598     setTLS(oldTLS);
    599 
    600     return ret;
    601 }
    602 
    603 void rsdScriptInvokeInit(const Context *dc, Script *script) {
    604     DrvScript *drv = (DrvScript *)script->mHal.drv;
    605 
    606     if (drv->mInit) {
    607         drv->mInit();
    608     }
    609 }
    610 
    611 void rsdScriptInvokeFreeChildren(const Context *dc, Script *script) {
    612     DrvScript *drv = (DrvScript *)script->mHal.drv;
    613 
    614     if (drv->mFreeChildren) {
    615         drv->mFreeChildren();
    616     }
    617 }
    618 
    619 void rsdScriptInvokeFunction(const Context *dc, Script *script,
    620                             uint32_t slot,
    621                             const void *params,
    622                             size_t paramLength) {
    623     DrvScript *drv = (DrvScript *)script->mHal.drv;
    624     //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
    625 
    626     Script * oldTLS = setTLS(script);
    627     reinterpret_cast<void (*)(const void *, uint32_t)>(
    628         drv->mInvokeFunctions[slot])(params, paramLength);
    629     setTLS(oldTLS);
    630 }
    631 
    632 void rsdScriptSetGlobalVar(const Context *dc, const Script *script,
    633                            uint32_t slot, void *data, size_t dataLength) {
    634     DrvScript *drv = (DrvScript *)script->mHal.drv;
    635     //rsAssert(!script->mFieldIsObject[slot]);
    636     //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
    637 
    638     if (drv->mIntrinsicID) {
    639         drv->mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
    640         return;
    641     }
    642 
    643     int32_t *destPtr = reinterpret_cast<int32_t *>(drv->mFieldAddress[slot]);
    644     if (!destPtr) {
    645         //ALOGV("Calling setVar on slot = %i which is null", slot);
    646         return;
    647     }
    648 
    649     memcpy(destPtr, data, dataLength);
    650 }
    651 
    652 void rsdScriptSetGlobalVarWithElemDims(
    653         const android::renderscript::Context *dc,
    654         const android::renderscript::Script *script,
    655         uint32_t slot, void *data, size_t dataLength,
    656         const android::renderscript::Element *elem,
    657         const size_t *dims, size_t dimLength) {
    658     DrvScript *drv = (DrvScript *)script->mHal.drv;
    659 
    660     int32_t *destPtr = reinterpret_cast<int32_t *>(drv->mFieldAddress[slot]);
    661     if (!destPtr) {
    662         //ALOGV("Calling setVar on slot = %i which is null", slot);
    663         return;
    664     }
    665 
    666     // We want to look at dimension in terms of integer components,
    667     // but dimLength is given in terms of bytes.
    668     dimLength /= sizeof(int);
    669 
    670     // Only a single dimension is currently supported.
    671     rsAssert(dimLength == 1);
    672     if (dimLength == 1) {
    673         // First do the increment loop.
    674         size_t stride = elem->getSizeBytes();
    675         char *cVal = reinterpret_cast<char *>(data);
    676         for (size_t i = 0; i < dims[0]; i++) {
    677             elem->incRefs(cVal);
    678             cVal += stride;
    679         }
    680 
    681         // Decrement loop comes after (to prevent race conditions).
    682         char *oldVal = reinterpret_cast<char *>(destPtr);
    683         for (size_t i = 0; i < dims[0]; i++) {
    684             elem->decRefs(oldVal);
    685             oldVal += stride;
    686         }
    687     }
    688 
    689     memcpy(destPtr, data, dataLength);
    690 }
    691 
    692 void rsdScriptSetGlobalBind(const Context *dc, const Script *script, uint32_t slot, Allocation *data) {
    693     DrvScript *drv = (DrvScript *)script->mHal.drv;
    694 
    695     //rsAssert(!script->mFieldIsObject[slot]);
    696     //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
    697 
    698     if (drv->mIntrinsicID) {
    699         drv->mIntrinsicFuncs.bind(dc, script, drv->mIntrinsicData, slot, data);
    700         return;
    701     }
    702 
    703     int32_t *destPtr = reinterpret_cast<int32_t *>(drv->mFieldAddress[slot]);
    704     if (!destPtr) {
    705         //ALOGV("Calling setVar on slot = %i which is null", slot);
    706         return;
    707     }
    708 
    709     void *ptr = NULL;
    710     drv->mBoundAllocs[slot] = data;
    711     if(data) {
    712         DrvAllocation *allocDrv = (DrvAllocation *)data->mHal.drv;
    713         ptr = allocDrv->lod[0].mallocPtr;
    714     }
    715     memcpy(destPtr, &ptr, sizeof(void *));
    716 }
    717 
    718 void rsdScriptSetGlobalObj(const Context *dc, const Script *script, uint32_t slot, ObjectBase *data) {
    719     DrvScript *drv = (DrvScript *)script->mHal.drv;
    720     //rsAssert(script->mFieldIsObject[slot]);
    721     //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
    722 
    723     int32_t *destPtr = reinterpret_cast<int32_t *>(drv->mFieldAddress[slot]);
    724     if (!destPtr) {
    725         //ALOGV("Calling setVar on slot = %i which is null", slot);
    726         return;
    727     }
    728 
    729     rsrSetObject(dc, script, (ObjectBase **)destPtr, data);
    730 }
    731 
    732 void rsdScriptDestroy(const Context *dc, Script *script) {
    733     DrvScript *drv = (DrvScript *)script->mHal.drv;
    734 
    735     if (drv == NULL) {
    736         return;
    737     }
    738 
    739     for (size_t i = 0; i < script->mHal.info.exportedVariableCount; ++i) {
    740         if (drv->mFieldIsObject[i]) {
    741             if (drv->mFieldAddress[i] != NULL) {
    742                 ObjectBase **obj_addr =
    743                     reinterpret_cast<ObjectBase **>(drv->mFieldAddress[i]);
    744                 rsrClearObject(dc, script, obj_addr);
    745             }
    746         }
    747     }
    748 
    749     delete[] drv->mInvokeFunctions;
    750     delete[] drv->mForEachFunctions;
    751     delete[] drv->mFieldAddress;
    752     delete[] drv->mFieldIsObject;
    753     delete[] drv->mForEachSignatures;
    754     delete[] drv->mBoundAllocs;
    755     if (drv->mScriptSO) {
    756         dlclose(drv->mScriptSO);
    757     }
    758     free(drv);
    759     script->mHal.drv = NULL;
    760 }
    761 
    762 Allocation * rsdScriptGetAllocationForPointer(const android::renderscript::Context *dc,
    763                                               const android::renderscript::Script *sc,
    764                                               const void *ptr) {
    765     DrvScript *drv = (DrvScript *)sc->mHal.drv;
    766     if (!ptr) {
    767         return NULL;
    768     }
    769 
    770     for (uint32_t ct=0; ct < sc->mHal.info.exportedVariableCount; ct++) {
    771         Allocation *a = drv->mBoundAllocs[ct];
    772         if (!a) continue;
    773         DrvAllocation *adrv = (DrvAllocation *)a->mHal.drv;
    774         if (adrv->lod[0].mallocPtr == ptr) {
    775             return a;
    776         }
    777     }
    778     ALOGE("rsGetAllocation, failed to find %p", ptr);
    779     return NULL;
    780 }
    781 
    782