rsScriptC.cpp revision 639e6e9349adec4113312a29b295af432f14faaf
1/*
2 * Copyright (C) 2009 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#include "rsContext.h"
18#include "rsScriptC.h"
19#include "rsMatrix.h"
20#include "../../../external/llvm/libbcc/include/bcc/bcc.h"
21#include "utils/Timers.h"
22
23#include <GLES/gl.h>
24#include <GLES/glext.h>
25
26using namespace android;
27using namespace android::renderscript;
28
29#define GET_TLS()  Context::ScriptTLSStruct * tls = \
30    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
31    Context * rsc = tls->mContext; \
32    ScriptC * sc = (ScriptC *) tls->mScript
33
34
35ScriptC::ScriptC(Context *rsc) : Script(rsc)
36{
37    mAllocFile = __FILE__;
38    mAllocLine = __LINE__;
39    mBccScript = NULL;
40    memset(&mProgram, 0, sizeof(mProgram));
41}
42
43ScriptC::~ScriptC()
44{
45    if (mBccScript) {
46        bccDeleteScript(mBccScript);
47    }
48    free(mEnviroment.mScriptText);
49    mEnviroment.mScriptText = NULL;
50}
51
52void ScriptC::setupScript()
53{
54    for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
55        if (!mSlots[ct].get())
56            continue;
57        void *ptr = mSlots[ct]->getPtr();
58        void **dest = ((void ***)mEnviroment.mFieldAddress)[ct];
59        //LOGE("setupScript %i %p = %p    %p %i", ct, dest, ptr, mSlots[ct]->getType(), mSlots[ct]->getType()->getDimX());
60
61        //const uint32_t *p32 = (const uint32_t *)ptr;
62        //for (uint32_t ct2=0; ct2 < mSlots[ct]->getType()->getDimX(); ct2++) {
63            //LOGE("  %i = 0x%08x ", ct2, p32[ct2]);
64        //}
65
66        if (dest) {
67            *dest = ptr;
68        } else {
69            LOGE("ScriptC::setupScript, NULL var binding address.");
70        }
71    }
72}
73
74
75uint32_t ScriptC::run(Context *rsc, uint32_t launchIndex)
76{
77    if (mProgram.mRoot == NULL) {
78        rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
79        return 0;
80    }
81
82    Context::ScriptTLSStruct * tls =
83    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey);
84    rsAssert(tls);
85
86    if (mEnviroment.mFragmentStore.get()) {
87        rsc->setFragmentStore(mEnviroment.mFragmentStore.get());
88    }
89    if (mEnviroment.mFragment.get()) {
90        rsc->setFragment(mEnviroment.mFragment.get());
91    }
92    if (mEnviroment.mVertex.get()) {
93        rsc->setVertex(mEnviroment.mVertex.get());
94    }
95    if (mEnviroment.mRaster.get()) {
96        rsc->setRaster(mEnviroment.mRaster.get());
97    }
98
99    if (launchIndex == 0) {
100        mEnviroment.mStartTimeMillis
101                = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
102    }
103    setupScript();
104
105    uint32_t ret = 0;
106    tls->mScript = this;
107    //LOGE("ScriptC::run %p", mProgram.mRoot);
108    ret = mProgram.mRoot();
109    tls->mScript = NULL;
110    //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
301}
302}
303
304
305