rsScriptC.cpp revision 9c4e4ca9ff75a7fe18544c83fcf782e46c9b6ac2
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}
108
109static ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name)
110{
111    const ScriptCState::SymbolTable_t *sym = ScriptCState::lookupSymbol(name);
112    if (sym) {
113        return sym->mPtr;
114    }
115    LOGE("ScriptC sym lookup failed for %s", name);
116    return NULL;
117}
118
119void ScriptCState::runCompiler(Context *rsc)
120{
121    mAccScript = accCreateScript();
122    String8 tmp;
123
124    rsc->appendNameDefines(&tmp);
125    appendDecls(&tmp);
126    tmp.append("#line 1\n");
127
128    const char* scriptSource[] = {tmp.string(), mProgram.mScriptText};
129    int scriptLength[] = {tmp.length(), mProgram.mScriptTextLength} ;
130    accScriptSource(mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength);
131    accRegisterSymbolCallback(mAccScript, symbolLookup, NULL);
132    accCompileScript(mAccScript);
133    accGetScriptLabel(mAccScript, "main", (ACCvoid**) &mProgram.mScript);
134    rsAssert(mProgram.mScript);
135
136    if (!mProgram.mScript) {
137        ACCchar buf[4096];
138        ACCsizei len;
139        accGetScriptInfoLog(mAccScript, sizeof(buf), &len, buf);
140        LOGE(buf);
141
142    }
143
144    mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
145    mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
146    mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore());
147
148    if (mProgram.mScript) {
149        const static int pragmaMax = 16;
150        ACCsizei pragmaCount;
151        ACCchar * str[pragmaMax];
152        accGetPragmas(mAccScript, &pragmaCount, pragmaMax, &str[0]);
153
154        for (int ct=0; ct < pragmaCount; ct+=2) {
155            if (!strcmp(str[ct], "version")) {
156                continue;
157            }
158
159            if (!strcmp(str[ct], "stateVertex")) {
160                if (!strcmp(str[ct+1], "default")) {
161                    continue;
162                }
163                if (!strcmp(str[ct+1], "parent")) {
164                    mEnviroment.mVertex.clear();
165                    continue;
166                }
167                ProgramVertex * pv = (ProgramVertex *)rsc->lookupName(str[ct+1]);
168                if (pv != NULL) {
169                    mEnviroment.mVertex.set(pv);
170                    continue;
171                }
172                LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
173            }
174
175            if (!strcmp(str[ct], "stateRaster")) {
176                LOGE("Unreconized value %s passed to stateRaster", str[ct+1]);
177            }
178
179            if (!strcmp(str[ct], "stateFragment")) {
180                if (!strcmp(str[ct+1], "default")) {
181                    continue;
182                }
183                if (!strcmp(str[ct+1], "parent")) {
184                    mEnviroment.mFragment.clear();
185                    continue;
186                }
187                ProgramFragment * pf = (ProgramFragment *)rsc->lookupName(str[ct+1]);
188                if (pf != NULL) {
189                    mEnviroment.mFragment.set(pf);
190                    continue;
191                }
192                LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
193            }
194
195            if (!strcmp(str[ct], "stateFragmentStore")) {
196                if (!strcmp(str[ct+1], "default")) {
197                    continue;
198                }
199                if (!strcmp(str[ct+1], "parent")) {
200                    mEnviroment.mFragmentStore.clear();
201                    continue;
202                }
203                ProgramFragmentStore * pfs =
204                    (ProgramFragmentStore *)rsc->lookupName(str[ct+1]);
205                if (pfs != NULL) {
206                    mEnviroment.mFragmentStore.set(pfs);
207                    continue;
208                }
209                LOGE("Unreconized value %s passed to stateFragmentStore", str[ct+1]);
210            }
211
212        }
213
214
215    } else {
216        // Deal with an error.
217    }
218
219}
220
221namespace android {
222namespace renderscript {
223
224void rsi_ScriptCBegin(Context * rsc)
225{
226    ScriptCState *ss = &rsc->mScriptC;
227    ss->clear();
228}
229
230void rsi_ScriptCAddType(Context * rsc, RsType vt)
231{
232    ScriptCState *ss = &rsc->mScriptC;
233    ss->mConstantBufferTypes.add(static_cast<const Type *>(vt));
234}
235
236void rsi_ScriptCSetScript(Context * rsc, void *vp)
237{
238    ScriptCState *ss = &rsc->mScriptC;
239    ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
240}
241
242void rsi_ScriptCSetRoot(Context * rsc, bool isRoot)
243{
244    ScriptCState *ss = &rsc->mScriptC;
245    ss->mEnviroment.mIsRoot = isRoot;
246}
247
248void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
249{
250    ScriptCState *ss = &rsc->mScriptC;
251    ss->mProgram.mScriptText = text;
252    ss->mProgram.mScriptTextLength = len;
253}
254
255
256RsScript rsi_ScriptCCreate(Context * rsc)
257{
258    ScriptCState *ss = &rsc->mScriptC;
259
260    ss->runCompiler(rsc);
261
262    ScriptC *s = new ScriptC();
263    s->incRef();
264    s->mAccScript = ss->mAccScript;
265    ss->mAccScript = NULL;
266    s->mEnviroment = ss->mEnviroment;
267    s->mProgram = ss->mProgram;
268    ss->clear();
269
270    return s;
271}
272
273}
274}
275
276
277