rsScriptC.cpp revision d3f2eaf60a349316a219ebd12b4ee88f6d1b1261
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() 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(); 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(&tmp); 134 appendTypes(&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(String8 *str) 264{ 265 char buf[256]; 266 LOGD("appendVarDefines mInt32Defines.size()=%d mFloatDefines.size()=%d\n", 267 mInt32Defines.size(), mFloatDefines.size()); 268 for (size_t ct=0; ct < mInt32Defines.size(); ct++) { 269 str->append("#define "); 270 str->append(mInt32Defines.keyAt(ct)); 271 str->append(" "); 272 sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct)); 273 str->append(buf); 274 } 275 for (size_t ct=0; ct < mFloatDefines.size(); ct++) { 276 str->append("#define "); 277 str->append(mFloatDefines.keyAt(ct)); 278 str->append(" "); 279 sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct)); 280 str->append(buf); 281 } 282} 283 284 285 286void ScriptCState::appendTypes(String8 *str) 287{ 288 char buf[256]; 289 String8 tmp; 290 291 str->append("struct vec2_s {float x; float y;};"); 292 str->append("struct vec3_s {float x; float y; float z;};"); 293 str->append("struct vec4_s {float x; float y; float z; float w;};"); 294 295 for (size_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) { 296 const Type *t = mConstantBufferTypes[ct].get(); 297 if (!t) { 298 continue; 299 } 300 const Element *e = t->getElement(); 301 if (e->getName() && (e->getComponentCount() > 1)) { 302 String8 s("struct struct_"); 303 s.append(e->getName()); 304 appendElementBody(&s, e); 305 s.append(";\n"); 306 s.append("#define "); 307 s.append(e->getName()); 308 s.append("_t struct struct_"); 309 s.append(e->getName()); 310 s.append("\n\n"); 311 LOGD(s); 312 str->append(s); 313 } 314 315 if (t->getName()) { 316 for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) { 317 const Component *c = e->getComponent(ct2); 318 tmp.setTo("#define OFFSETOF_"); 319 tmp.append(t->getName()); 320 tmp.append("_"); 321 tmp.append(c->getComponentName()); 322 sprintf(buf, " %i\n", ct2); 323 tmp.append(buf); 324 LOGD(tmp); 325 str->append(tmp); 326 } 327 } 328 329 if (mSlotNames[ct].length() > 0) { 330 String8 s; 331 if (e->getComponentCount() > 1) { 332 if (e->getName()) { 333 // Use the named struct 334 s.setTo(e->getName()); 335 s.append("_t *"); 336 } else { 337 // create an struct named from the slot. 338 s.setTo("struct "); 339 s.append(mSlotNames[ct]); 340 s.append("_s"); 341 appendElementBody(&s, e); 342 s.append(";\n"); 343 s.append("struct "); 344 s.append(mSlotNames[ct]); 345 s.append("_s * "); 346 } 347 } else { 348 // Just make an array 349 s.setTo(e->getComponent(0)->getCType()); 350 s.append("_t *"); 351 } 352 s.append(mSlotNames[ct]); 353 s.append(";\n"); 354 LOGD(s); 355 str->append(s); 356 } 357 } 358} 359 360 361namespace android { 362namespace renderscript { 363 364void rsi_ScriptCBegin(Context * rsc) 365{ 366 ScriptCState *ss = &rsc->mScriptC; 367 ss->clear(); 368} 369 370void rsi_ScriptCSetScript(Context * rsc, void *vp) 371{ 372 rsAssert(0); 373 //ScriptCState *ss = &rsc->mScriptC; 374 //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp); 375} 376 377void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len) 378{ 379 ScriptCState *ss = &rsc->mScriptC; 380 ss->mScript->mEnviroment.mScriptText = text; 381 ss->mScript->mEnviroment.mScriptTextLength = len; 382} 383 384 385RsScript rsi_ScriptCCreate(Context * rsc) 386{ 387 ScriptCState *ss = &rsc->mScriptC; 388 389 ScriptC *s = ss->mScript; 390 ss->mScript = NULL; 391 392 ss->runCompiler(rsc, s); 393 s->incUserRef(); 394 for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) { 395 s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get()); 396 s->mSlotNames[ct] = ss->mSlotNames[ct]; 397 s->mSlotWritable[ct] = ss->mSlotWritable[ct]; 398 } 399 400 ss->clear(); 401 return s; 402} 403 404void rsi_ScriptCSetDefineF(Context *rsc, const char* name, float value) 405{ 406 ScriptCState *ss = &rsc->mScriptC; 407 ss->mFloatDefines.add(String8(name), value); 408} 409 410void rsi_ScriptCSetDefineI32(Context *rsc, const char* name, int32_t value) 411{ 412 ScriptCState *ss = &rsc->mScriptC; 413 ss->mInt32Defines.add(String8(name), value); 414} 415 416} 417} 418 419 420