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