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