rsScriptC.cpp revision 22fa371bf64b8aae786acfe5d711af21afb13a93
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
74const Allocation *ScriptC::ptrToAllocation(const void *ptr) const
75{
76    if (!ptr) {
77        return NULL;
78    }
79    for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
80        if (!mSlots[ct].get())
81            continue;
82        if (mSlots[ct]->getPtr() == ptr) {
83            return mSlots[ct].get();
84        }
85    }
86    LOGE("ScriptC::ptrToAllocation, failed to find %p", ptr);
87    return NULL;
88}
89
90void ScriptC::setTLS()
91{
92    Context::ScriptTLSStruct * tls = (Context::ScriptTLSStruct *)
93                                  pthread_getspecific(Context::gThreadTLSKey);
94    rsAssert(tls);
95    tls->mScript = this;
96}
97
98void ScriptC::clearTLS()
99{
100    Context::ScriptTLSStruct * tls = (Context::ScriptTLSStruct *)
101                                  pthread_getspecific(Context::gThreadTLSKey);
102    rsAssert(tls);
103    tls->mScript = NULL;
104}
105
106uint32_t ScriptC::run(Context *rsc, uint32_t launchIndex)
107{
108    if (mProgram.mRoot == NULL) {
109        rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
110        return 0;
111    }
112
113    if (mEnviroment.mFragmentStore.get()) {
114        rsc->setFragmentStore(mEnviroment.mFragmentStore.get());
115    }
116    if (mEnviroment.mFragment.get()) {
117        rsc->setFragment(mEnviroment.mFragment.get());
118    }
119    if (mEnviroment.mVertex.get()) {
120        rsc->setVertex(mEnviroment.mVertex.get());
121    }
122    if (mEnviroment.mRaster.get()) {
123        rsc->setRaster(mEnviroment.mRaster.get());
124    }
125
126    if (launchIndex == 0) {
127        mEnviroment.mStartTimeMillis
128                = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
129    }
130    setupScript();
131
132    uint32_t ret = 0;
133    setTLS();
134    //LOGE("ScriptC::run %p", mProgram.mRoot);
135    ret = mProgram.mRoot();
136    clearTLS();
137    //LOGE("ScriptC::run ret %i", ret);
138    return ret;
139}
140
141void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len)
142{
143    //LOGE("rsi_ScriptInvoke %i", slot);
144    if ((slot >= mEnviroment.mInvokeFunctionCount) ||
145        (mEnviroment.mInvokeFunctions[slot] == NULL)) {
146        rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script");
147        return;
148    }
149    setupScript();
150    setTLS();
151
152    const uint32_t * dPtr = (const uint32_t *)data;
153    switch(len) {
154    case 0:
155        mEnviroment.mInvokeFunctions[slot]();
156        break;
157    case 4:
158        ((void (*)(uint32_t))
159         mEnviroment.mInvokeFunctions[slot])(dPtr[0]);
160        break;
161    case 8:
162        ((void (*)(uint32_t, uint32_t))
163         mEnviroment.mInvokeFunctions[slot])(dPtr[0], dPtr[1]);
164        break;
165    case 12:
166        ((void (*)(uint32_t, uint32_t, uint32_t))
167         mEnviroment.mInvokeFunctions[slot])(dPtr[0], dPtr[1], dPtr[2]);
168        break;
169    case 16:
170        ((void (*)(uint32_t, uint32_t, uint32_t, uint32_t))
171         mEnviroment.mInvokeFunctions[slot])(dPtr[0], dPtr[1], dPtr[2], dPtr[3]);
172        break;
173    case 20:
174        ((void (*)(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t))
175         mEnviroment.mInvokeFunctions[slot])(dPtr[0], dPtr[1], dPtr[2], dPtr[3], dPtr[4]);
176        break;
177    }
178    clearTLS();
179}
180
181ScriptCState::ScriptCState()
182{
183    mScript = NULL;
184    clear();
185}
186
187ScriptCState::~ScriptCState()
188{
189    delete mScript;
190    mScript = NULL;
191}
192
193void ScriptCState::clear()
194{
195    for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
196        mConstantBufferTypes[ct].clear();
197        mSlotWritable[ct] = false;
198    }
199
200    delete mScript;
201    mScript = new ScriptC(NULL);
202}
203
204static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name)
205{
206    const ScriptCState::SymbolTable_t *sym;
207    sym = ScriptCState::lookupSymbol(name);
208    if (sym) {
209        return sym->mPtr;
210    }
211    sym = ScriptCState::lookupSymbolCL(name);
212    if (sym) {
213        return sym->mPtr;
214    }
215    sym = ScriptCState::lookupSymbolGL(name);
216    if (sym) {
217        return sym->mPtr;
218    }
219    LOGE("ScriptC sym lookup failed for %s", name);
220    return NULL;
221}
222
223void ScriptCState::runCompiler(Context *rsc, ScriptC *s)
224{
225    LOGE("ScriptCState::runCompiler ");
226
227    s->mBccScript = bccCreateScript();
228    bccScriptBitcode(s->mBccScript, s->mEnviroment.mScriptText, s->mEnviroment.mScriptTextLength);
229    bccRegisterSymbolCallback(s->mBccScript, symbolLookup, NULL);
230    bccCompileScript(s->mBccScript);
231    bccGetScriptLabel(s->mBccScript, "root", (BCCvoid**) &s->mProgram.mRoot);
232    bccGetScriptLabel(s->mBccScript, "init", (BCCvoid**) &s->mProgram.mInit);
233    LOGE("root %p,  init %p", s->mProgram.mRoot, s->mProgram.mInit);
234
235    if (s->mProgram.mInit) {
236        s->mProgram.mInit();
237    }
238
239    s->mEnviroment.mInvokeFunctions = (Script::InvokeFunc_t *)calloc(100, sizeof(void *));
240    BCCchar **labels = new char*[100];
241    bccGetFunctions(s->mBccScript, (BCCsizei *)&s->mEnviroment.mInvokeFunctionCount,
242                    100, (BCCchar **)labels);
243    //LOGE("func count %i", s->mEnviroment.mInvokeFunctionCount);
244    for (uint32_t i=0; i < s->mEnviroment.mInvokeFunctionCount; i++) {
245        BCCsizei length;
246        bccGetFunctionBinary(s->mBccScript, labels[i], (BCCvoid **)&(s->mEnviroment.mInvokeFunctions[i]), &length);
247        //LOGE("func %i %p", i, s->mEnviroment.mInvokeFunctions[i]);
248    }
249
250    s->mEnviroment.mFieldAddress = (void **)calloc(100, sizeof(void *));
251    bccGetExportVars(s->mBccScript, (BCCsizei *)&s->mEnviroment.mFieldCount,
252                     100, s->mEnviroment.mFieldAddress);
253    //LOGE("var count %i", s->mEnviroment.mFieldCount);
254    for (uint32_t i=0; i < s->mEnviroment.mFieldCount; i++) {
255        //LOGE("var %i %p", i, s->mEnviroment.mFieldAddress[i]);
256    }
257
258    s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
259    s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
260    s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
261    s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
262
263    if (s->mProgram.mRoot) {
264        const static int pragmaMax = 16;
265        BCCsizei pragmaCount;
266        BCCchar * str[pragmaMax];
267        bccGetPragmas(s->mBccScript, &pragmaCount, pragmaMax, &str[0]);
268
269        for (int ct=0; ct < pragmaCount; ct+=2) {
270            //LOGE("pragme %s %s", str[ct], str[ct+1]);
271            if (!strcmp(str[ct], "version")) {
272                continue;
273            }
274
275            if (!strcmp(str[ct], "stateVertex")) {
276                if (!strcmp(str[ct+1], "default")) {
277                    continue;
278                }
279                if (!strcmp(str[ct+1], "parent")) {
280                    s->mEnviroment.mVertex.clear();
281                    continue;
282                }
283                LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
284            }
285
286            if (!strcmp(str[ct], "stateRaster")) {
287                if (!strcmp(str[ct+1], "default")) {
288                    continue;
289                }
290                if (!strcmp(str[ct+1], "parent")) {
291                    s->mEnviroment.mRaster.clear();
292                    continue;
293                }
294                LOGE("Unreconized value %s passed to stateRaster", str[ct+1]);
295            }
296
297            if (!strcmp(str[ct], "stateFragment")) {
298                if (!strcmp(str[ct+1], "default")) {
299                    continue;
300                }
301                if (!strcmp(str[ct+1], "parent")) {
302                    s->mEnviroment.mFragment.clear();
303                    continue;
304                }
305                LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
306            }
307
308            if (!strcmp(str[ct], "stateStore")) {
309                if (!strcmp(str[ct+1], "default")) {
310                    continue;
311                }
312                if (!strcmp(str[ct+1], "parent")) {
313                    s->mEnviroment.mFragmentStore.clear();
314                    continue;
315                }
316                LOGE("Unreconized value %s passed to stateStore", str[ct+1]);
317            }
318
319        }
320
321
322    } else {
323        // Deal with an error.
324    }
325}
326
327
328
329namespace android {
330namespace renderscript {
331
332void rsi_ScriptCBegin(Context * rsc)
333{
334    ScriptCState *ss = &rsc->mScriptC;
335    ss->clear();
336}
337
338void rsi_ScriptCSetScript(Context * rsc, void *vp)
339{
340    rsAssert(0);
341    //ScriptCState *ss = &rsc->mScriptC;
342    //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
343}
344
345void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
346{
347    ScriptCState *ss = &rsc->mScriptC;
348
349    char *t = (char *)malloc(len + 1);
350    memcpy(t, text, len);
351    t[len] = 0;
352    ss->mScript->mEnviroment.mScriptText = t;
353    ss->mScript->mEnviroment.mScriptTextLength = len;
354}
355
356
357RsScript rsi_ScriptCCreate(Context * rsc)
358{
359    ScriptCState *ss = &rsc->mScriptC;
360
361    ScriptC *s = ss->mScript;
362    ss->mScript = NULL;
363
364    ss->runCompiler(rsc, s);
365    s->incUserRef();
366    s->setContext(rsc);
367    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
368        s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
369        s->mSlotWritable[ct] = ss->mSlotWritable[ct];
370    }
371
372    ss->clear();
373    return s;
374}
375
376}
377}
378
379
380