rsdBcc.cpp revision 3ea5b9cc71960a95a34adfde600c8fb87d4f053a
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
19#include <bcc/BCCContext.h>
20#include <bcc/Renderscript/RSCompilerDriver.h>
21#include <bcc/Renderscript/RSExecutable.h>
22#include <bcc/Renderscript/RSInfo.h>
23
24#include "rsdBcc.h"
25#include "rsdRuntime.h"
26#include "rsdAllocation.h"
27#include "rsdIntrinsics.h"
28
29#include "rsContext.h"
30#include "rsElement.h"
31#include "rsScriptC.h"
32
33#include "utils/Vector.h"
34#include "utils/Timers.h"
35#include "utils/StopWatch.h"
36
37using namespace android;
38using namespace android::renderscript;
39
40
41static Script * setTLS(Script *sc) {
42    ScriptTLSStruct * tls = (ScriptTLSStruct *)pthread_getspecific(rsdgThreadTLSKey);
43    rsAssert(tls);
44    Script *old = tls->mScript;
45    tls->mScript = sc;
46    return old;
47}
48
49
50bool rsdScriptInit(const Context *rsc,
51                     ScriptC *script,
52                     char const *resName,
53                     char const *cacheDir,
54                     uint8_t const *bitcode,
55                     size_t bitcodeSize,
56                     uint32_t flags) {
57    //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
58    //ALOGE("rsdScriptInit %p %p", rsc, script);
59
60    pthread_mutex_lock(&rsdgInitMutex);
61
62    bcc::RSExecutable *exec;
63    const bcc::RSInfo *info;
64    DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript));
65    if (drv == NULL) {
66        goto error;
67    }
68    script->mHal.drv = drv;
69
70    drv->mCompilerContext = NULL;
71    drv->mCompilerDriver = NULL;
72    drv->mExecutable = NULL;
73
74    drv->mCompilerContext = new bcc::BCCContext();
75    if (drv->mCompilerContext == NULL) {
76        ALOGE("bcc: FAILS to create compiler context (out of memory)");
77        goto error;
78    }
79
80    drv->mCompilerDriver = new bcc::RSCompilerDriver();
81    if (drv->mCompilerDriver == NULL) {
82        ALOGE("bcc: FAILS to create compiler driver (out of memory)");
83        goto error;
84    }
85
86    script->mHal.info.isThreadable = true;
87
88    drv->mCompilerDriver->setRSRuntimeLookupFunction(rsdLookupRuntimeStub);
89    drv->mCompilerDriver->setRSRuntimeLookupContext(script);
90
91    exec = drv->mCompilerDriver->build(*drv->mCompilerContext,
92                                       cacheDir, resName,
93                                       (const char *)bitcode, bitcodeSize);
94
95    if (exec == NULL) {
96        ALOGE("bcc: FAILS to prepare executable for '%s'", resName);
97        goto error;
98    }
99
100    drv->mExecutable = exec;
101
102    exec->setThreadable(script->mHal.info.isThreadable);
103    if (!exec->syncInfo()) {
104        ALOGW("bcc: FAILS to synchronize the RS info file to the disk");
105    }
106
107    drv->mRoot = reinterpret_cast<int (*)()>(exec->getSymbolAddress("root"));
108    drv->mRootExpand =
109        reinterpret_cast<int (*)()>(exec->getSymbolAddress("root.expand"));
110    drv->mInit = reinterpret_cast<void (*)()>(exec->getSymbolAddress("init"));
111    drv->mFreeChildren =
112        reinterpret_cast<void (*)()>(exec->getSymbolAddress(".rs.dtor"));
113
114    info = &drv->mExecutable->getInfo();
115    // Copy info over to runtime
116    script->mHal.info.exportedFunctionCount = info->getExportFuncNames().size();
117    script->mHal.info.exportedVariableCount = info->getExportVarNames().size();
118    script->mHal.info.exportedPragmaCount = info->getPragmas().size();
119    script->mHal.info.exportedPragmaKeyList =
120        const_cast<const char**>(exec->getPragmaKeys().array());
121    script->mHal.info.exportedPragmaValueList =
122        const_cast<const char**>(exec->getPragmaValues().array());
123
124    if (drv->mRootExpand) {
125        script->mHal.info.root = drv->mRootExpand;
126    } else {
127        script->mHal.info.root = drv->mRoot;
128    }
129
130    if (script->mHal.info.exportedVariableCount) {
131        drv->mBoundAllocs = new Allocation *[script->mHal.info.exportedVariableCount];
132        memset(drv->mBoundAllocs, 0, sizeof(void *) * script->mHal.info.exportedVariableCount);
133    }
134
135    pthread_mutex_unlock(&rsdgInitMutex);
136    return true;
137
138error:
139
140    pthread_mutex_unlock(&rsdgInitMutex);
141    if (drv) {
142        delete drv->mCompilerContext;
143        delete drv->mCompilerDriver;
144        delete drv->mExecutable;
145        delete[] drv->mBoundAllocs;
146        free(drv);
147    }
148    script->mHal.drv = NULL;
149    return false;
150
151}
152
153bool rsdInitIntrinsic(const Context *rsc, Script *s, RsScriptIntrinsicID iid, Element *e) {
154    pthread_mutex_lock(&rsdgInitMutex);
155
156    DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript));
157    if (drv == NULL) {
158        goto error;
159    }
160    s->mHal.drv = drv;
161    drv->mIntrinsicID = iid;
162    drv->mIntrinsicData = rsdIntrinsic_Init(rsc, s, iid, &drv->mIntrinsicFuncs);
163    s->mHal.info.isThreadable = true;
164
165    pthread_mutex_unlock(&rsdgInitMutex);
166    return true;
167
168error:
169    pthread_mutex_unlock(&rsdgInitMutex);
170    return false;
171}
172
173typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
174
175static void wc_xy(void *usr, uint32_t idx) {
176    MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
177    RsForEachStubParamStruct p;
178    memcpy(&p, &mtls->fep, sizeof(p));
179    RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv;
180    uint32_t sig = mtls->sig;
181
182#if defined(ARCH_ARM_RS_USE_CACHED_SCANLINE_WRITE)
183    unsigned char buf[1024 * 8];
184#endif
185
186    outer_foreach_t fn = (outer_foreach_t) mtls->kernel;
187    while (1) {
188        uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
189        uint32_t yStart = mtls->yStart + slice * mtls->mSliceSize;
190        uint32_t yEnd = yStart + mtls->mSliceSize;
191        yEnd = rsMin(yEnd, mtls->yEnd);
192        if (yEnd <= yStart) {
193            return;
194        }
195
196        //ALOGE("usr idx %i, x %i,%i  y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
197        //ALOGE("usr ptr in %p,  out %p", mtls->fep.ptrIn, mtls->fep.ptrOut);
198
199#if defined(ARCH_ARM_RS_USE_CACHED_SCANLINE_WRITE)
200        if (mtls->fep.yStrideOut < sizeof(buf)) {
201            p.out = buf;
202            for (p.y = yStart; p.y < yEnd; p.y++) {
203                p.in = mtls->fep.ptrIn + (mtls->fep.yStrideIn * p.y);
204                fn(&p, mtls->xStart, mtls->xEnd, mtls->fep.eStrideIn, mtls->fep.eStrideOut);
205                memcpy(mtls->fep.ptrOut + (mtls->fep.yStrideOut * p.y), buf, mtls->fep.yStrideOut);
206            }
207        } else
208#endif
209            {
210            for (p.y = yStart; p.y < yEnd; p.y++) {
211                p.out = mtls->fep.ptrOut + (mtls->fep.yStrideOut * p.y) +
212                        (mtls->fep.eStrideOut * mtls->xStart);
213                p.in = mtls->fep.ptrIn + (mtls->fep.yStrideIn * p.y) +
214                       (mtls->fep.eStrideIn * mtls->xStart);
215                fn(&p, mtls->xStart, mtls->xEnd, mtls->fep.eStrideIn, mtls->fep.eStrideOut);
216            }
217        }
218    }
219}
220
221static void wc_x(void *usr, uint32_t idx) {
222    MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
223    RsForEachStubParamStruct p;
224    memcpy(&p, &mtls->fep, sizeof(p));
225    RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv;
226    uint32_t sig = mtls->sig;
227
228    outer_foreach_t fn = (outer_foreach_t) mtls->kernel;
229    while (1) {
230        uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
231        uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize;
232        uint32_t xEnd = xStart + mtls->mSliceSize;
233        xEnd = rsMin(xEnd, mtls->xEnd);
234        if (xEnd <= xStart) {
235            return;
236        }
237
238        //ALOGE("usr slice %i idx %i, x %i,%i", slice, idx, xStart, xEnd);
239        //ALOGE("usr ptr in %p,  out %p", mtls->fep.ptrIn, mtls->fep.ptrOut);
240
241        p.out = mtls->fep.ptrOut + (mtls->fep.eStrideOut * xStart);
242        p.in = mtls->fep.ptrIn + (mtls->fep.eStrideIn * xStart);
243        fn(&p, xStart, xEnd, mtls->fep.eStrideIn, mtls->fep.eStrideOut);
244    }
245}
246
247void rsdScriptInvokeForEachMtlsSetup(const Context *rsc,
248                                     const Allocation * ain,
249                                     Allocation * aout,
250                                     const void * usr,
251                                     uint32_t usrLen,
252                                     const RsScriptCall *sc,
253                                     MTLaunchStruct *mtls) {
254
255    memset(mtls, 0, sizeof(MTLaunchStruct));
256
257    if (ain) {
258        mtls->fep.dimX = ain->getType()->getDimX();
259        mtls->fep.dimY = ain->getType()->getDimY();
260        mtls->fep.dimZ = ain->getType()->getDimZ();
261        //mtls->dimArray = ain->getType()->getDimArray();
262    } else if (aout) {
263        mtls->fep.dimX = aout->getType()->getDimX();
264        mtls->fep.dimY = aout->getType()->getDimY();
265        mtls->fep.dimZ = aout->getType()->getDimZ();
266        //mtls->dimArray = aout->getType()->getDimArray();
267    } else {
268        rsc->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
269        return;
270    }
271
272    if (!sc || (sc->xEnd == 0)) {
273        mtls->xEnd = mtls->fep.dimX;
274    } else {
275        rsAssert(sc->xStart < mtls->fep.dimX);
276        rsAssert(sc->xEnd <= mtls->fep.dimX);
277        rsAssert(sc->xStart < sc->xEnd);
278        mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
279        mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
280        if (mtls->xStart >= mtls->xEnd) return;
281    }
282
283    if (!sc || (sc->yEnd == 0)) {
284        mtls->yEnd = mtls->fep.dimY;
285    } else {
286        rsAssert(sc->yStart < mtls->fep.dimY);
287        rsAssert(sc->yEnd <= mtls->fep.dimY);
288        rsAssert(sc->yStart < sc->yEnd);
289        mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
290        mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
291        if (mtls->yStart >= mtls->yEnd) return;
292    }
293
294    mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
295    mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
296    mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
297    mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
298
299    rsAssert(!ain || (ain->getType()->getDimZ() == 0));
300
301    Context *mrsc = (Context *)rsc;
302    mtls->rsc = mrsc;
303    mtls->ain = ain;
304    mtls->aout = aout;
305    mtls->fep.usr = usr;
306    mtls->fep.usrLen = usrLen;
307    mtls->mSliceSize = 10;
308    mtls->mSliceNum = 0;
309
310    mtls->fep.ptrIn = NULL;
311    mtls->fep.eStrideIn = 0;
312
313    if (ain) {
314        DrvAllocation *aindrv = (DrvAllocation *)ain->mHal.drv;
315        mtls->fep.ptrIn = (const uint8_t *)aindrv->lod[0].mallocPtr;
316        mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes();
317        mtls->fep.yStrideIn = aindrv->lod[0].stride;
318    }
319
320    mtls->fep.ptrOut = NULL;
321    mtls->fep.eStrideOut = 0;
322    if (aout) {
323        DrvAllocation *aoutdrv = (DrvAllocation *)aout->mHal.drv;
324        mtls->fep.ptrOut = (uint8_t *)aoutdrv->lod[0].mallocPtr;
325        mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes();
326        mtls->fep.yStrideOut = aoutdrv->lod[0].stride;
327    }
328}
329
330void rsdScriptLaunchThreads(const Context *rsc,
331                            Script *s,
332                            uint32_t slot,
333                            const Allocation * ain,
334                            Allocation * aout,
335                            const void * usr,
336                            uint32_t usrLen,
337                            const RsScriptCall *sc,
338                            MTLaunchStruct *mtls) {
339
340    Script * oldTLS = setTLS(s);
341    Context *mrsc = (Context *)rsc;
342    RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv;
343
344    if ((dc->mWorkers.mCount >= 1) && s->mHal.info.isThreadable && !dc->mInForEach) {
345        const size_t targetByteChunk = 16 * 1024;
346        dc->mInForEach = true;
347        if (mtls->fep.dimY > 1) {
348            uint32_t s1 = mtls->fep.dimY / ((dc->mWorkers.mCount + 1) * 4);
349            uint32_t s2 = 0;
350
351            // This chooses our slice size to rate limit atomic ops to
352            // one per 16k bytes of reads/writes.
353            if (mtls->fep.yStrideOut) {
354                s2 = targetByteChunk / mtls->fep.yStrideOut;
355            } else {
356                s2 = targetByteChunk / mtls->fep.yStrideIn;
357            }
358            mtls->mSliceSize = rsMin(s1, s2);
359
360            if(mtls->mSliceSize < 1) {
361                mtls->mSliceSize = 1;
362            }
363
364            rsdLaunchThreads(mrsc, wc_xy, mtls);
365        } else {
366            uint32_t s1 = mtls->fep.dimX / ((dc->mWorkers.mCount + 1) * 4);
367            uint32_t s2 = 0;
368
369            // This chooses our slice size to rate limit atomic ops to
370            // one per 16k bytes of reads/writes.
371            if (mtls->fep.eStrideOut) {
372                s2 = targetByteChunk / mtls->fep.eStrideOut;
373            } else {
374                s2 = targetByteChunk / mtls->fep.eStrideIn;
375            }
376            mtls->mSliceSize = rsMin(s1, s2);
377
378            if(mtls->mSliceSize < 1) {
379                mtls->mSliceSize = 1;
380            }
381
382            rsdLaunchThreads(mrsc, wc_x, mtls);
383        }
384        dc->mInForEach = false;
385
386        //ALOGE("launch 1");
387    } else {
388        RsForEachStubParamStruct p;
389        memcpy(&p, &mtls->fep, sizeof(p));
390        uint32_t sig = mtls->sig;
391
392        //ALOGE("launch 3");
393        outer_foreach_t fn = (outer_foreach_t) mtls->kernel;
394        for (p.ar[0] = mtls->arrayStart; p.ar[0] < mtls->arrayEnd; p.ar[0]++) {
395            for (p.z = mtls->zStart; p.z < mtls->zEnd; p.z++) {
396                for (p.y = mtls->yStart; p.y < mtls->yEnd; p.y++) {
397                    uint32_t offset = mtls->fep.dimY * mtls->fep.dimZ * p.ar[0] +
398                                      mtls->fep.dimY * p.z + p.y;
399                    p.out = mtls->fep.ptrOut + (mtls->fep.yStrideOut * offset) +
400                            (mtls->fep.eStrideOut * mtls->xStart);
401                    p.in = mtls->fep.ptrIn + (mtls->fep.yStrideIn * offset) +
402                           (mtls->fep.eStrideIn * mtls->xStart);
403                    fn(&p, mtls->xStart, mtls->xEnd, mtls->fep.eStrideIn, mtls->fep.eStrideOut);
404                }
405            }
406        }
407    }
408
409    setTLS(oldTLS);
410}
411
412void rsdScriptInvokeForEach(const Context *rsc,
413                            Script *s,
414                            uint32_t slot,
415                            const Allocation * ain,
416                            Allocation * aout,
417                            const void * usr,
418                            uint32_t usrLen,
419                            const RsScriptCall *sc) {
420
421    RsdHal * dc = (RsdHal *)rsc->mHal.drv;
422
423    MTLaunchStruct mtls;
424    rsdScriptInvokeForEachMtlsSetup(rsc, ain, aout, usr, usrLen, sc, &mtls);
425    mtls.script = s;
426    mtls.fep.slot = slot;
427
428    DrvScript *drv = (DrvScript *)s->mHal.drv;
429    if (drv->mIntrinsicID) {
430        mtls.kernel = (void (*)())drv->mIntrinsicFuncs.root;
431        mtls.fep.usr = drv->mIntrinsicData;
432    } else {
433        rsAssert(slot < drv->mExecutable->getExportForeachFuncAddrs().size());
434        mtls.kernel = reinterpret_cast<ForEachFunc_t>(
435                          drv->mExecutable->getExportForeachFuncAddrs()[slot]);
436        rsAssert(mtls.kernel != NULL);
437        mtls.sig = drv->mExecutable->getInfo().getExportForeachFuncs()[slot].second;
438    }
439
440
441    rsdScriptLaunchThreads(rsc, s, slot, ain, aout, usr, usrLen, sc, &mtls);
442}
443
444
445int rsdScriptInvokeRoot(const Context *dc, Script *script) {
446    DrvScript *drv = (DrvScript *)script->mHal.drv;
447
448    Script * oldTLS = setTLS(script);
449    int ret = drv->mRoot();
450    setTLS(oldTLS);
451
452    return ret;
453}
454
455void rsdScriptInvokeInit(const Context *dc, Script *script) {
456    DrvScript *drv = (DrvScript *)script->mHal.drv;
457
458    if (drv->mInit) {
459        drv->mInit();
460    }
461}
462
463void rsdScriptInvokeFreeChildren(const Context *dc, Script *script) {
464    DrvScript *drv = (DrvScript *)script->mHal.drv;
465
466    if (drv->mFreeChildren) {
467        drv->mFreeChildren();
468    }
469}
470
471void rsdScriptInvokeFunction(const Context *dc, Script *script,
472                            uint32_t slot,
473                            const void *params,
474                            size_t paramLength) {
475    DrvScript *drv = (DrvScript *)script->mHal.drv;
476    //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
477
478    Script * oldTLS = setTLS(script);
479    reinterpret_cast<void (*)(const void *, uint32_t)>(
480        drv->mExecutable->getExportFuncAddrs()[slot])(params, paramLength);
481    setTLS(oldTLS);
482}
483
484void rsdScriptSetGlobalVar(const Context *dc, const Script *script,
485                           uint32_t slot, void *data, size_t dataLength) {
486    DrvScript *drv = (DrvScript *)script->mHal.drv;
487    //rsAssert(!script->mFieldIsObject[slot]);
488    //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
489
490    if (drv->mIntrinsicID) {
491        drv->mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
492        return;
493    }
494
495    int32_t *destPtr = reinterpret_cast<int32_t *>(
496                          drv->mExecutable->getExportVarAddrs()[slot]);
497    if (!destPtr) {
498        //ALOGV("Calling setVar on slot = %i which is null", slot);
499        return;
500    }
501
502    memcpy(destPtr, data, dataLength);
503}
504
505void rsdScriptSetGlobalVarWithElemDims(
506        const android::renderscript::Context *dc,
507        const android::renderscript::Script *script,
508        uint32_t slot, void *data, size_t dataLength,
509        const android::renderscript::Element *elem,
510        const size_t *dims, size_t dimLength) {
511    DrvScript *drv = (DrvScript *)script->mHal.drv;
512
513    int32_t *destPtr = reinterpret_cast<int32_t *>(
514        drv->mExecutable->getExportVarAddrs()[slot]);
515    if (!destPtr) {
516        //ALOGV("Calling setVar on slot = %i which is null", slot);
517        return;
518    }
519
520    // We want to look at dimension in terms of integer components,
521    // but dimLength is given in terms of bytes.
522    dimLength /= sizeof(int);
523
524    // Only a single dimension is currently supported.
525    rsAssert(dimLength == 1);
526    if (dimLength == 1) {
527        // First do the increment loop.
528        size_t stride = elem->getSizeBytes();
529        char *cVal = reinterpret_cast<char *>(data);
530        for (size_t i = 0; i < dims[0]; i++) {
531            elem->incRefs(cVal);
532            cVal += stride;
533        }
534
535        // Decrement loop comes after (to prevent race conditions).
536        char *oldVal = reinterpret_cast<char *>(destPtr);
537        for (size_t i = 0; i < dims[0]; i++) {
538            elem->decRefs(oldVal);
539            oldVal += stride;
540        }
541    }
542
543    memcpy(destPtr, data, dataLength);
544}
545
546void rsdScriptSetGlobalBind(const Context *dc, const Script *script, uint32_t slot, Allocation *data) {
547    DrvScript *drv = (DrvScript *)script->mHal.drv;
548
549    //rsAssert(!script->mFieldIsObject[slot]);
550    //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
551
552    rsAssert(!drv->mIntrinsicID);
553
554    int32_t *destPtr = reinterpret_cast<int32_t *>(
555                          drv->mExecutable->getExportVarAddrs()[slot]);
556    if (!destPtr) {
557        //ALOGV("Calling setVar on slot = %i which is null", slot);
558        return;
559    }
560
561    void *ptr = NULL;
562    drv->mBoundAllocs[slot] = data;
563    if(data) {
564        DrvAllocation *allocDrv = (DrvAllocation *)data->mHal.drv;
565        ptr = allocDrv->lod[0].mallocPtr;
566    }
567    memcpy(destPtr, &ptr, sizeof(void *));
568}
569
570void rsdScriptSetGlobalObj(const Context *dc, const Script *script, uint32_t slot, ObjectBase *data) {
571    DrvScript *drv = (DrvScript *)script->mHal.drv;
572    //rsAssert(script->mFieldIsObject[slot]);
573    //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
574
575    if (drv->mIntrinsicID) {
576        drv->mIntrinsicFuncs.setVarObj(dc, script, drv->mIntrinsicData, slot,
577                                       static_cast<Allocation *>(data));
578        return;
579    }
580
581    int32_t *destPtr = reinterpret_cast<int32_t *>(
582                          drv->mExecutable->getExportVarAddrs()[slot]);
583    if (!destPtr) {
584        //ALOGV("Calling setVar on slot = %i which is null", slot);
585        return;
586    }
587
588    rsrSetObject(dc, script, (ObjectBase **)destPtr, data);
589}
590
591void rsdScriptDestroy(const Context *dc, Script *script) {
592    DrvScript *drv = (DrvScript *)script->mHal.drv;
593
594    if (drv == NULL) {
595        return;
596    }
597
598    if (drv->mExecutable) {
599        Vector<void *>::const_iterator var_addr_iter =
600            drv->mExecutable->getExportVarAddrs().begin();
601        Vector<void *>::const_iterator var_addr_end =
602            drv->mExecutable->getExportVarAddrs().end();
603
604        bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter =
605            drv->mExecutable->getInfo().getObjectSlots().begin();
606        bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end =
607            drv->mExecutable->getInfo().getObjectSlots().end();
608
609        while ((var_addr_iter != var_addr_end) &&
610               (is_object_iter != is_object_end)) {
611            // The field address can be NULL if the script-side has optimized
612            // the corresponding global variable away.
613            ObjectBase **obj_addr =
614                reinterpret_cast<ObjectBase **>(*var_addr_iter);
615            if (*is_object_iter) {
616                if (*var_addr_iter != NULL) {
617                    rsrClearObject(dc, script, obj_addr);
618                }
619            }
620            var_addr_iter++;
621            is_object_iter++;
622        }
623    }
624
625    delete drv->mCompilerContext;
626    delete drv->mCompilerDriver;
627    delete drv->mExecutable;
628    delete[] drv->mBoundAllocs;
629    free(drv);
630    script->mHal.drv = NULL;
631}
632
633Allocation * rsdScriptGetAllocationForPointer(const android::renderscript::Context *dc,
634                                              const android::renderscript::Script *sc,
635                                              const void *ptr) {
636    DrvScript *drv = (DrvScript *)sc->mHal.drv;
637    if (!ptr) {
638        return NULL;
639    }
640
641    for (uint32_t ct=0; ct < sc->mHal.info.exportedVariableCount; ct++) {
642        Allocation *a = drv->mBoundAllocs[ct];
643        if (!a) continue;
644        DrvAllocation *adrv = (DrvAllocation *)a->mHal.drv;
645        if (adrv->lod[0].mallocPtr == ptr) {
646            return a;
647        }
648    }
649    ALOGE("rsGetAllocation, failed to find %p", ptr);
650    return NULL;
651}
652
653