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