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