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