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