rsScriptC.cpp revision 57b79ceb1126e3797fa42367b97dd7bcfcda1ed9
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/String8.h"
23#include "utils/Timers.h"
24
25#include <GLES/gl.h>
26#include <GLES/glext.h>
27
28using namespace android;
29using namespace android::renderscript;
30
31#define GET_TLS()  Context::ScriptTLSStruct * tls = \
32    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
33    Context * rsc = tls->mContext; \
34    ScriptC * sc = (ScriptC *) tls->mScript
35
36
37ScriptC::ScriptC()
38{
39    mAccScript = NULL;
40    memset(&mProgram, 0, sizeof(mProgram));
41}
42
43ScriptC::~ScriptC()
44{
45    if (mAccScript) {
46        accDeleteScript(mAccScript);
47    }
48}
49
50
51bool ScriptC::run(Context *rsc, uint32_t launchIndex)
52{
53    Context::ScriptTLSStruct * tls =
54    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey);
55
56    if (mEnviroment.mFragmentStore.get()) {
57        rsc->setFragmentStore(mEnviroment.mFragmentStore.get());
58    }
59    if (mEnviroment.mFragment.get()) {
60        rsc->setFragment(mEnviroment.mFragment.get());
61    }
62    if (mEnviroment.mVertex.get()) {
63        rsc->setVertex(mEnviroment.mVertex.get());
64    }
65
66    if (launchIndex == 0) {
67        mEnviroment.mStartTimeMillis
68                = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
69    }
70
71    bool ret = false;
72    tls->mScript = this;
73    ret = mProgram.mScript(launchIndex) != 0;
74    tls->mScript = NULL;
75    return ret;
76}
77
78ScriptCState::ScriptCState()
79{
80    clear();
81}
82
83ScriptCState::~ScriptCState()
84{
85    if (mAccScript) {
86        accDeleteScript(mAccScript);
87    }
88}
89
90void ScriptCState::clear()
91{
92    memset(&mProgram, 0, sizeof(mProgram));
93
94    mConstantBufferTypes.clear();
95
96    memset(&mEnviroment, 0, sizeof(mEnviroment));
97    mEnviroment.mClearColor[0] = 0;
98    mEnviroment.mClearColor[1] = 0;
99    mEnviroment.mClearColor[2] = 0;
100    mEnviroment.mClearColor[3] = 1;
101    mEnviroment.mClearDepth = 1;
102    mEnviroment.mClearStencil = 0;
103    mEnviroment.mIsRoot = false;
104
105    mAccScript = NULL;
106
107    mInt32Defines.clear();
108    mFloatDefines.clear();
109}
110
111static ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name)
112{
113    const ScriptCState::SymbolTable_t *sym = ScriptCState::lookupSymbol(name);
114    if (sym) {
115        return sym->mPtr;
116    }
117    LOGE("ScriptC sym lookup failed for %s", name);
118    return NULL;
119}
120
121void ScriptCState::runCompiler(Context *rsc)
122{
123    mAccScript = accCreateScript();
124    String8 tmp;
125
126    rsc->appendNameDefines(&tmp);
127    appendDecls(&tmp);
128    rsc->appendVarDefines(&tmp);
129    appendVarDefines(&tmp);
130    tmp.append("#line 1\n");
131
132    const char* scriptSource[] = {tmp.string(), mProgram.mScriptText};
133    int scriptLength[] = {tmp.length(), mProgram.mScriptTextLength} ;
134    accScriptSource(mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength);
135    accRegisterSymbolCallback(mAccScript, symbolLookup, NULL);
136    accCompileScript(mAccScript);
137    accGetScriptLabel(mAccScript, "main", (ACCvoid**) &mProgram.mScript);
138    rsAssert(mProgram.mScript);
139
140    if (!mProgram.mScript) {
141        ACCchar buf[4096];
142        ACCsizei len;
143        accGetScriptInfoLog(mAccScript, sizeof(buf), &len, buf);
144        LOGE(buf);
145    }
146
147    mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
148    mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
149    mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore());
150
151    if (mProgram.mScript) {
152        const static int pragmaMax = 16;
153        ACCsizei pragmaCount;
154        ACCchar * str[pragmaMax];
155        accGetPragmas(mAccScript, &pragmaCount, pragmaMax, &str[0]);
156
157        for (int ct=0; ct < pragmaCount; ct+=2) {
158            if (!strcmp(str[ct], "version")) {
159                continue;
160            }
161
162            if (!strcmp(str[ct], "stateVertex")) {
163                if (!strcmp(str[ct+1], "default")) {
164                    continue;
165                }
166                if (!strcmp(str[ct+1], "parent")) {
167                    mEnviroment.mVertex.clear();
168                    continue;
169                }
170                ProgramVertex * pv = (ProgramVertex *)rsc->lookupName(str[ct+1]);
171                if (pv != NULL) {
172                    mEnviroment.mVertex.set(pv);
173                    continue;
174                }
175                LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
176            }
177
178            if (!strcmp(str[ct], "stateRaster")) {
179                LOGE("Unreconized value %s passed to stateRaster", str[ct+1]);
180            }
181
182            if (!strcmp(str[ct], "stateFragment")) {
183                if (!strcmp(str[ct+1], "default")) {
184                    continue;
185                }
186                if (!strcmp(str[ct+1], "parent")) {
187                    mEnviroment.mFragment.clear();
188                    continue;
189                }
190                ProgramFragment * pf = (ProgramFragment *)rsc->lookupName(str[ct+1]);
191                if (pf != NULL) {
192                    mEnviroment.mFragment.set(pf);
193                    continue;
194                }
195                LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
196            }
197
198            if (!strcmp(str[ct], "stateFragmentStore")) {
199                if (!strcmp(str[ct+1], "default")) {
200                    continue;
201                }
202                if (!strcmp(str[ct+1], "parent")) {
203                    mEnviroment.mFragmentStore.clear();
204                    continue;
205                }
206                ProgramFragmentStore * pfs =
207                    (ProgramFragmentStore *)rsc->lookupName(str[ct+1]);
208                if (pfs != NULL) {
209                    mEnviroment.mFragmentStore.set(pfs);
210                    continue;
211                }
212                LOGE("Unreconized value %s passed to stateFragmentStore", str[ct+1]);
213            }
214
215        }
216
217
218    } else {
219        // Deal with an error.
220    }
221}
222
223
224void ScriptCState::appendVarDefines(String8 *str)
225{
226    char buf[256];
227    LOGD("appendVarDefines mInt32Defines.size()=%d mFloatDefines.size()=%d\n",
228            mInt32Defines.size(), mFloatDefines.size());
229    for (size_t ct=0; ct < mInt32Defines.size(); ct++) {
230        str->append("#define ");
231        str->append(mInt32Defines.keyAt(ct));
232        str->append(" ");
233        sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct));
234        str->append(buf);
235    }
236    for (size_t ct=0; ct < mFloatDefines.size(); ct++) {
237        str->append("#define ");
238        str->append(mFloatDefines.keyAt(ct));
239        str->append(" ");
240        sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct));
241        str->append(buf);
242    }
243}
244
245
246namespace android {
247namespace renderscript {
248
249void rsi_ScriptCBegin(Context * rsc)
250{
251    ScriptCState *ss = &rsc->mScriptC;
252    ss->clear();
253}
254
255void rsi_ScriptCAddType(Context * rsc, RsType vt)
256{
257    ScriptCState *ss = &rsc->mScriptC;
258    ss->mConstantBufferTypes.add(static_cast<const Type *>(vt));
259}
260
261void rsi_ScriptCSetScript(Context * rsc, void *vp)
262{
263    ScriptCState *ss = &rsc->mScriptC;
264    ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
265}
266
267void rsi_ScriptCSetRoot(Context * rsc, bool isRoot)
268{
269    ScriptCState *ss = &rsc->mScriptC;
270    ss->mEnviroment.mIsRoot = isRoot;
271}
272
273void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
274{
275    ScriptCState *ss = &rsc->mScriptC;
276    ss->mProgram.mScriptText = text;
277    ss->mProgram.mScriptTextLength = len;
278}
279
280
281RsScript rsi_ScriptCCreate(Context * rsc)
282{
283    ScriptCState *ss = &rsc->mScriptC;
284
285    ss->runCompiler(rsc);
286
287    ScriptC *s = new ScriptC();
288    s->incRef();
289    s->mAccScript = ss->mAccScript;
290    ss->mAccScript = NULL;
291    s->mEnviroment = ss->mEnviroment;
292    s->mProgram = ss->mProgram;
293    ss->clear();
294
295    return s;
296}
297
298void rsi_ScriptCSetDefineF(Context *rsc, const char* name, float value)
299{
300    ScriptCState *ss = &rsc->mScriptC;
301    ss->mFloatDefines.add(String8(name), value);
302}
303
304void rsi_ScriptCSetDefineI32(Context *rsc, const char* name, int32_t value)
305{
306    ScriptCState *ss = &rsc->mScriptC;
307    ss->mInt32Defines.add(String8(name), value);
308}
309
310}
311}
312
313
314