rsScriptC.cpp revision ccc010bb7c0f89e162bf60033968a20be90a903a
140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski/*
240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * Copyright (C) 2009 The Android Open Source Project
340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski *
440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * you may not use this file except in compliance with the License.
640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * You may obtain a copy of the License at
740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski *
840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski *
1040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * Unless required by applicable law or agreed to in writing, software
1140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
1240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * See the License for the specific language governing permissions and
1440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * limitations under the License.
1540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski */
1640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
1740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include "rsContext.h"
1840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include "rsScriptC.h"
19dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski#include "rsMatrix.h"
20dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski#include "../../../external/llvm/libbcc/include/bcc/bcc.h"
21dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski#include "utils/Timers.h"
2240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
23dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski#include <GLES/gl.h>
2440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <GLES/glext.h>
2540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
26dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinskiusing namespace android;
2740e8eefbedcafc51948945647d746daaee092f16Adam Lesinskiusing namespace android::renderscript;
2840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
2940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#define GET_TLS()  Context::ScriptTLSStruct * tls = \
3040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
3140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    Context * rsc = tls->mContext; \
32dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    ScriptC * sc = (ScriptC *) tls->mScript
33dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski
34dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski
3540e8eefbedcafc51948945647d746daaee092f16Adam LesinskiScriptC::ScriptC(Context *rsc) : Script(rsc)
36dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski{
37dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    mAllocFile = __FILE__;
38dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    mAllocLine = __LINE__;
39dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    mBccScript = NULL;
40dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    memset(&mProgram, 0, sizeof(mProgram));
41dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski}
42dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski
4340e8eefbedcafc51948945647d746daaee092f16Adam LesinskiScriptC::~ScriptC()
44dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski{
45dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    if (mBccScript) {
46dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        bccDeleteScript(mBccScript);
4740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
4840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    free(mEnviroment.mScriptText);
49dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    mEnviroment.mScriptText = NULL;
50c3344e8a6d7402326204d1232a4c5ffa382f70a9Adam Lesinski}
51c3344e8a6d7402326204d1232a4c5ffa382f70a9Adam Lesinski
52c3344e8a6d7402326204d1232a4c5ffa382f70a9Adam Lesinskivoid ScriptC::setupScript()
53c3344e8a6d7402326204d1232a4c5ffa382f70a9Adam Lesinski{
5440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
5540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        if (!mSlots[ct].get())
56dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski            continue;
57dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        void *ptr = mSlots[ct]->getPtr();
58dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        void **dest = ((void ***)mEnviroment.mFieldAddress)[ct];
59dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        //LOGE("setupScript %i %p = %p    %p %i", ct, dest, ptr, mSlots[ct]->getType(), mSlots[ct]->getType()->getDimX());
60dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski
61dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        //const uint32_t *p32 = (const uint32_t *)ptr;
62dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        //for (uint32_t ct2=0; ct2 < mSlots[ct]->getType()->getDimX(); ct2++) {
63dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski            //LOGE("  %i = 0x%08x ", ct2, p32[ct2]);
64dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        //}
65dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski
66dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        if (dest) {
67dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski            *dest = ptr;
68dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        } else {
69dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski            LOGE("ScriptC::setupScript, NULL var binding address.");
70dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        }
71dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    }
72dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski}
73dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski
74dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski
75dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinskiuint32_t ScriptC::run(Context *rsc, uint32_t launchIndex)
76dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski{
77c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski    if (mProgram.mRoot == NULL) {
78c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski        rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
79dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        return 0;
80dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    }
81dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski
82dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    Context::ScriptTLSStruct * tls =
83dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey);
84dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    rsAssert(tls);
85dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski
86dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    if (mEnviroment.mFragmentStore.get()) {
87dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        rsc->setFragmentStore(mEnviroment.mFragmentStore.get());
88dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    }
89dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    if (mEnviroment.mFragment.get()) {
90dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        rsc->setFragment(mEnviroment.mFragment.get());
91dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    }
92dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    if (mEnviroment.mVertex.get()) {
93dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        rsc->setVertex(mEnviroment.mVertex.get());
94dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    }
95dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    if (mEnviroment.mRaster.get()) {
96dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        rsc->setRaster(mEnviroment.mRaster.get());
97dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    }
98dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski
99dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    if (launchIndex == 0) {
100dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski        mEnviroment.mStartTimeMillis
101dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski                = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
102dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    }
103dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    setupScript();
104dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski
105dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    uint32_t ret = 0;
106dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    tls->mScript = this;
107dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski    //LOGE("ScriptC::run %p", mProgram.mRoot);
108c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski    ret = mProgram.mRoot();
109c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski    tls->mScript = NULL;
11040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    //LOGE("ScriptC::run ret %i", ret);
111    return ret;
112}
113
114ScriptCState::ScriptCState()
115{
116    mScript = NULL;
117    clear();
118}
119
120ScriptCState::~ScriptCState()
121{
122    delete mScript;
123    mScript = NULL;
124}
125
126void ScriptCState::clear()
127{
128    for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
129        mConstantBufferTypes[ct].clear();
130        mSlotWritable[ct] = false;
131    }
132
133    delete mScript;
134    mScript = new ScriptC(NULL);
135}
136
137static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name)
138{
139    const ScriptCState::SymbolTable_t *sym = ScriptCState::lookupSymbol(name);
140    if (sym) {
141        return sym->mPtr;
142    }
143    LOGE("ScriptC sym lookup failed for %s", name);
144    return NULL;
145}
146
147void ScriptCState::runCompiler(Context *rsc, ScriptC *s)
148{
149    LOGE("ScriptCState::runCompiler ");
150
151    s->mBccScript = bccCreateScript();
152    bccScriptBitcode(s->mBccScript, s->mEnviroment.mScriptText, s->mEnviroment.mScriptTextLength);
153    bccRegisterSymbolCallback(s->mBccScript, symbolLookup, NULL);
154    LOGE("ScriptCState::runCompiler 3");
155    bccCompileScript(s->mBccScript);
156    LOGE("ScriptCState::runCompiler 4");
157    bccGetScriptLabel(s->mBccScript, "root", (BCCvoid**) &s->mProgram.mRoot);
158    bccGetScriptLabel(s->mBccScript, "init", (BCCvoid**) &s->mProgram.mInit);
159    LOGE("root %p,  init %p", s->mProgram.mRoot, s->mProgram.mInit);
160
161    if (s->mProgram.mInit) {
162        s->mProgram.mInit();
163    }
164
165    s->mEnviroment.mInvokeFunctions = (Script::InvokeFunc_t *)calloc(100, sizeof(void *));
166    BCCchar **labels = new char*[100];
167    bccGetFunctions(s->mBccScript, (BCCsizei *)&s->mEnviroment.mInvokeFunctionCount,
168                    100, (BCCchar **)labels);
169    //LOGE("func count %i", s->mEnviroment.mInvokeFunctionCount);
170    for (uint32_t i=0; i < s->mEnviroment.mInvokeFunctionCount; i++) {
171        BCCsizei length;
172        bccGetFunctionBinary(s->mBccScript, labels[i], (BCCvoid **)&(s->mEnviroment.mInvokeFunctions[i]), &length);
173        //LOGE("func %i %p", i, s->mEnviroment.mInvokeFunctions[i]);
174    }
175
176    s->mEnviroment.mFieldAddress = (void **)calloc(100, sizeof(void *));
177    bccGetExportVars(s->mBccScript, (BCCsizei *)&s->mEnviroment.mFieldCount,
178                     100, s->mEnviroment.mFieldAddress);
179    //LOGE("var count %i", s->mEnviroment.mFieldCount);
180    for (uint32_t i=0; i < s->mEnviroment.mFieldCount; i++) {
181        //LOGE("var %i %p", i, s->mEnviroment.mFieldAddress[i]);
182    }
183
184    s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
185    s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
186    s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
187    s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
188
189    if (s->mProgram.mRoot) {
190        const static int pragmaMax = 16;
191        BCCsizei pragmaCount;
192        BCCchar * str[pragmaMax];
193        bccGetPragmas(s->mBccScript, &pragmaCount, pragmaMax, &str[0]);
194
195        for (int ct=0; ct < pragmaCount; ct+=2) {
196            if (!strcmp(str[ct], "version")) {
197                continue;
198            }
199
200            if (!strcmp(str[ct], "stateVertex")) {
201                if (!strcmp(str[ct+1], "default")) {
202                    continue;
203                }
204                if (!strcmp(str[ct+1], "parent")) {
205                    s->mEnviroment.mVertex.clear();
206                    continue;
207                }
208                LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
209            }
210
211            if (!strcmp(str[ct], "stateRaster")) {
212                if (!strcmp(str[ct+1], "default")) {
213                    continue;
214                }
215                if (!strcmp(str[ct+1], "parent")) {
216                    s->mEnviroment.mRaster.clear();
217                    continue;
218                }
219                LOGE("Unreconized value %s passed to stateRaster", str[ct+1]);
220            }
221
222            if (!strcmp(str[ct], "stateFragment")) {
223                if (!strcmp(str[ct+1], "default")) {
224                    continue;
225                }
226                if (!strcmp(str[ct+1], "parent")) {
227                    s->mEnviroment.mFragment.clear();
228                    continue;
229                }
230                LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
231            }
232
233            if (!strcmp(str[ct], "stateStore")) {
234                if (!strcmp(str[ct+1], "default")) {
235                    continue;
236                }
237                if (!strcmp(str[ct+1], "parent")) {
238                    s->mEnviroment.mFragmentStore.clear();
239                    continue;
240                }
241                LOGE("Unreconized value %s passed to stateStore", str[ct+1]);
242            }
243
244        }
245
246
247    } else {
248        // Deal with an error.
249    }
250}
251
252
253
254namespace android {
255namespace renderscript {
256
257void rsi_ScriptCBegin(Context * rsc)
258{
259    ScriptCState *ss = &rsc->mScriptC;
260    ss->clear();
261}
262
263void rsi_ScriptCSetScript(Context * rsc, void *vp)
264{
265    rsAssert(0);
266    //ScriptCState *ss = &rsc->mScriptC;
267    //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
268}
269
270void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
271{
272    ScriptCState *ss = &rsc->mScriptC;
273
274    char *t = (char *)malloc(len + 1);
275    memcpy(t, text, len);
276    t[len] = 0;
277    ss->mScript->mEnviroment.mScriptText = t;
278    ss->mScript->mEnviroment.mScriptTextLength = len;
279}
280
281
282RsScript rsi_ScriptCCreate(Context * rsc)
283{
284    ScriptCState *ss = &rsc->mScriptC;
285
286    ScriptC *s = ss->mScript;
287    ss->mScript = NULL;
288
289    ss->runCompiler(rsc, s);
290    s->incUserRef();
291    s->setContext(rsc);
292    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
293        s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
294        s->mSlotWritable[ct] = ss->mSlotWritable[ct];
295    }
296
297    ss->clear();
298    return s;
299}
300
301void rsi_ScriptCSetDefineF(Context *rsc, const char* name, float value)
302{
303    LOGE("Error rsi_ScriptCSetDefineF");
304}
305
306void rsi_ScriptCSetDefineI32(Context *rsc, const char* name, int32_t value)
307{
308    LOGE("Error rsi_ScriptCSetDefineI");
309}
310
311}
312}
313
314
315