rsScriptC.cpp revision d79b2e9f8b0fa43f6734aaa5e9d0d389d5da5109
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#include "../../../external/llvm/libbcc/include/bcc/bcc.h" 21#include "utils/Timers.h" 22 23#include <GLES/gl.h> 24#include <GLES/glext.h> 25 26using namespace android; 27using namespace android::renderscript; 28 29#define GET_TLS() Context::ScriptTLSStruct * tls = \ 30 (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \ 31 Context * rsc = tls->mContext; \ 32 ScriptC * sc = (ScriptC *) tls->mScript 33 34 35ScriptC::ScriptC(Context *rsc) : Script(rsc) 36{ 37 mAllocFile = __FILE__; 38 mAllocLine = __LINE__; 39 mBccScript = NULL; 40 memset(&mProgram, 0, sizeof(mProgram)); 41} 42 43ScriptC::~ScriptC() 44{ 45 if (mBccScript) { 46 bccDeleteScript(mBccScript); 47 } 48 free(mEnviroment.mScriptText); 49 mEnviroment.mScriptText = NULL; 50} 51 52void ScriptC::setupScript() 53{ 54 for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) { 55 if (!mSlots[ct].get()) 56 continue; 57 void *ptr = mSlots[ct]->getPtr(); 58 void **dest = ((void ***)mEnviroment.mFieldAddress)[ct]; 59 //LOGE("setupScript %i %p = %p %p %i", ct, dest, ptr, mSlots[ct]->getType(), mSlots[ct]->getType()->getDimX()); 60 61 //const uint32_t *p32 = (const uint32_t *)ptr; 62 //for (uint32_t ct2=0; ct2 < mSlots[ct]->getType()->getDimX(); ct2++) { 63 //LOGE(" %i = 0x%08x ", ct2, p32[ct2]); 64 //} 65 66 if (dest) { 67 *dest = ptr; 68 } else { 69 LOGE("ScriptC::setupScript, NULL var binding address."); 70 } 71 } 72} 73 74const Allocation *ScriptC::ptrToAllocation(const void *ptr) const 75{ 76 if (!ptr) { 77 return NULL; 78 } 79 for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) { 80 if (!mSlots[ct].get()) 81 continue; 82 if (mSlots[ct]->getPtr() == ptr) { 83 return mSlots[ct].get(); 84 } 85 } 86 LOGE("ScriptC::ptrToAllocation, failed to find %p", ptr); 87 return NULL; 88} 89 90void ScriptC::setTLS() 91{ 92 Context::ScriptTLSStruct * tls = (Context::ScriptTLSStruct *) 93 pthread_getspecific(Context::gThreadTLSKey); 94 rsAssert(tls); 95 tls->mScript = this; 96} 97 98void ScriptC::clearTLS() 99{ 100 Context::ScriptTLSStruct * tls = (Context::ScriptTLSStruct *) 101 pthread_getspecific(Context::gThreadTLSKey); 102 rsAssert(tls); 103 tls->mScript = NULL; 104} 105 106uint32_t ScriptC::run(Context *rsc, uint32_t launchIndex) 107{ 108 if (mProgram.mRoot == NULL) { 109 rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script"); 110 return 0; 111 } 112 113 if (mEnviroment.mFragmentStore.get()) { 114 rsc->setFragmentStore(mEnviroment.mFragmentStore.get()); 115 } 116 if (mEnviroment.mFragment.get()) { 117 rsc->setFragment(mEnviroment.mFragment.get()); 118 } 119 if (mEnviroment.mVertex.get()) { 120 rsc->setVertex(mEnviroment.mVertex.get()); 121 } 122 if (mEnviroment.mRaster.get()) { 123 rsc->setRaster(mEnviroment.mRaster.get()); 124 } 125 126 if (launchIndex == 0) { 127 mEnviroment.mStartTimeMillis 128 = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC)); 129 } 130 setupScript(); 131 132 uint32_t ret = 0; 133 setTLS(); 134 //LOGE("ScriptC::run %p", mProgram.mRoot); 135 ret = mProgram.mRoot(); 136 clearTLS(); 137 //LOGE("ScriptC::run ret %i", ret); 138 return ret; 139} 140 141void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len) 142{ 143 //LOGE("rsi_ScriptInvoke %i", slot); 144 if ((slot >= mEnviroment.mInvokeFunctionCount) || 145 (mEnviroment.mInvokeFunctions[slot] == NULL)) { 146 rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script"); 147 return; 148 } 149 setupScript(); 150 setTLS(); 151 152 const uint32_t * dPtr = (const uint32_t *)data; 153 switch(len) { 154 case 0: 155 mEnviroment.mInvokeFunctions[slot](); 156 break; 157 case 4: 158 ((void (*)(uint32_t)) 159 mEnviroment.mInvokeFunctions[slot])(dPtr[0]); 160 break; 161 case 8: 162 ((void (*)(uint32_t, uint32_t)) 163 mEnviroment.mInvokeFunctions[slot])(dPtr[0], dPtr[1]); 164 break; 165 case 12: 166 ((void (*)(uint32_t, uint32_t, uint32_t)) 167 mEnviroment.mInvokeFunctions[slot])(dPtr[0], dPtr[1], dPtr[2]); 168 break; 169 case 16: 170 ((void (*)(uint32_t, uint32_t, uint32_t, uint32_t)) 171 mEnviroment.mInvokeFunctions[slot])(dPtr[0], dPtr[1], dPtr[2], dPtr[3]); 172 break; 173 case 20: 174 ((void (*)(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)) 175 mEnviroment.mInvokeFunctions[slot])(dPtr[0], dPtr[1], dPtr[2], dPtr[3], dPtr[4]); 176 break; 177 } 178 clearTLS(); 179} 180 181ScriptCState::ScriptCState() 182{ 183 mScript = NULL; 184 clear(); 185} 186 187ScriptCState::~ScriptCState() 188{ 189 delete mScript; 190 mScript = NULL; 191} 192 193void ScriptCState::clear() 194{ 195 for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) { 196 mConstantBufferTypes[ct].clear(); 197 mSlotWritable[ct] = false; 198 } 199 200 delete mScript; 201 mScript = new ScriptC(NULL); 202} 203 204static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name) 205{ 206 const ScriptCState::SymbolTable_t *sym; 207 sym = ScriptCState::lookupSymbol(name); 208 if (sym) { 209 return sym->mPtr; 210 } 211 sym = ScriptCState::lookupSymbolCL(name); 212 if (sym) { 213 return sym->mPtr; 214 } 215 sym = ScriptCState::lookupSymbolGL(name); 216 if (sym) { 217 return sym->mPtr; 218 } 219 LOGE("ScriptC sym lookup failed for %s", name); 220 return NULL; 221} 222 223void ScriptCState::runCompiler(Context *rsc, ScriptC *s) 224{ 225 LOGE("ScriptCState::runCompiler "); 226 227 s->mBccScript = bccCreateScript(); 228 bccScriptBitcode(s->mBccScript, s->mEnviroment.mScriptText, s->mEnviroment.mScriptTextLength); 229 bccRegisterSymbolCallback(s->mBccScript, symbolLookup, NULL); 230 bccCompileScript(s->mBccScript); 231 bccGetScriptLabel(s->mBccScript, "root", (BCCvoid**) &s->mProgram.mRoot); 232 bccGetScriptLabel(s->mBccScript, "init", (BCCvoid**) &s->mProgram.mInit); 233 LOGE("root %p, init %p", s->mProgram.mRoot, s->mProgram.mInit); 234 235 if (s->mProgram.mInit) { 236 s->mProgram.mInit(); 237 } 238 239 s->mEnviroment.mInvokeFunctions = (Script::InvokeFunc_t *)calloc(100, sizeof(void *)); 240 BCCchar **labels = new char*[100]; 241 bccGetFunctions(s->mBccScript, (BCCsizei *)&s->mEnviroment.mInvokeFunctionCount, 242 100, (BCCchar **)labels); 243 //LOGE("func count %i", s->mEnviroment.mInvokeFunctionCount); 244 for (uint32_t i=0; i < s->mEnviroment.mInvokeFunctionCount; i++) { 245 BCCsizei length; 246 bccGetFunctionBinary(s->mBccScript, labels[i], (BCCvoid **)&(s->mEnviroment.mInvokeFunctions[i]), &length); 247 //LOGE("func %i %p", i, s->mEnviroment.mInvokeFunctions[i]); 248 } 249 250 s->mEnviroment.mFieldAddress = (void **)calloc(100, sizeof(void *)); 251 bccGetExportVars(s->mBccScript, (BCCsizei *)&s->mEnviroment.mFieldCount, 252 100, s->mEnviroment.mFieldAddress); 253 //LOGE("var count %i", s->mEnviroment.mFieldCount); 254 for (uint32_t i=0; i < s->mEnviroment.mFieldCount; i++) { 255 //LOGE("var %i %p", i, s->mEnviroment.mFieldAddress[i]); 256 } 257 258 s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment()); 259 s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex()); 260 s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore()); 261 s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster()); 262 263 if (s->mProgram.mRoot) { 264 const static int pragmaMax = 16; 265 BCCsizei pragmaCount; 266 BCCchar * str[pragmaMax]; 267 bccGetPragmas(s->mBccScript, &pragmaCount, pragmaMax, &str[0]); 268 269 for (int ct=0; ct < pragmaCount; ct+=2) { 270 //LOGE("pragme %s %s", str[ct], str[ct+1]); 271 if (!strcmp(str[ct], "version")) { 272 continue; 273 } 274 275 if (!strcmp(str[ct], "stateVertex")) { 276 if (!strcmp(str[ct+1], "default")) { 277 continue; 278 } 279 if (!strcmp(str[ct+1], "parent")) { 280 s->mEnviroment.mVertex.clear(); 281 continue; 282 } 283 LOGE("Unreconized value %s passed to stateVertex", str[ct+1]); 284 } 285 286 if (!strcmp(str[ct], "stateRaster")) { 287 if (!strcmp(str[ct+1], "default")) { 288 continue; 289 } 290 if (!strcmp(str[ct+1], "parent")) { 291 s->mEnviroment.mRaster.clear(); 292 continue; 293 } 294 LOGE("Unreconized value %s passed to stateRaster", str[ct+1]); 295 } 296 297 if (!strcmp(str[ct], "stateFragment")) { 298 if (!strcmp(str[ct+1], "default")) { 299 continue; 300 } 301 if (!strcmp(str[ct+1], "parent")) { 302 s->mEnviroment.mFragment.clear(); 303 continue; 304 } 305 LOGE("Unreconized value %s passed to stateFragment", str[ct+1]); 306 } 307 308 if (!strcmp(str[ct], "stateStore")) { 309 if (!strcmp(str[ct+1], "default")) { 310 continue; 311 } 312 if (!strcmp(str[ct+1], "parent")) { 313 s->mEnviroment.mFragmentStore.clear(); 314 continue; 315 } 316 LOGE("Unreconized value %s passed to stateStore", str[ct+1]); 317 } 318 319 } 320 321 322 } else { 323 // Deal with an error. 324 } 325} 326 327 328 329namespace android { 330namespace renderscript { 331 332void rsi_ScriptCBegin(Context * rsc) 333{ 334 ScriptCState *ss = &rsc->mScriptC; 335 ss->clear(); 336} 337 338void rsi_ScriptCSetScript(Context * rsc, void *vp) 339{ 340 rsAssert(0); 341 //ScriptCState *ss = &rsc->mScriptC; 342 //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp); 343} 344 345void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len) 346{ 347 ScriptCState *ss = &rsc->mScriptC; 348 349 char *t = (char *)malloc(len + 1); 350 memcpy(t, text, len); 351 t[len] = 0; 352 ss->mScript->mEnviroment.mScriptText = t; 353 ss->mScript->mEnviroment.mScriptTextLength = len; 354} 355 356 357RsScript rsi_ScriptCCreate(Context * rsc) 358{ 359 ScriptCState *ss = &rsc->mScriptC; 360 361 ScriptC *s = ss->mScript; 362 ss->mScript = NULL; 363 364 ss->runCompiler(rsc, s); 365 s->incUserRef(); 366 s->setContext(rsc); 367 for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) { 368 s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get()); 369 s->mSlotWritable[ct] = ss->mSlotWritable[ct]; 370 } 371 372 ss->clear(); 373 return s; 374} 375 376} 377} 378 379 380