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