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