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