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