10f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines/*
20f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * Copyright (C) 2011-2012 The Android Open Source Project
30f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines *
40f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
50f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * you may not use this file except in compliance with the License.
60f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * You may obtain a copy of the License at
70f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines *
80f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines *      http://www.apache.org/licenses/LICENSE-2.0
90f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines *
100f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * Unless required by applicable law or agreed to in writing, software
110f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
120f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * See the License for the specific language governing permissions and
140f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines * limitations under the License.
150f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines */
160f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
170f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "rsdCore.h"
180f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "rsdBcc.h"
190f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "rsdRuntime.h"
200f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "rsdAllocation.h"
21ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams#include "rsdIntrinsics.h"
22b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines
230f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "rsContext.h"
240f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "rsElement.h"
250f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "rsScriptC.h"
260f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
270f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "utils/Vector.h"
280f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "utils/Timers.h"
290f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines#include "utils/StopWatch.h"
30b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines#include "utils/String8.h"
31b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines
32b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines#include <dlfcn.h>
3342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#include <stdio.h>
3442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#include <string.h>
350f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
360f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesusing namespace android;
370f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesusing namespace android::renderscript;
380f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
3942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#define MAXLINE 500
4042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#define MAKE_STR_HELPER(S) #S
4142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#define MAKE_STR(S) MAKE_STR_HELPER(S)
4242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#define EXPORT_VAR_STR "exportVarCount: "
4342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#define EXPORT_VAR_STR_LEN strlen(EXPORT_VAR_STR)
4442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#define EXPORT_FUNC_STR "exportFuncCount: "
4542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#define EXPORT_FUNC_STR_LEN strlen(EXPORT_FUNC_STR)
4642cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#define EXPORT_FOREACH_STR "exportForEachCount: "
4742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#define EXPORT_FOREACH_STR_LEN strlen(EXPORT_FOREACH_STR)
4842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#define OBJECT_SLOT_STR "objectSlotCount: "
4942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines#define OBJECT_SLOT_STR_LEN strlen(OBJECT_SLOT_STR)
5042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines
510f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
520f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
530f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesstatic Script * setTLS(Script *sc) {
540f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    ScriptTLSStruct * tls = (ScriptTLSStruct *)pthread_getspecific(rsdgThreadTLSKey);
550f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    rsAssert(tls);
560f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    Script *old = tls->mScript;
570f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    tls->mScript = sc;
580f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    return old;
590f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
600f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
610f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
620f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesbool rsdScriptInit(const Context *rsc,
630f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                     ScriptC *script,
640f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                     char const *resName,
650f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                     char const *cacheDir,
660f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                     uint8_t const *bitcode,
670f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                     size_t bitcodeSize,
680f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                     uint32_t flags) {
690f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
700f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("rsdScriptInit %p %p", rsc, script);
710f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
720f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    pthread_mutex_lock(&rsdgInitMutex);
730f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
74b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    String8 scriptSOName(cacheDir);
75b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    scriptSOName = scriptSOName.getPathDir();
76b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    scriptSOName.appendPath("lib");
77b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    scriptSOName.append("/lib");
78b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    scriptSOName.append(resName);
79b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    scriptSOName.append(".so");
80b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines
8142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    String8 scriptInfoName(cacheDir);
8242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    scriptInfoName = scriptInfoName.getPathDir();
8342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    scriptInfoName.appendPath("lib/");
8442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    scriptInfoName.append(resName);
8542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    scriptInfoName.append(".bcinfo");
86b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines
8742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    void *scriptSO = NULL;
8842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    FILE *fp = NULL;
890f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript));
900f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (drv == NULL) {
910f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        goto error;
920f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
930f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    script->mHal.drv = drv;
940f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
9542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    ALOGE("Opening up info object: %s", scriptInfoName.string());
9642cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines
9742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    fp = fopen(scriptInfoName.string(), "r");
9842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    if (!fp) {
9942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        ALOGE("Unable to open info file: %s", scriptInfoName.string());
10042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        goto error;
10142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    }
10242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines
10342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    ALOGE("Opening up shared object: %s", scriptSOName.string());
10442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    scriptSO = dlopen(scriptSOName.string(), RTLD_NOW | RTLD_LOCAL);
10542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    if (scriptSO == NULL) {
10642cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        ALOGE("Unable to open shared library (%s): %s",
10742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines              scriptSOName.string(), dlerror());
10842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        goto error;
10942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    }
11042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    drv->mScriptSO = scriptSO;
1110f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
112b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    if (scriptSO) {
11342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        char line[MAXLINE];
11442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        drv->mScriptSO = scriptSO;
115b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        drv->mRoot = (RootFunc_t) dlsym(scriptSO, "root");
116b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        if (drv->mRoot) {
117b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            ALOGE("Found root(): %p", drv->mRoot);
118b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        }
119b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        drv->mRootExpand = (RootFunc_t) dlsym(scriptSO, "root.expand");
120b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        if (drv->mRootExpand) {
121b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            ALOGE("Found root.expand(): %p", drv->mRootExpand);
122b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        }
123b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        drv->mInit = (InvokeFunc_t) dlsym(scriptSO, "init");
124b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        if (drv->mInit) {
125b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            ALOGE("Found init(): %p", drv->mInit);
126b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        }
127b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        drv->mFreeChildren = (InvokeFunc_t) dlsym(scriptSO, ".rs.dtor");
128b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        if (drv->mFreeChildren) {
129b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            ALOGE("Found .rs.dtor(): %p", drv->mFreeChildren);
130b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        }
1310f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
13242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        size_t varCount = 0;
13342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        if (fgets(line, MAXLINE, fp) == NULL) {
13442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            goto error;
13542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        }
13642cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
13742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            ALOGE("Invalid export var count!: %s", line);
13842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            goto error;
139b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        }
1400f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
141b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        script->mHal.info.exportedVariableCount = varCount;
142b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        ALOGE("varCount: %zu", varCount);
143b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        if (varCount > 0) {
144b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            // Start by creating/zeroing this member, since we don't want to
145b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            // accidentally clean up invalid pointers later (if we error out).
146b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            drv->mFieldIsObject = new bool[varCount];
147b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            if (drv->mFieldIsObject == NULL) {
148b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                goto error;
149b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            }
150b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            memset(drv->mFieldIsObject, 0,
151b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                   varCount * sizeof(*drv->mFieldIsObject));
152b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            drv->mFieldAddress = new void*[varCount];
153b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            if (drv->mFieldAddress == NULL) {
154b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                goto error;
155b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            }
156b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            for (size_t i = 0; i < varCount; ++i) {
15742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                if (fgets(line, MAXLINE, fp) == NULL) {
15842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    goto error;
15942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                }
16042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                char *c = strrchr(line, '\n');
16142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                if (c) {
16242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    *c = '\0';
16342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                }
16442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                drv->mFieldAddress[i] = dlsym(scriptSO, line);
165b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                if (drv->mFieldAddress[i] == NULL) {
166b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                    ALOGE("Failed to find variable address for %s: %s",
16742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                          line, dlerror());
16842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    // Not a critical error if we don't find a global variable.
169b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                }
170b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                else {
17142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    ALOGE("Found variable %s at %p", line,
172b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                          drv->mFieldAddress[i]);
173b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                }
174b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            }
175b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        }
1760f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
17742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        size_t funcCount = 0;
17842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        if (fgets(line, MAXLINE, fp) == NULL) {
17942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            goto error;
18042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        }
18142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
18242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            ALOGE("Invalid export func count!: %s", line);
18342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            goto error;
18442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        }
18542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines
18642cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        script->mHal.info.exportedFunctionCount = funcCount;
18742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        ALOGE("funcCount: %zu", funcCount);
18842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines
18942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        if (funcCount > 0) {
19042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            drv->mInvokeFunctions = new InvokeFunc_t[funcCount];
19142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            if (drv->mInvokeFunctions == NULL) {
19242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                goto error;
19342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            }
19442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            for (size_t i = 0; i < funcCount; ++i) {
19542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                if (fgets(line, MAXLINE, fp) == NULL) {
19642cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    goto error;
19742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                }
19842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                char *c = strrchr(line, '\n');
19942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                if (c) {
20042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    *c = '\0';
20142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                }
20242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines
20342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                drv->mInvokeFunctions[i] =
20442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                        (InvokeFunc_t) dlsym(scriptSO, line);
20542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                if (drv->mInvokeFunctions[i] == NULL) {
20642cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    ALOGE("Failed to get function address for %s(): %s",
20742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                          line, dlerror());
20842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    goto error;
20942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                }
21042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                else {
21142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    ALOGE("Found InvokeFunc_t %s at %p", line,
21242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                          drv->mInvokeFunctions[i]);
213b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                }
214b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            }
215b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        }
2160f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
21742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        size_t forEachCount = 0;
21842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        if (fgets(line, MAXLINE, fp) == NULL) {
21942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            goto error;
22042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        }
22142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
22242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            ALOGE("Invalid export forEach count!: %s", line);
22342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            goto error;
22442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        }
22542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines
226b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        if (forEachCount > 0) {
2270f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
228b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            drv->mForEachSignatures = new uint32_t[forEachCount];
229b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            if (drv->mForEachSignatures == NULL) {
230b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                goto error;
231b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            }
232b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            drv->mForEachFunctions = new ForEachFunc_t[forEachCount];
233b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            if (drv->mForEachFunctions == NULL) {
234b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                goto error;
235b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            }
236b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            for (size_t i = 0; i < forEachCount; ++i) {
23742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                unsigned int tmpSig = 0;
23842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                char tmpName[MAXLINE];
23942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines
24042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                if (fgets(line, MAXLINE, fp) == NULL) {
24142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    goto error;
24242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                }
24342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
24442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                           &tmpSig, tmpName) != 2) {
24542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    ALOGE("Invalid export forEach!: %s", line);
24642cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    goto error;
24742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                }
24842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines
24942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                drv->mForEachSignatures[i] = tmpSig;
250b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                drv->mForEachFunctions[i] =
25142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                        (ForEachFunc_t) dlsym(scriptSO, tmpName);
252b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                if (drv->mForEachFunctions[i] == NULL) {
253b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                    ALOGE("Failed to find forEach function address for %s: %s",
25442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                          tmpName, dlerror());
255b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                    goto error;
256b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                }
257b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                else {
258b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                    // TODO - Maybe add ForEachExpandPass to .so creation and
259b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                    // then lookup the ".expand" version of these kernels
260b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                    // instead.
26142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    ALOGE("Found forEach %s at %p", tmpName,
262b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                          drv->mForEachFunctions[i]);
263b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                }
264b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            }
265b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        }
2660f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
26742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        size_t objectSlotCount = 0;
26842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        if (fgets(line, MAXLINE, fp) == NULL) {
26942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            goto error;
27042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        }
27142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
27242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            ALOGE("Invalid object slot count!: %s", line);
27342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            goto error;
27442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        }
27542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines
27642cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        if (objectSlotCount > 0) {
27742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            rsAssert(varCount > 0);
27842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            for (size_t i = 0; i < objectSlotCount; ++i) {
27942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                uint32_t varNum = 0;
28042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                if (fgets(line, MAXLINE, fp) == NULL) {
28142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    goto error;
28242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                }
28342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                if (sscanf(line, "%u", &varNum) != 1) {
28442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    ALOGE("Invalid object slot!: %s", line);
28542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    goto error;
28642cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                }
28742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines
28842cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                if (varNum < varCount) {
28942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                    drv->mFieldIsObject[varNum] = true;
29042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines                }
29142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            }
29242cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        }
29342cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines
294b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        script->mHal.info.exportedPragmaCount = 0;
2950f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
296b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        if (drv->mRootExpand) {
297b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            script->mHal.info.root = drv->mRootExpand;
298b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        } else {
299b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            script->mHal.info.root = drv->mRoot;
300b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        }
301b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines
302b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        if (varCount > 0) {
303b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            drv->mBoundAllocs = new Allocation *[varCount];
304b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            memset(drv->mBoundAllocs, 0, varCount * sizeof(*drv->mBoundAllocs));
305b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        }
306b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines
307b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        script->mHal.info.isThreadable = true;
3080f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
309b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        if (scriptSO == (void*)1) {
310b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            rsdLookupRuntimeStub(script, "acos");
311b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        }
3120f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
3130f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
31442cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    fclose(fp);
3150f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    pthread_mutex_unlock(&rsdgInitMutex);
3160f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    return true;
3170f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
3180f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hineserror:
3190f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
32042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    fclose(fp);
3210f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    pthread_mutex_unlock(&rsdgInitMutex);
3220f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (drv) {
323b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        delete[] drv->mInvokeFunctions;
324b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        delete[] drv->mForEachFunctions;
325b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        delete[] drv->mFieldAddress;
326b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        delete[] drv->mFieldIsObject;
327b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        delete[] drv->mForEachSignatures;
3280f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        delete[] drv->mBoundAllocs;
32942cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        if (drv->mScriptSO) {
33042cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines            dlclose(drv->mScriptSO);
33142cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        }
3320f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        free(drv);
3330f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
3340f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    script->mHal.drv = NULL;
3350f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    return false;
3360f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
3370f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
3380f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
339ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsbool rsdInitIntrinsic(const Context *rsc, Script *s, RsScriptIntrinsicID iid, Element *e) {
340ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    pthread_mutex_lock(&rsdgInitMutex);
341ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
342ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript));
343ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    if (drv == NULL) {
344ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        goto error;
345ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    }
346ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    s->mHal.drv = drv;
347ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    drv->mIntrinsicID = iid;
348ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    drv->mIntrinsicData = rsdIntrinsic_Init(rsc, s, iid, &drv->mIntrinsicFuncs);
349ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    s->mHal.info.isThreadable = true;
350ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
351ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    pthread_mutex_unlock(&rsdgInitMutex);
352ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    return true;
353ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
354ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samserror:
355ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    pthread_mutex_unlock(&rsdgInitMutex);
356ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    return false;
357ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams}
358ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
3590f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinestypedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
3600f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
3610f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesstatic void wc_xy(void *usr, uint32_t idx) {
3620f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
3630f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    RsForEachStubParamStruct p;
364ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    memcpy(&p, &mtls->fep, sizeof(p));
3650f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv;
3660f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    uint32_t sig = mtls->sig;
3670f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
368b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    rs_t bare_fn = (rs_t) mtls->kernel;
3690f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    while (1) {
3700f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
3710f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        uint32_t yStart = mtls->yStart + slice * mtls->mSliceSize;
3720f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        uint32_t yEnd = yStart + mtls->mSliceSize;
3730f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        yEnd = rsMin(yEnd, mtls->yEnd);
3740f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        if (yEnd <= yStart) {
3750f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            return;
3760f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        }
3770f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
3780f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        //ALOGE("usr idx %i, x %i,%i  y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
3790f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        //ALOGE("usr ptr in %p,  out %p", mtls->ptrIn, mtls->ptrOut);
3800f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        for (p.y = yStart; p.y < yEnd; p.y++) {
381ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            p.out = mtls->fep.ptrOut + (mtls->fep.yStrideOut * p.y);
382ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            p.in = mtls->fep.ptrIn + (mtls->fep.yStrideIn * p.y);
383b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            for (uint32_t x = mtls->xStart; x < mtls->xEnd; ++x) {
384b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                bare_fn(p.in, p.out, p.usr, x, p.y, 0, 0);
385ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                p.in = (char *)(p.in) + mtls->fep.eStrideIn;
386ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                p.out = (char *)(p.out) + mtls->fep.eStrideOut;
387b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            }
3880f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        }
3890f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
3900f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
3910f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
3920f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesstatic void wc_x(void *usr, uint32_t idx) {
3930f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
3940f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    RsForEachStubParamStruct p;
395ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    memcpy(&p, &mtls->fep, sizeof(p));
3960f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv;
3970f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    uint32_t sig = mtls->sig;
3980f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
399b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    rs_t bare_fn = (rs_t) mtls->kernel;
4000f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    while (1) {
4010f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
4020f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize;
4030f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        uint32_t xEnd = xStart + mtls->mSliceSize;
4040f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        xEnd = rsMin(xEnd, mtls->xEnd);
4050f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        if (xEnd <= xStart) {
4060f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            return;
4070f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        }
4080f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
4090f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        //ALOGE("usr slice %i idx %i, x %i,%i", slice, idx, xStart, xEnd);
4100f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        //ALOGE("usr ptr in %p,  out %p", mtls->ptrIn, mtls->ptrOut);
4110f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
412ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        p.out = mtls->fep.ptrOut + (mtls->fep.eStrideOut * xStart);
413ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        p.in = mtls->fep.ptrIn + (mtls->fep.eStrideIn * xStart);
414b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        for (uint32_t x = mtls->xStart; x < mtls->xEnd; ++x) {
415b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            bare_fn(p.in, p.out, p.usr, x, 0, 0, 0);
416ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            p.in = (char *)(p.in) + mtls->fep.eStrideIn;
417ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            p.out = (char *)(p.out) + mtls->fep.eStrideOut;
418b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        }
4190f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
4200f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
4210f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
422ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsvoid rsdScriptInvokeForEachMtlsSetup(const Context *rsc,
423ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                                     const Allocation * ain,
424ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                                     Allocation * aout,
425ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                                     const void * usr,
426ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                                     uint32_t usrLen,
427ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                                     const RsScriptCall *sc,
428ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                                     MTLaunchStruct *mtls) {
4290f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
430ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    memset(mtls, 0, sizeof(MTLaunchStruct));
4310f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
4320f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (ain) {
433ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->fep.dimX = ain->getType()->getDimX();
434ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->fep.dimY = ain->getType()->getDimY();
435ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->fep.dimZ = ain->getType()->getDimZ();
436ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        //mtls->dimArray = ain->getType()->getDimArray();
4370f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    } else if (aout) {
438ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->fep.dimX = aout->getType()->getDimX();
439ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->fep.dimY = aout->getType()->getDimY();
440ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->fep.dimZ = aout->getType()->getDimZ();
441ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        //mtls->dimArray = aout->getType()->getDimArray();
4420f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    } else {
4430f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        rsc->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
4440f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        return;
4450f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
4460f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
4470f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (!sc || (sc->xEnd == 0)) {
448ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->xEnd = mtls->fep.dimX;
4490f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    } else {
450ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        rsAssert(sc->xStart < mtls->fep.dimX);
451ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        rsAssert(sc->xEnd <= mtls->fep.dimX);
4520f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        rsAssert(sc->xStart < sc->xEnd);
453ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
454ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
455ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        if (mtls->xStart >= mtls->xEnd) return;
4560f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
4570f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
4580f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (!sc || (sc->yEnd == 0)) {
459ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->yEnd = mtls->fep.dimY;
4600f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    } else {
461ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        rsAssert(sc->yStart < mtls->fep.dimY);
462ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        rsAssert(sc->yEnd <= mtls->fep.dimY);
4630f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        rsAssert(sc->yStart < sc->yEnd);
464ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
465ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
466ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        if (mtls->yStart >= mtls->yEnd) return;
4670f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
4680f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
469ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
470ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
471ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
472ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
4730f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
4740f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    rsAssert(!ain || (ain->getType()->getDimZ() == 0));
4750f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
4760f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    Context *mrsc = (Context *)rsc;
477ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->rsc = mrsc;
478ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->ain = ain;
479ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->aout = aout;
480ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->fep.usr = usr;
481ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->fep.usrLen = usrLen;
482ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->mSliceSize = 10;
483ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->mSliceNum = 0;
4840f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
485ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->fep.ptrIn = NULL;
486ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->fep.eStrideIn = 0;
4870f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
4880f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (ain) {
4890f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        DrvAllocation *aindrv = (DrvAllocation *)ain->mHal.drv;
490ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->fep.ptrIn = (const uint8_t *)aindrv->lod[0].mallocPtr;
491ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes();
492ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->fep.yStrideIn = aindrv->lod[0].stride;
4930f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
4940f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
495ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->fep.ptrOut = NULL;
496ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls->fep.eStrideOut = 0;
4970f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (aout) {
4980f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        DrvAllocation *aoutdrv = (DrvAllocation *)aout->mHal.drv;
499ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->fep.ptrOut = (uint8_t *)aoutdrv->lod[0].mallocPtr;
500ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes();
501ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls->fep.yStrideOut = aoutdrv->lod[0].stride;
5020f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
503ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams}
504ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
505ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsvoid rsdScriptLaunchThreads(const Context *rsc,
506ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            Script *s,
507ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            uint32_t slot,
508ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            const Allocation * ain,
509ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            Allocation * aout,
510ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            const void * usr,
511ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            uint32_t usrLen,
512ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            const RsScriptCall *sc,
513ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            MTLaunchStruct *mtls) {
514ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
515ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    Script * oldTLS = setTLS(s);
516ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    Context *mrsc = (Context *)rsc;
517ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv;
5180f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
5190f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if ((dc->mWorkers.mCount > 1) && s->mHal.info.isThreadable && !dc->mInForEach) {
5200f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        dc->mInForEach = true;
521ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        if (mtls->fep.dimY > 1) {
522ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mtls->mSliceSize = mtls->fep.dimY / (dc->mWorkers.mCount * 4);
523ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if(mtls->mSliceSize < 1) {
524ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                mtls->mSliceSize = 1;
5250f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            }
5260f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
527ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            rsdLaunchThreads(mrsc, wc_xy, mtls);
5280f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        } else {
529ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            mtls->mSliceSize = mtls->fep.dimX / (dc->mWorkers.mCount * 4);
530ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            if(mtls->mSliceSize < 1) {
531ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                mtls->mSliceSize = 1;
5320f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            }
5330f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
534ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            rsdLaunchThreads(mrsc, wc_x, mtls);
5350f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        }
5360f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        dc->mInForEach = false;
5370f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
5380f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        //ALOGE("launch 1");
5390f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    } else {
5400f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        RsForEachStubParamStruct p;
541ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        memcpy(&p, &mtls->fep, sizeof(p));
542ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        uint32_t sig = mtls->sig;
5430f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
5440f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        //ALOGE("launch 3");
545ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        outer_foreach_t fn = (outer_foreach_t) mtls->kernel;
546ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        for (p.ar[0] = mtls->arrayStart; p.ar[0] < mtls->arrayEnd; p.ar[0]++) {
547ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams            for (p.z = mtls->zStart; p.z < mtls->zEnd; p.z++) {
548ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                for (p.y = mtls->yStart; p.y < mtls->yEnd; p.y++) {
549ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    uint32_t offset = mtls->fep.dimY * mtls->fep.dimZ * p.ar[0] +
550ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                                      mtls->fep.dimY * p.z + p.y;
551ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    p.out = mtls->fep.ptrOut + (mtls->fep.yStrideOut * offset);
552ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    p.in = mtls->fep.ptrIn + (mtls->fep.yStrideIn * offset);
553ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                    fn(&p, mtls->xStart, mtls->xEnd, mtls->fep.eStrideIn, mtls->fep.eStrideOut);
5540f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                }
5550f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            }
5560f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        }
5570f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
5580f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
5590f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    setTLS(oldTLS);
5600f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
5610f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
562ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Samsvoid rsdScriptInvokeForEach(const Context *rsc,
563ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            Script *s,
564ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            uint32_t slot,
565ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            const Allocation * ain,
566ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            Allocation * aout,
567ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            const void * usr,
568ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            uint32_t usrLen,
569ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams                            const RsScriptCall *sc) {
570ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
571ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    RsdHal * dc = (RsdHal *)rsc->mHal.drv;
572ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
573ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    MTLaunchStruct mtls;
574ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    rsdScriptInvokeForEachMtlsSetup(rsc, ain, aout, usr, usrLen, sc, &mtls);
575ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls.script = s;
576ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    mtls.fep.slot = slot;
577ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
578ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    DrvScript *drv = (DrvScript *)s->mHal.drv;
579ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    if (drv->mIntrinsicID) {
580ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls.kernel = (void (*)())drv->mIntrinsicFuncs.root;
581ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls.fep.usr = drv->mIntrinsicData;
582ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    } else {
583ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams		mtls.kernel = drv->mForEachFunctions[slot];
584ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        rsAssert(mtls.kernel != NULL);
585ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        mtls.sig = drv->mForEachSignatures[slot];
586ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    }
587ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
588ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
589ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    rsdScriptLaunchThreads(rsc, s, slot, ain, aout, usr, usrLen, sc, &mtls);
590ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams}
591ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
5920f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
5930f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesint rsdScriptInvokeRoot(const Context *dc, Script *script) {
5940f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    DrvScript *drv = (DrvScript *)script->mHal.drv;
5950f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
5960f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    Script * oldTLS = setTLS(script);
5970f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    int ret = drv->mRoot();
5980f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    setTLS(oldTLS);
5990f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6000f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    return ret;
6010f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
6020f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6030f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid rsdScriptInvokeInit(const Context *dc, Script *script) {
6040f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    DrvScript *drv = (DrvScript *)script->mHal.drv;
6050f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6060f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (drv->mInit) {
6070f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        drv->mInit();
6080f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
6090f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
6100f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6110f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid rsdScriptInvokeFreeChildren(const Context *dc, Script *script) {
6120f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    DrvScript *drv = (DrvScript *)script->mHal.drv;
6130f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6140f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (drv->mFreeChildren) {
6150f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        drv->mFreeChildren();
6160f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
6170f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
6180f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6190f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid rsdScriptInvokeFunction(const Context *dc, Script *script,
6200f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                            uint32_t slot,
6210f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                            const void *params,
6220f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                            size_t paramLength) {
6230f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    DrvScript *drv = (DrvScript *)script->mHal.drv;
6240f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
6250f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6260f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    Script * oldTLS = setTLS(script);
6270f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    reinterpret_cast<void (*)(const void *, uint32_t)>(
628b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        drv->mInvokeFunctions[slot])(params, paramLength);
6290f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    setTLS(oldTLS);
6300f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
6310f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6320f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid rsdScriptSetGlobalVar(const Context *dc, const Script *script,
6330f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                           uint32_t slot, void *data, size_t dataLength) {
6340f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    DrvScript *drv = (DrvScript *)script->mHal.drv;
6350f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //rsAssert(!script->mFieldIsObject[slot]);
6360f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
6370f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
638ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    if (drv->mIntrinsicID) {
639ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        drv->mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
640ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        return;
641ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    }
642ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
643b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    int32_t *destPtr = reinterpret_cast<int32_t *>(drv->mFieldAddress[slot]);
6440f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (!destPtr) {
6450f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        //ALOGV("Calling setVar on slot = %i which is null", slot);
6460f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        return;
6470f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
6480f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6490f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    memcpy(destPtr, data, dataLength);
6500f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
6510f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6520f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid rsdScriptSetGlobalVarWithElemDims(
6530f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        const android::renderscript::Context *dc,
6540f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        const android::renderscript::Script *script,
6550f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        uint32_t slot, void *data, size_t dataLength,
6560f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        const android::renderscript::Element *elem,
6570f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        const size_t *dims, size_t dimLength) {
6580f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    DrvScript *drv = (DrvScript *)script->mHal.drv;
6590f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
660b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    int32_t *destPtr = reinterpret_cast<int32_t *>(drv->mFieldAddress[slot]);
6610f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (!destPtr) {
6620f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        //ALOGV("Calling setVar on slot = %i which is null", slot);
6630f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        return;
6640f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
6650f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6660f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    // We want to look at dimension in terms of integer components,
6670f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    // but dimLength is given in terms of bytes.
6680f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    dimLength /= sizeof(int);
6690f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6700f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    // Only a single dimension is currently supported.
6710f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    rsAssert(dimLength == 1);
6720f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (dimLength == 1) {
6730f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        // First do the increment loop.
6740f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        size_t stride = elem->getSizeBytes();
6750f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        char *cVal = reinterpret_cast<char *>(data);
6760f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        for (size_t i = 0; i < dims[0]; i++) {
6770f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            elem->incRefs(cVal);
6780f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            cVal += stride;
6790f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        }
6800f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6810f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        // Decrement loop comes after (to prevent race conditions).
6820f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        char *oldVal = reinterpret_cast<char *>(destPtr);
6830f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        for (size_t i = 0; i < dims[0]; i++) {
6840f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            elem->decRefs(oldVal);
6850f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            oldVal += stride;
6860f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        }
6870f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
6880f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6890f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    memcpy(destPtr, data, dataLength);
6900f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
6910f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6920f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid rsdScriptSetGlobalBind(const Context *dc, const Script *script, uint32_t slot, Allocation *data) {
6930f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    DrvScript *drv = (DrvScript *)script->mHal.drv;
6940f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
6950f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //rsAssert(!script->mFieldIsObject[slot]);
6960f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
6970f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
698ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    if (drv->mIntrinsicID) {
699ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        drv->mIntrinsicFuncs.bind(dc, script, drv->mIntrinsicData, slot, data);
700ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams        return;
701ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams    }
702ca29b8caf56fa4866752f9cea4ec02b2a271dceeJason Sams
703b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    int32_t *destPtr = reinterpret_cast<int32_t *>(drv->mFieldAddress[slot]);
7040f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (!destPtr) {
7050f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        //ALOGV("Calling setVar on slot = %i which is null", slot);
7060f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        return;
7070f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
7080f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
7090f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    void *ptr = NULL;
7100f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    drv->mBoundAllocs[slot] = data;
7110f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if(data) {
7120f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        DrvAllocation *allocDrv = (DrvAllocation *)data->mHal.drv;
7130f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        ptr = allocDrv->lod[0].mallocPtr;
7140f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
7150f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    memcpy(destPtr, &ptr, sizeof(void *));
7160f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
7170f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
7180f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid rsdScriptSetGlobalObj(const Context *dc, const Script *script, uint32_t slot, ObjectBase *data) {
7190f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    DrvScript *drv = (DrvScript *)script->mHal.drv;
7200f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //rsAssert(script->mFieldIsObject[slot]);
7210f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
7220f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
723b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    int32_t *destPtr = reinterpret_cast<int32_t *>(drv->mFieldAddress[slot]);
7240f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (!destPtr) {
7250f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        //ALOGV("Calling setVar on slot = %i which is null", slot);
7260f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        return;
7270f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
7280f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
7290f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    rsrSetObject(dc, script, (ObjectBase **)destPtr, data);
7300f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
7310f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
7320f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hinesvoid rsdScriptDestroy(const Context *dc, Script *script) {
7330f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    DrvScript *drv = (DrvScript *)script->mHal.drv;
7340f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
7350f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (drv == NULL) {
7360f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        return;
7370f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
7380f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
739b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    for (size_t i = 0; i < script->mHal.info.exportedVariableCount; ++i) {
740b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines        if (drv->mFieldIsObject[i]) {
741b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines            if (drv->mFieldAddress[i] != NULL) {
742b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                ObjectBase **obj_addr =
743b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                    reinterpret_cast<ObjectBase **>(drv->mFieldAddress[i]);
744b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines                rsrClearObject(dc, script, obj_addr);
7450f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            }
7460f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        }
7470f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
7480f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
749b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    delete[] drv->mInvokeFunctions;
750b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    delete[] drv->mForEachFunctions;
751b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    delete[] drv->mFieldAddress;
752b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    delete[] drv->mFieldIsObject;
753b54fe7cb6c2932c38021b899b0485cd2e25e623fStephen Hines    delete[] drv->mForEachSignatures;
7540f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    delete[] drv->mBoundAllocs;
75542cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    if (drv->mScriptSO) {
75642cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines        dlclose(drv->mScriptSO);
75742cd6edc8e3c21fce3ede8a42d715b32f6336aceStephen Hines    }
7580f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    free(drv);
7590f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    script->mHal.drv = NULL;
7600f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
7610f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
7620f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen HinesAllocation * rsdScriptGetAllocationForPointer(const android::renderscript::Context *dc,
7630f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                                              const android::renderscript::Script *sc,
7640f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines                                              const void *ptr) {
7650f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    DrvScript *drv = (DrvScript *)sc->mHal.drv;
7660f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    if (!ptr) {
7670f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        return NULL;
7680f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
7690f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
7700f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    for (uint32_t ct=0; ct < sc->mHal.info.exportedVariableCount; ct++) {
7710f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        Allocation *a = drv->mBoundAllocs[ct];
7720f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        if (!a) continue;
7730f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        DrvAllocation *adrv = (DrvAllocation *)a->mHal.drv;
7740f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        if (adrv->lod[0].mallocPtr == ptr) {
7750f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines            return a;
7760f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines        }
7770f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    }
7780f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    ALOGE("rsGetAllocation, failed to find %p", ptr);
7790f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines    return NULL;
7800f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines}
7810f6f72e19db852cc253fd2fc05459abdf8d5c3afStephen Hines
782