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