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