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