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