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