rsScriptC.cpp revision 2dca84dd6c07992f78ad050177975f16486dd77e
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 free(mEnviroment.mScriptText); 50 mEnviroment.mScriptText = NULL; 51} 52 53void 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 63uint32_t 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 uint32_t ret = 0; 89 tls->mScript = this; 90 ret = mProgram.mScript(launchIndex); 91 tls->mScript = NULL; 92 return ret; 93} 94 95ScriptCState::ScriptCState() 96{ 97 mScript = NULL; 98 clear(); 99} 100 101ScriptCState::~ScriptCState() 102{ 103 delete mScript; 104 mScript = NULL; 105} 106 107void 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 123static 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 133void 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 270static 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 284void 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 309void 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 390namespace android { 391namespace renderscript { 392 393void rsi_ScriptCBegin(Context * rsc) 394{ 395 ScriptCState *ss = &rsc->mScriptC; 396 ss->clear(); 397} 398 399void 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 406void 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 418RsScript 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 438void rsi_ScriptCSetDefineF(Context *rsc, const char* name, float value) 439{ 440 ScriptCState *ss = &rsc->mScriptC; 441 ss->mFloatDefines.add(String8(name), value); 442} 443 444void 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