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