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