rsScriptC.cpp revision 5235cf3f41cfcfe39c7072fddf1ead52db31292d
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
21#include "acc/acc.h"
22#include "utils/Timers.h"
23
24#include <GLES/gl.h>
25#include <GLES/glext.h>
26
27using namespace android;
28using namespace android::renderscript;
29
30#define GET_TLS()  Context::ScriptTLSStruct * tls = \
31    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
32    Context * rsc = tls->mContext; \
33    ScriptC * sc = (ScriptC *) tls->mScript
34
35
36ScriptC::ScriptC(Context *rsc) : Script(rsc)
37{
38    mAllocFile = __FILE__;
39    mAllocLine = __LINE__;
40    mAccScript = NULL;
41    memset(&mProgram, 0, sizeof(mProgram));
42}
43
44ScriptC::~ScriptC()
45{
46    if (mAccScript) {
47        accDeleteScript(mAccScript);
48    }
49}
50
51void ScriptC::setupScript()
52{
53    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
54        if (mProgram.mSlotPointers[ct]) {
55            *mProgram.mSlotPointers[ct] = mSlots[ct]->getPtr();
56        }
57    }
58}
59
60
61bool ScriptC::run(Context *rsc, uint32_t launchIndex)
62{
63    Context::ScriptTLSStruct * tls =
64    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey);
65
66    if (mEnviroment.mFragmentStore.get()) {
67        rsc->setFragmentStore(mEnviroment.mFragmentStore.get());
68    }
69    if (mEnviroment.mFragment.get()) {
70        rsc->setFragment(mEnviroment.mFragment.get());
71    }
72    if (mEnviroment.mVertex.get()) {
73        rsc->setVertex(mEnviroment.mVertex.get());
74    }
75    if (mEnviroment.mRaster.get()) {
76        rsc->setRaster(mEnviroment.mRaster.get());
77    }
78
79    if (launchIndex == 0) {
80        mEnviroment.mStartTimeMillis
81                = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
82    }
83    setupScript();
84
85    bool ret = false;
86    tls->mScript = this;
87    ret = mProgram.mScript(launchIndex) != 0;
88    tls->mScript = NULL;
89    return ret;
90}
91
92ScriptCState::ScriptCState()
93{
94    mScript = NULL;
95    clear();
96}
97
98ScriptCState::~ScriptCState()
99{
100    delete mScript;
101    mScript = NULL;
102}
103
104void ScriptCState::clear()
105{
106    for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
107        mConstantBufferTypes[ct].clear();
108        mSlotNames[ct].setTo("");
109        mInvokableNames[ct].setTo("");
110        mSlotWritable[ct] = false;
111    }
112
113    delete mScript;
114    mScript = new ScriptC(NULL);
115
116    mInt32Defines.clear();
117    mFloatDefines.clear();
118}
119
120static ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name)
121{
122    const ScriptCState::SymbolTable_t *sym = ScriptCState::lookupSymbol(name);
123    if (sym) {
124        return sym->mPtr;
125    }
126    LOGE("ScriptC sym lookup failed for %s", name);
127    return NULL;
128}
129
130void ScriptCState::runCompiler(Context *rsc, ScriptC *s)
131{
132    s->mAccScript = accCreateScript();
133    String8 tmp;
134
135    rsc->appendNameDefines(&tmp);
136    appendDecls(&tmp);
137    rsc->appendVarDefines(&tmp);
138    appendVarDefines(rsc, &tmp);
139    appendTypes(rsc, &tmp);
140    tmp.append("#line 1\n");
141
142    const char* scriptSource[] = {tmp.string(), s->mEnviroment.mScriptText};
143    int scriptLength[] = {tmp.length(), s->mEnviroment.mScriptTextLength} ;
144    accScriptSource(s->mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength);
145    accRegisterSymbolCallback(s->mAccScript, symbolLookup, NULL);
146    accCompileScript(s->mAccScript);
147    accGetScriptLabel(s->mAccScript, "main", (ACCvoid**) &s->mProgram.mScript);
148    accGetScriptLabel(s->mAccScript, "init", (ACCvoid**) &s->mProgram.mInit);
149    rsAssert(s->mProgram.mScript);
150
151    if (!s->mProgram.mScript) {
152        ACCchar buf[4096];
153        ACCsizei len;
154        accGetScriptInfoLog(s->mAccScript, sizeof(buf), &len, buf);
155        LOGV(buf);
156    }
157
158    if (s->mProgram.mInit) {
159        s->mProgram.mInit();
160    }
161
162    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
163        if (mSlotNames[ct].length() > 0) {
164            accGetScriptLabel(s->mAccScript,
165                              mSlotNames[ct].string(),
166                              (ACCvoid**) &s->mProgram.mSlotPointers[ct]);
167        }
168    }
169
170    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
171        if (mInvokableNames[ct].length() > 0) {
172            accGetScriptLabel(s->mAccScript,
173                              mInvokableNames[ct].string(),
174                              (ACCvoid**) &s->mEnviroment.mInvokables[ct]);
175        }
176    }
177
178    s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
179    s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
180    s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore());
181    s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
182
183    if (s->mProgram.mScript) {
184        const static int pragmaMax = 16;
185        ACCsizei pragmaCount;
186        ACCchar * str[pragmaMax];
187        accGetPragmas(s->mAccScript, &pragmaCount, pragmaMax, &str[0]);
188
189        for (int ct=0; ct < pragmaCount; ct+=2) {
190            if (!strcmp(str[ct], "version")) {
191                continue;
192            }
193
194            if (!strcmp(str[ct], "stateVertex")) {
195                if (!strcmp(str[ct+1], "default")) {
196                    continue;
197                }
198                if (!strcmp(str[ct+1], "parent")) {
199                    s->mEnviroment.mVertex.clear();
200                    continue;
201                }
202                ProgramVertex * pv = (ProgramVertex *)rsc->lookupName(str[ct+1]);
203                if (pv != NULL) {
204                    s->mEnviroment.mVertex.set(pv);
205                    continue;
206                }
207                LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
208            }
209
210            if (!strcmp(str[ct], "stateRaster")) {
211                if (!strcmp(str[ct+1], "default")) {
212                    continue;
213                }
214                if (!strcmp(str[ct+1], "parent")) {
215                    s->mEnviroment.mRaster.clear();
216                    continue;
217                }
218                ProgramRaster * pr = (ProgramRaster *)rsc->lookupName(str[ct+1]);
219                if (pr != NULL) {
220                    s->mEnviroment.mRaster.set(pr);
221                    continue;
222                }
223                LOGE("Unreconized value %s passed to stateRaster", str[ct+1]);
224            }
225
226            if (!strcmp(str[ct], "stateFragment")) {
227                if (!strcmp(str[ct+1], "default")) {
228                    continue;
229                }
230                if (!strcmp(str[ct+1], "parent")) {
231                    s->mEnviroment.mFragment.clear();
232                    continue;
233                }
234                ProgramFragment * pf = (ProgramFragment *)rsc->lookupName(str[ct+1]);
235                if (pf != NULL) {
236                    s->mEnviroment.mFragment.set(pf);
237                    continue;
238                }
239                LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
240            }
241
242            if (!strcmp(str[ct], "stateStore")) {
243                if (!strcmp(str[ct+1], "default")) {
244                    continue;
245                }
246                if (!strcmp(str[ct+1], "parent")) {
247                    s->mEnviroment.mFragmentStore.clear();
248                    continue;
249                }
250                ProgramFragmentStore * pfs =
251                    (ProgramFragmentStore *)rsc->lookupName(str[ct+1]);
252                if (pfs != NULL) {
253                    s->mEnviroment.mFragmentStore.set(pfs);
254                    continue;
255                }
256                LOGE("Unreconized value %s passed to stateStore", str[ct+1]);
257            }
258
259        }
260
261
262    } else {
263        // Deal with an error.
264    }
265}
266
267static void appendElementBody(String8 *s, const Element *e)
268{
269    s->append(" {\n");
270    for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
271        const Component *c = e->getComponent(ct2);
272        s->append("    ");
273        s->append(c->getCType());
274        s->append(" ");
275        s->append(c->getComponentName());
276        s->append(";\n");
277    }
278    s->append("}");
279}
280
281void ScriptCState::appendVarDefines(const Context *rsc, String8 *str)
282{
283    char buf[256];
284    if (rsc->props.mLogScripts) {
285        LOGD("appendVarDefines mInt32Defines.size()=%d mFloatDefines.size()=%d\n",
286                mInt32Defines.size(), mFloatDefines.size());
287    }
288    for (size_t ct=0; ct < mInt32Defines.size(); ct++) {
289        str->append("#define ");
290        str->append(mInt32Defines.keyAt(ct));
291        str->append(" ");
292        sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct));
293        str->append(buf);
294    }
295    for (size_t ct=0; ct < mFloatDefines.size(); ct++) {
296        str->append("#define ");
297        str->append(mFloatDefines.keyAt(ct));
298        str->append(" ");
299        sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct));
300        str->append(buf);
301    }
302}
303
304
305
306void ScriptCState::appendTypes(const Context *rsc, String8 *str)
307{
308    char buf[256];
309    String8 tmp;
310
311    str->append("struct vec2_s {float x; float y;};");
312    str->append("struct vec3_s {float x; float y; float z;};");
313    str->append("struct vec4_s {float x; float y; float z; float w;};");
314
315    for (size_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
316        const Type *t = mConstantBufferTypes[ct].get();
317        if (!t) {
318            continue;
319        }
320        const Element *e = t->getElement();
321        if (e->getName() && (e->getComponentCount() > 1)) {
322            String8 s("struct struct_");
323            s.append(e->getName());
324            appendElementBody(&s, e);
325            s.append(";\n");
326            s.append("#define ");
327            s.append(e->getName());
328            s.append("_t struct struct_");
329            s.append(e->getName());
330            s.append("\n\n");
331            if (rsc->props.mLogScripts) {
332                LOGV(s);
333            }
334            str->append(s);
335        }
336
337        if (t->getName()) {
338            for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
339                const Component *c = e->getComponent(ct2);
340                tmp.setTo("#define OFFSETOF_");
341                tmp.append(t->getName());
342                tmp.append("_");
343                tmp.append(c->getComponentName());
344                sprintf(buf, " %i\n", ct2);
345                tmp.append(buf);
346                if (rsc->props.mLogScripts) {
347                    LOGV(tmp);
348                }
349                str->append(tmp);
350            }
351        }
352
353        if (mSlotNames[ct].length() > 0) {
354            String8 s;
355            if (e->getComponentCount() > 1) {
356                if (e->getName()) {
357                    // Use the named struct
358                    s.setTo(e->getName());
359                    s.append("_t *");
360                } else {
361                    // create an struct named from the slot.
362                    s.setTo("struct ");
363                    s.append(mSlotNames[ct]);
364                    s.append("_s");
365                    appendElementBody(&s, e);
366                    s.append(";\n");
367                    s.append("struct ");
368                    s.append(mSlotNames[ct]);
369                    s.append("_s * ");
370                }
371            } else {
372                // Just make an array
373                s.setTo(e->getComponent(0)->getCType());
374                s.append("_t *");
375            }
376            s.append(mSlotNames[ct]);
377            s.append(";\n");
378            if (rsc->props.mLogScripts) {
379                LOGV(s);
380            }
381            str->append(s);
382        }
383    }
384}
385
386
387namespace android {
388namespace renderscript {
389
390void rsi_ScriptCBegin(Context * rsc)
391{
392    ScriptCState *ss = &rsc->mScriptC;
393    ss->clear();
394}
395
396void rsi_ScriptCSetScript(Context * rsc, void *vp)
397{
398    rsAssert(0);
399    //ScriptCState *ss = &rsc->mScriptC;
400    //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
401}
402
403void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
404{
405    ScriptCState *ss = &rsc->mScriptC;
406    ss->mScript->mEnviroment.mScriptText = text;
407    ss->mScript->mEnviroment.mScriptTextLength = len;
408}
409
410
411RsScript rsi_ScriptCCreate(Context * rsc)
412{
413    ScriptCState *ss = &rsc->mScriptC;
414
415    ScriptC *s = ss->mScript;
416    ss->mScript = NULL;
417
418    ss->runCompiler(rsc, s);
419    s->incUserRef();
420    s->setContext(rsc);
421    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
422        s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
423        s->mSlotNames[ct] = ss->mSlotNames[ct];
424        s->mSlotWritable[ct] = ss->mSlotWritable[ct];
425    }
426
427    ss->clear();
428    return s;
429}
430
431void rsi_ScriptCSetDefineF(Context *rsc, const char* name, float value)
432{
433    ScriptCState *ss = &rsc->mScriptC;
434    ss->mFloatDefines.add(String8(name), value);
435}
436
437void rsi_ScriptCSetDefineI32(Context *rsc, const char* name, int32_t value)
438{
439    ScriptCState *ss = &rsc->mScriptC;
440    ss->mInt32Defines.add(String8(name), value);
441}
442
443}
444}
445
446
447