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