rsScriptC.cpp revision 90b36a88cf0cc549b296ac15a249ea7786c6de9e
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    bool ret = false;
71    tls->mScript = this;
72    ret = mProgram.mScript(launchIndex) != 0;
73    tls->mScript = NULL;
74    return ret;
75}
76
77ScriptCState::ScriptCState()
78{
79    clear();
80}
81
82ScriptCState::~ScriptCState()
83{
84    if (mAccScript) {
85        accDeleteScript(mAccScript);
86    }
87}
88
89void ScriptCState::clear()
90{
91    memset(&mProgram, 0, sizeof(mProgram));
92
93    for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
94        mConstantBufferTypes[ct].clear();
95        mSlotNames[ct].setTo("");
96        mSlotWritable[ct] = false;
97    }
98
99    memset(&mEnviroment, 0, sizeof(mEnviroment));
100    mEnviroment.mClearColor[0] = 0;
101    mEnviroment.mClearColor[1] = 0;
102    mEnviroment.mClearColor[2] = 0;
103    mEnviroment.mClearColor[3] = 1;
104    mEnviroment.mClearDepth = 1;
105    mEnviroment.mClearStencil = 0;
106    mEnviroment.mIsRoot = false;
107
108    mAccScript = NULL;
109
110    mInt32Defines.clear();
111    mFloatDefines.clear();
112}
113
114static ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name)
115{
116    const ScriptCState::SymbolTable_t *sym = ScriptCState::lookupSymbol(name);
117    if (sym) {
118        return sym->mPtr;
119    }
120    LOGE("ScriptC sym lookup failed for %s", name);
121    return NULL;
122}
123
124void ScriptCState::runCompiler(Context *rsc)
125{
126    mAccScript = accCreateScript();
127    String8 tmp;
128
129    rsc->appendNameDefines(&tmp);
130    appendDecls(&tmp);
131    rsc->appendVarDefines(&tmp);
132    appendVarDefines(&tmp);
133    appendTypes(&tmp);
134    tmp.append("#line 1\n");
135
136    const char* scriptSource[] = {tmp.string(), mProgram.mScriptText};
137    int scriptLength[] = {tmp.length(), mProgram.mScriptTextLength} ;
138    accScriptSource(mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength);
139    accRegisterSymbolCallback(mAccScript, symbolLookup, NULL);
140    accCompileScript(mAccScript);
141    accGetScriptLabel(mAccScript, "main", (ACCvoid**) &mProgram.mScript);
142    rsAssert(mProgram.mScript);
143
144    if (!mProgram.mScript) {
145        ACCchar buf[4096];
146        ACCsizei len;
147        accGetScriptInfoLog(mAccScript, sizeof(buf), &len, buf);
148        LOGE(buf);
149    }
150
151    mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
152    mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
153    mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore());
154
155    if (mProgram.mScript) {
156        const static int pragmaMax = 16;
157        ACCsizei pragmaCount;
158        ACCchar * str[pragmaMax];
159        accGetPragmas(mAccScript, &pragmaCount, pragmaMax, &str[0]);
160
161        for (int ct=0; ct < pragmaCount; ct+=2) {
162            if (!strcmp(str[ct], "version")) {
163                continue;
164            }
165
166            if (!strcmp(str[ct], "stateVertex")) {
167                if (!strcmp(str[ct+1], "default")) {
168                    continue;
169                }
170                if (!strcmp(str[ct+1], "parent")) {
171                    mEnviroment.mVertex.clear();
172                    continue;
173                }
174                ProgramVertex * pv = (ProgramVertex *)rsc->lookupName(str[ct+1]);
175                if (pv != NULL) {
176                    mEnviroment.mVertex.set(pv);
177                    continue;
178                }
179                LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
180            }
181
182            if (!strcmp(str[ct], "stateRaster")) {
183                LOGE("Unreconized value %s passed to stateRaster", str[ct+1]);
184            }
185
186            if (!strcmp(str[ct], "stateFragment")) {
187                if (!strcmp(str[ct+1], "default")) {
188                    continue;
189                }
190                if (!strcmp(str[ct+1], "parent")) {
191                    mEnviroment.mFragment.clear();
192                    continue;
193                }
194                ProgramFragment * pf = (ProgramFragment *)rsc->lookupName(str[ct+1]);
195                if (pf != NULL) {
196                    mEnviroment.mFragment.set(pf);
197                    continue;
198                }
199                LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
200            }
201
202            if (!strcmp(str[ct], "stateFragmentStore")) {
203                if (!strcmp(str[ct+1], "default")) {
204                    continue;
205                }
206                if (!strcmp(str[ct+1], "parent")) {
207                    mEnviroment.mFragmentStore.clear();
208                    continue;
209                }
210                ProgramFragmentStore * pfs =
211                    (ProgramFragmentStore *)rsc->lookupName(str[ct+1]);
212                if (pfs != NULL) {
213                    mEnviroment.mFragmentStore.set(pfs);
214                    continue;
215                }
216                LOGE("Unreconized value %s passed to stateFragmentStore", str[ct+1]);
217            }
218
219        }
220
221
222    } else {
223        // Deal with an error.
224    }
225}
226
227
228void ScriptCState::appendVarDefines(String8 *str)
229{
230    char buf[256];
231    LOGD("appendVarDefines mInt32Defines.size()=%d mFloatDefines.size()=%d\n",
232            mInt32Defines.size(), mFloatDefines.size());
233    for (size_t ct=0; ct < mInt32Defines.size(); ct++) {
234        str->append("#define ");
235        str->append(mInt32Defines.keyAt(ct));
236        str->append(" ");
237        sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct));
238        str->append(buf);
239    }
240    for (size_t ct=0; ct < mFloatDefines.size(); ct++) {
241        str->append("#define ");
242        str->append(mFloatDefines.keyAt(ct));
243        str->append(" ");
244        sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct));
245        str->append(buf);
246    }
247}
248
249void ScriptCState::appendTypes(String8 *str)
250{
251    char buf[256];
252    String8 tmp;
253
254    for (size_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
255        const Type *t = mConstantBufferTypes[ct].get();
256        if (!t) {
257            continue;
258        }
259        const Element *e = t->getElement();
260
261        if (t->getName()) {
262            for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
263                const Component *c = e->getComponent(ct2);
264                tmp.setTo("#define OFFSETOF_");
265                tmp.append(t->getName());
266                tmp.append("_");
267                tmp.append(c->getComponentName());
268                sprintf(buf, " %i\n", ct2);
269                tmp.append(buf);
270                LOGD(tmp);
271                str->append(tmp);
272            }
273        }
274
275        if (mSlotNames[ct].length() > 0) {
276            for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
277                const Component *c = e->getComponent(ct2);
278                tmp.setTo("#define ");
279                tmp.append(mSlotNames[ct]);
280                tmp.append("_");
281                tmp.append(c->getComponentName());
282                switch (c->getType()) {
283                case Component::FLOAT:
284                    tmp.append(" loadF(");
285                    break;
286                case Component::SIGNED:
287                    sprintf(buf, " loadI%i(", c->getBits());
288                    tmp.append(buf);
289                    break;
290                case Component::UNSIGNED:
291                    sprintf(buf, " loadU%i(", c->getBits());
292                    tmp.append(buf);
293                    break;
294                }
295                sprintf(buf, "%i, %i)\n", ct, ct2);
296                tmp.append(buf);
297
298                LOGD(tmp);
299                str->append(tmp);
300            }
301        }
302    }
303
304}
305
306
307namespace android {
308namespace renderscript {
309
310void rsi_ScriptCBegin(Context * rsc)
311{
312    ScriptCState *ss = &rsc->mScriptC;
313    ss->clear();
314}
315
316void rsi_ScriptCSetScript(Context * rsc, void *vp)
317{
318    ScriptCState *ss = &rsc->mScriptC;
319    ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
320}
321
322void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
323{
324    ScriptCState *ss = &rsc->mScriptC;
325    ss->mProgram.mScriptText = text;
326    ss->mProgram.mScriptTextLength = len;
327}
328
329
330RsScript rsi_ScriptCCreate(Context * rsc)
331{
332    ScriptCState *ss = &rsc->mScriptC;
333
334    ss->runCompiler(rsc);
335
336    ScriptC *s = new ScriptC();
337    s->incRef();
338    s->mAccScript = ss->mAccScript;
339    ss->mAccScript = NULL;
340    s->mEnviroment = ss->mEnviroment;
341    s->mProgram = ss->mProgram;
342    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
343        s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
344        s->mSlotNames[ct] = ss->mSlotNames[ct];
345        s->mSlotWritable[ct] = ss->mSlotWritable[ct];
346    }
347
348    ss->clear();
349    return s;
350}
351
352void rsi_ScriptCSetDefineF(Context *rsc, const char* name, float value)
353{
354    ScriptCState *ss = &rsc->mScriptC;
355    ss->mFloatDefines.add(String8(name), value);
356}
357
358void rsi_ScriptCSetDefineI32(Context *rsc, const char* name, int32_t value)
359{
360    ScriptCState *ss = &rsc->mScriptC;
361    ss->mInt32Defines.add(String8(name), value);
362}
363
364}
365}
366
367
368