rsCpuScript.cpp revision 1d476620399d54774e4fd386c1d23cc583d49522
1/* 2 * Copyright (C) 2011-2012 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 18 19#include "rsCpuCore.h" 20 21#include "rsCpuScript.h" 22//#include "rsdRuntime.h" 23//#include "rsdAllocation.h" 24//#include "rsCpuIntrinsics.h" 25 26#ifndef RS_SERVER 27#include "utils/Vector.h" 28#include "utils/Timers.h" 29#include "utils/StopWatch.h" 30#endif 31 32#ifdef RS_COMPATIBILITY_LIB 33 #include <dlfcn.h> 34 #include <stdio.h> 35 #include <string.h> 36#else 37 #include <bcc/BCCContext.h> 38 #include <bcc/Renderscript/RSCompilerDriver.h> 39 #include <bcc/Renderscript/RSExecutable.h> 40 #include <bcc/Renderscript/RSInfo.h> 41#endif 42 43namespace android { 44namespace renderscript { 45 46 47#ifdef RS_COMPATIBILITY_LIB 48#define MAXLINE 500 49#define MAKE_STR_HELPER(S) #S 50#define MAKE_STR(S) MAKE_STR_HELPER(S) 51#define EXPORT_VAR_STR "exportVarCount: " 52#define EXPORT_VAR_STR_LEN strlen(EXPORT_VAR_STR) 53#define EXPORT_FUNC_STR "exportFuncCount: " 54#define EXPORT_FUNC_STR_LEN strlen(EXPORT_FUNC_STR) 55#define EXPORT_FOREACH_STR "exportForEachCount: " 56#define EXPORT_FOREACH_STR_LEN strlen(EXPORT_FOREACH_STR) 57#define OBJECT_SLOT_STR "objectSlotCount: " 58#define OBJECT_SLOT_STR_LEN strlen(OBJECT_SLOT_STR) 59 60// Copy up to a newline or size chars from str -> s, updating str 61// Returns s when successful and NULL when '\0' is finally reached. 62static char* strgets(char *s, int size, const char **ppstr) { 63 if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) { 64 return NULL; 65 } 66 67 int i; 68 for (i = 0; i < (size - 1); i++) { 69 s[i] = **ppstr; 70 (*ppstr)++; 71 if (s[i] == '\0') { 72 return s; 73 } else if (s[i] == '\n') { 74 s[i+1] = '\0'; 75 return s; 76 } 77 } 78 79 // size has been exceeded. 80 s[i] = '\0'; 81 82 return s; 83} 84#endif 85 86RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) { 87 mCtx = ctx; 88 mScript = s; 89 90#ifdef RS_COMPATIBILITY_LIB 91 mScriptSO = NULL; 92 mInvokeFunctions = NULL; 93 mForEachFunctions = NULL; 94 mFieldAddress = NULL; 95 mFieldIsObject = NULL; 96 mForEachSignatures = NULL; 97#else 98 mCompilerContext = NULL; 99 mCompilerDriver = NULL; 100 mExecutable = NULL; 101#endif 102 103 mRoot = NULL; 104 mRootExpand = NULL; 105 mInit = NULL; 106 mFreeChildren = NULL; 107 108 109 mBoundAllocs = NULL; 110 mIntrinsicData = NULL; 111 mIsThreadable = true; 112} 113 114 115bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir, 116 uint8_t const *bitcode, size_t bitcodeSize, 117 uint32_t flags) { 118 //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc); 119 //ALOGE("rsdScriptInit %p %p", rsc, script); 120 121 mCtx->lockMutex(); 122 123#ifndef RS_COMPATIBILITY_LIB 124 bcc::RSExecutable *exec; 125 126 mCompilerContext = NULL; 127 mCompilerDriver = NULL; 128 mExecutable = NULL; 129 130 mCompilerContext = new bcc::BCCContext(); 131 if (mCompilerContext == NULL) { 132 ALOGE("bcc: FAILS to create compiler context (out of memory)"); 133 mCtx->unlockMutex(); 134 return false; 135 } 136 137 mCompilerDriver = new bcc::RSCompilerDriver(); 138 if (mCompilerDriver == NULL) { 139 ALOGE("bcc: FAILS to create compiler driver (out of memory)"); 140 mCtx->unlockMutex(); 141 return false; 142 } 143 144 mCompilerDriver->setRSRuntimeLookupFunction(lookupRuntimeStub); 145 mCompilerDriver->setRSRuntimeLookupContext(this); 146 147 const char *core_lib = NULL; 148 RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback(); 149 if (selectRTCallback != NULL) { 150 core_lib = selectRTCallback((const char *)bitcode, bitcodeSize); 151 } 152 exec = mCompilerDriver->build(*mCompilerContext, cacheDir, resName, 153 (const char *)bitcode, bitcodeSize, core_lib, 154 mCtx->getLinkRuntimeCallback()); 155 156 if (exec == NULL) { 157 ALOGE("bcc: FAILS to prepare executable for '%s'", resName); 158 mCtx->unlockMutex(); 159 return false; 160 } 161 162 mExecutable = exec; 163 164 exec->setThreadable(mIsThreadable); 165 if (!exec->syncInfo()) { 166 ALOGW("bcc: FAILS to synchronize the RS info file to the disk"); 167 } 168 169 mRoot = reinterpret_cast<int (*)()>(exec->getSymbolAddress("root")); 170 mRootExpand = 171 reinterpret_cast<int (*)()>(exec->getSymbolAddress("root.expand")); 172 mInit = reinterpret_cast<void (*)()>(exec->getSymbolAddress("init")); 173 mFreeChildren = 174 reinterpret_cast<void (*)()>(exec->getSymbolAddress(".rs.dtor")); 175 176 177 const bcc::RSInfo *info = &mExecutable->getInfo(); 178 if (info->getExportVarNames().size()) { 179 mBoundAllocs = new Allocation *[info->getExportVarNames().size()]; 180 memset(mBoundAllocs, 0, sizeof(void *) * info->getExportVarNames().size()); 181 } 182 183#else 184 185#ifndef RS_SERVER 186 String8 scriptSOName(cacheDir); 187 scriptSOName = scriptSOName.getPathDir(); 188 scriptSOName.appendPath("lib"); 189 scriptSOName.append("/librs."); 190#else 191 String8 scriptSOName("lib"); 192#endif 193 scriptSOName.append(resName); 194 scriptSOName.append(".so"); 195 196 //script->mHal.drv = drv; 197 198 //ALOGV("Opening up shared object: %s", scriptSOName.string()); 199 mScriptSO = dlopen(scriptSOName.string(), RTLD_NOW | RTLD_LOCAL); 200 if (mScriptSO == NULL) { 201 ALOGE("Unable to open shared library (%s): %s", 202 scriptSOName.string(), dlerror()); 203 204 // One final attempt to find the library in "/system/lib". 205 // We do this to allow bundled applications to use the compatibility 206 // library fallback path. Those applications don't have a private 207 // library path, so they need to install to the system directly. 208 String8 scriptSONameSystem("/system/lib/librs."); 209 scriptSONameSystem.append(resName); 210 scriptSONameSystem.append(".so"); 211 mScriptSO = dlopen(scriptSONameSystem.string(), RTLD_NOW | RTLD_LOCAL); 212 if (mScriptSO == NULL) { 213 ALOGE("Unable to open system shared library (%s): %s", 214 scriptSONameSystem.string(), dlerror()); 215 goto error; 216 } 217 } 218 219 if (mScriptSO) { 220 char line[MAXLINE]; 221 mRoot = (RootFunc_t) dlsym(mScriptSO, "root"); 222 if (mRoot) { 223 //ALOGE("Found root(): %p", mRoot); 224 } 225 mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand"); 226 if (mRootExpand) { 227 //ALOGE("Found root.expand(): %p", mRootExpand); 228 } 229 mInit = (InvokeFunc_t) dlsym(mScriptSO, "init"); 230 if (mInit) { 231 //ALOGE("Found init(): %p", mInit); 232 } 233 mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor"); 234 if (mFreeChildren) { 235 //ALOGE("Found .rs.dtor(): %p", mFreeChildren); 236 } 237 238 const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info"); 239 if (rsInfo) { 240 //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo); 241 } 242 243 size_t varCount = 0; 244 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 245 goto error; 246 } 247 if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) { 248 ALOGE("Invalid export var count!: %s", line); 249 goto error; 250 } 251 252 mExportedVariableCount = varCount; 253 //ALOGE("varCount: %zu", varCount); 254 if (varCount > 0) { 255 // Start by creating/zeroing this member, since we don't want to 256 // accidentally clean up invalid pointers later (if we error out). 257 mFieldIsObject = new bool[varCount]; 258 if (mFieldIsObject == NULL) { 259 goto error; 260 } 261 memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject)); 262 mFieldAddress = new void*[varCount]; 263 if (mFieldAddress == NULL) { 264 goto error; 265 } 266 for (size_t i = 0; i < varCount; ++i) { 267 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 268 goto error; 269 } 270 char *c = strrchr(line, '\n'); 271 if (c) { 272 *c = '\0'; 273 } 274 mFieldAddress[i] = dlsym(mScriptSO, line); 275 if (mFieldAddress[i] == NULL) { 276 ALOGE("Failed to find variable address for %s: %s", 277 line, dlerror()); 278 // Not a critical error if we don't find a global variable. 279 } 280 else { 281 //ALOGE("Found variable %s at %p", line, 282 //mFieldAddress[i]); 283 } 284 } 285 } 286 287 size_t funcCount = 0; 288 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 289 goto error; 290 } 291 if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) { 292 ALOGE("Invalid export func count!: %s", line); 293 goto error; 294 } 295 296 mExportedFunctionCount = funcCount; 297 //ALOGE("funcCount: %zu", funcCount); 298 299 if (funcCount > 0) { 300 mInvokeFunctions = new InvokeFunc_t[funcCount]; 301 if (mInvokeFunctions == NULL) { 302 goto error; 303 } 304 for (size_t i = 0; i < funcCount; ++i) { 305 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 306 goto error; 307 } 308 char *c = strrchr(line, '\n'); 309 if (c) { 310 *c = '\0'; 311 } 312 313 mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line); 314 if (mInvokeFunctions[i] == NULL) { 315 ALOGE("Failed to get function address for %s(): %s", 316 line, dlerror()); 317 goto error; 318 } 319 else { 320 //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]); 321 } 322 } 323 } 324 325 size_t forEachCount = 0; 326 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 327 goto error; 328 } 329 if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) { 330 ALOGE("Invalid export forEach count!: %s", line); 331 goto error; 332 } 333 334 if (forEachCount > 0) { 335 336 mForEachSignatures = new uint32_t[forEachCount]; 337 if (mForEachSignatures == NULL) { 338 goto error; 339 } 340 mForEachFunctions = new ForEachFunc_t[forEachCount]; 341 if (mForEachFunctions == NULL) { 342 goto error; 343 } 344 for (size_t i = 0; i < forEachCount; ++i) { 345 unsigned int tmpSig = 0; 346 char tmpName[MAXLINE]; 347 348 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 349 goto error; 350 } 351 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s", 352 &tmpSig, tmpName) != 2) { 353 ALOGE("Invalid export forEach!: %s", line); 354 goto error; 355 } 356 357 // Lookup the expanded ForEach kernel. 358 strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName)); 359 mForEachSignatures[i] = tmpSig; 360 mForEachFunctions[i] = 361 (ForEachFunc_t) dlsym(mScriptSO, tmpName); 362 if (mForEachFunctions[i] == NULL) { 363 ALOGE("Failed to find forEach function address for %s: %s", 364 tmpName, dlerror()); 365 // Ignore missing root.expand functions. 366 // root() is always specified at location 0. 367 if (i != 0) { 368 goto error; 369 } 370 } 371 else { 372 //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]); 373 } 374 } 375 } 376 377 size_t objectSlotCount = 0; 378 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 379 goto error; 380 } 381 if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) { 382 ALOGE("Invalid object slot count!: %s", line); 383 goto error; 384 } 385 386 if (objectSlotCount > 0) { 387 rsAssert(varCount > 0); 388 for (size_t i = 0; i < objectSlotCount; ++i) { 389 uint32_t varNum = 0; 390 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 391 goto error; 392 } 393 if (sscanf(line, "%u", &varNum) != 1) { 394 ALOGE("Invalid object slot!: %s", line); 395 goto error; 396 } 397 398 if (varNum < varCount) { 399 mFieldIsObject[varNum] = true; 400 } 401 } 402 } 403 404 if (varCount > 0) { 405 mBoundAllocs = new Allocation *[varCount]; 406 memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs)); 407 } 408 409 if (mScriptSO == (void*)1) { 410 //rsdLookupRuntimeStub(script, "acos"); 411 } 412 } 413#endif 414 415 mCtx->unlockMutex(); 416 return true; 417 418#ifdef RS_COMPATIBILITY_LIB 419error: 420 421 mCtx->unlockMutex(); 422 delete[] mInvokeFunctions; 423 delete[] mForEachFunctions; 424 delete[] mFieldAddress; 425 delete[] mFieldIsObject; 426 delete[] mForEachSignatures; 427 delete[] mBoundAllocs; 428 if (mScriptSO) { 429 dlclose(mScriptSO); 430 } 431 return false; 432#endif 433} 434 435void RsdCpuScriptImpl::populateScript(Script *script) { 436#ifndef RS_COMPATIBILITY_LIB 437 const bcc::RSInfo *info = &mExecutable->getInfo(); 438 439 // Copy info over to runtime 440 script->mHal.info.exportedFunctionCount = info->getExportFuncNames().size(); 441 script->mHal.info.exportedVariableCount = info->getExportVarNames().size(); 442 script->mHal.info.exportedPragmaCount = info->getPragmas().size(); 443 script->mHal.info.exportedPragmaKeyList = 444 const_cast<const char**>(mExecutable->getPragmaKeys().array()); 445 script->mHal.info.exportedPragmaValueList = 446 const_cast<const char**>(mExecutable->getPragmaValues().array()); 447 448 if (mRootExpand) { 449 script->mHal.info.root = mRootExpand; 450 } else { 451 script->mHal.info.root = mRoot; 452 } 453#else 454 // Copy info over to runtime 455 script->mHal.info.exportedFunctionCount = mExportedFunctionCount; 456 script->mHal.info.exportedVariableCount = mExportedVariableCount; 457 script->mHal.info.exportedPragmaCount = 0; 458 script->mHal.info.exportedPragmaKeyList = 0; 459 script->mHal.info.exportedPragmaValueList = 0; 460 461 // Bug, need to stash in metadata 462 if (mRootExpand) { 463 script->mHal.info.root = mRootExpand; 464 } else { 465 script->mHal.info.root = mRoot; 466 } 467#endif 468} 469 470 471typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t); 472 473void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation * ain, Allocation * aout, 474 const void * usr, uint32_t usrLen, 475 const RsScriptCall *sc, 476 MTLaunchStruct *mtls) { 477 478 memset(mtls, 0, sizeof(MTLaunchStruct)); 479 480 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface 481 if (ain && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) { 482 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations"); 483 return; 484 } 485 if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) { 486 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations"); 487 return; 488 } 489 490 if (ain) { 491 mtls->fep.dimX = ain->getType()->getDimX(); 492 mtls->fep.dimY = ain->getType()->getDimY(); 493 mtls->fep.dimZ = ain->getType()->getDimZ(); 494 //mtls->dimArray = ain->getType()->getDimArray(); 495 } else if (aout) { 496 mtls->fep.dimX = aout->getType()->getDimX(); 497 mtls->fep.dimY = aout->getType()->getDimY(); 498 mtls->fep.dimZ = aout->getType()->getDimZ(); 499 //mtls->dimArray = aout->getType()->getDimArray(); 500 } else { 501 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations"); 502 return; 503 } 504 505 if (!sc || (sc->xEnd == 0)) { 506 mtls->xEnd = mtls->fep.dimX; 507 } else { 508 rsAssert(sc->xStart < mtls->fep.dimX); 509 rsAssert(sc->xEnd <= mtls->fep.dimX); 510 rsAssert(sc->xStart < sc->xEnd); 511 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart); 512 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd); 513 if (mtls->xStart >= mtls->xEnd) return; 514 } 515 516 if (!sc || (sc->yEnd == 0)) { 517 mtls->yEnd = mtls->fep.dimY; 518 } else { 519 rsAssert(sc->yStart < mtls->fep.dimY); 520 rsAssert(sc->yEnd <= mtls->fep.dimY); 521 rsAssert(sc->yStart < sc->yEnd); 522 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart); 523 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd); 524 if (mtls->yStart >= mtls->yEnd) return; 525 } 526 527 if (!sc || (sc->zEnd == 0)) { 528 mtls->zEnd = mtls->fep.dimZ; 529 } else { 530 rsAssert(sc->zStart < mtls->fep.dimZ); 531 rsAssert(sc->zEnd <= mtls->fep.dimZ); 532 rsAssert(sc->zStart < sc->zEnd); 533 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart); 534 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd); 535 if (mtls->zStart >= mtls->zEnd) return; 536 } 537 538 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd); 539 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd); 540 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd); 541 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd); 542 543 rsAssert(!ain || (ain->getType()->getDimZ() == 0)); 544 545 mtls->rsc = mCtx; 546 mtls->ain = ain; 547 mtls->aout = aout; 548 mtls->fep.usr = usr; 549 mtls->fep.usrLen = usrLen; 550 mtls->mSliceSize = 1; 551 mtls->mSliceNum = 0; 552 553 mtls->fep.ptrIn = NULL; 554 mtls->fep.eStrideIn = 0; 555 mtls->isThreadable = mIsThreadable; 556 557 if (ain) { 558 mtls->fep.ptrIn = (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr; 559 mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes(); 560 mtls->fep.yStrideIn = ain->mHal.drvState.lod[0].stride; 561 } 562 563 mtls->fep.ptrOut = NULL; 564 mtls->fep.eStrideOut = 0; 565 if (aout) { 566 mtls->fep.ptrOut = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr; 567 mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes(); 568 mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride; 569 } 570} 571 572 573void RsdCpuScriptImpl::invokeForEach(uint32_t slot, 574 const Allocation * ain, 575 Allocation * aout, 576 const void * usr, 577 uint32_t usrLen, 578 const RsScriptCall *sc) { 579 580 MTLaunchStruct mtls; 581 forEachMtlsSetup(ain, aout, usr, usrLen, sc, &mtls); 582 forEachKernelSetup(slot, &mtls); 583 584 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 585 mCtx->launchThreads(ain, aout, sc, &mtls); 586 mCtx->setTLS(oldTLS); 587} 588 589void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) { 590 mtls->script = this; 591 mtls->fep.slot = slot; 592#ifndef RS_COMPATIBILITY_LIB 593 rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size()); 594 mtls->kernel = reinterpret_cast<ForEachFunc_t>( 595 mExecutable->getExportForeachFuncAddrs()[slot]); 596 rsAssert(mtls->kernel != NULL); 597 mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second; 598#else 599 mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]); 600 rsAssert(mtls->kernel != NULL); 601 mtls->sig = mForEachSignatures[slot]; 602#endif 603} 604 605int RsdCpuScriptImpl::invokeRoot() { 606 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 607 int ret = mRoot(); 608 mCtx->setTLS(oldTLS); 609 return ret; 610} 611 612void RsdCpuScriptImpl::invokeInit() { 613 if (mInit) { 614 mInit(); 615 } 616} 617 618void RsdCpuScriptImpl::invokeFreeChildren() { 619 if (mFreeChildren) { 620 mFreeChildren(); 621 } 622} 623 624void RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params, 625 size_t paramLength) { 626 //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength); 627 628 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 629 reinterpret_cast<void (*)(const void *, uint32_t)>( 630#ifndef RS_COMPATIBILITY_LIB 631 mExecutable->getExportFuncAddrs()[slot])(params, paramLength); 632#else 633 mInvokeFunctions[slot])(params, paramLength); 634#endif 635 mCtx->setTLS(oldTLS); 636} 637 638void RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) { 639 //rsAssert(!script->mFieldIsObject[slot]); 640 //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength); 641 642 //if (mIntrinsicID) { 643 //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength); 644 //return; 645 //} 646 647#ifndef RS_COMPATIBILITY_LIB 648 int32_t *destPtr = reinterpret_cast<int32_t *>( 649 mExecutable->getExportVarAddrs()[slot]); 650#else 651 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 652#endif 653 if (!destPtr) { 654 //ALOGV("Calling setVar on slot = %i which is null", slot); 655 return; 656 } 657 658 memcpy(destPtr, data, dataLength); 659} 660 661void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength, 662 const Element *elem, 663 const size_t *dims, size_t dimLength) { 664 665#ifndef RS_COMPATIBILITY_LIB 666 int32_t *destPtr = reinterpret_cast<int32_t *>( 667 mExecutable->getExportVarAddrs()[slot]); 668#else 669 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 670#endif 671 if (!destPtr) { 672 //ALOGV("Calling setVar on slot = %i which is null", slot); 673 return; 674 } 675 676 // We want to look at dimension in terms of integer components, 677 // but dimLength is given in terms of bytes. 678 dimLength /= sizeof(int); 679 680 // Only a single dimension is currently supported. 681 rsAssert(dimLength == 1); 682 if (dimLength == 1) { 683 // First do the increment loop. 684 size_t stride = elem->getSizeBytes(); 685 const char *cVal = reinterpret_cast<const char *>(data); 686 for (size_t i = 0; i < dims[0]; i++) { 687 elem->incRefs(cVal); 688 cVal += stride; 689 } 690 691 // Decrement loop comes after (to prevent race conditions). 692 char *oldVal = reinterpret_cast<char *>(destPtr); 693 for (size_t i = 0; i < dims[0]; i++) { 694 elem->decRefs(oldVal); 695 oldVal += stride; 696 } 697 } 698 699 memcpy(destPtr, data, dataLength); 700} 701 702void RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) { 703 704 //rsAssert(!script->mFieldIsObject[slot]); 705 //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data); 706 707#ifndef RS_COMPATIBILITY_LIB 708 int32_t *destPtr = reinterpret_cast<int32_t *>( 709 mExecutable->getExportVarAddrs()[slot]); 710#else 711 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 712#endif 713 if (!destPtr) { 714 //ALOGV("Calling setVar on slot = %i which is null", slot); 715 return; 716 } 717 718 void *ptr = NULL; 719 mBoundAllocs[slot] = data; 720 if(data) { 721 ptr = data->mHal.drvState.lod[0].mallocPtr; 722 } 723 memcpy(destPtr, &ptr, sizeof(void *)); 724} 725 726void RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) { 727 728 //rsAssert(script->mFieldIsObject[slot]); 729 //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data); 730 731 //if (mIntrinsicID) { 732 //mIntrinsicFuncs.setVarObj(dc, script, drv->mIntrinsicData, slot, alloc); 733 //return; 734 //} 735 736#ifndef RS_COMPATIBILITY_LIB 737 int32_t *destPtr = reinterpret_cast<int32_t *>( 738 mExecutable->getExportVarAddrs()[slot]); 739#else 740 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 741#endif 742 if (!destPtr) { 743 //ALOGV("Calling setVar on slot = %i which is null", slot); 744 return; 745 } 746 747 rsrSetObject(mCtx->getContext(), (ObjectBase **)destPtr, data); 748} 749 750RsdCpuScriptImpl::~RsdCpuScriptImpl() { 751#ifndef RS_COMPATIBILITY_LIB 752 if (mExecutable) { 753 Vector<void *>::const_iterator var_addr_iter = 754 mExecutable->getExportVarAddrs().begin(); 755 Vector<void *>::const_iterator var_addr_end = 756 mExecutable->getExportVarAddrs().end(); 757 758 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter = 759 mExecutable->getInfo().getObjectSlots().begin(); 760 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end = 761 mExecutable->getInfo().getObjectSlots().end(); 762 763 while ((var_addr_iter != var_addr_end) && 764 (is_object_iter != is_object_end)) { 765 // The field address can be NULL if the script-side has optimized 766 // the corresponding global variable away. 767 ObjectBase **obj_addr = 768 reinterpret_cast<ObjectBase **>(*var_addr_iter); 769 if (*is_object_iter) { 770 if (*var_addr_iter != NULL) { 771 rsrClearObject(mCtx->getContext(), obj_addr); 772 } 773 } 774 var_addr_iter++; 775 is_object_iter++; 776 } 777 } 778 779 if (mCompilerContext) { 780 delete mCompilerContext; 781 } 782 if (mCompilerDriver) { 783 delete mCompilerDriver; 784 } 785 if (mExecutable) { 786 delete mExecutable; 787 } 788 if (mBoundAllocs) { 789 delete[] mBoundAllocs; 790 } 791#else 792 if (mFieldIsObject) { 793 for (size_t i = 0; i < mExportedVariableCount; ++i) { 794 if (mFieldIsObject[i]) { 795 if (mFieldAddress[i] != NULL) { 796 ObjectBase **obj_addr = 797 reinterpret_cast<ObjectBase **>(mFieldAddress[i]); 798 rsrClearObject(mCtx->getContext(), obj_addr); 799 } 800 } 801 } 802 } 803 804 if (mInvokeFunctions) delete[] mInvokeFunctions; 805 if (mForEachFunctions) delete[] mForEachFunctions; 806 if (mFieldAddress) delete[] mFieldAddress; 807 if (mFieldIsObject) delete[] mFieldIsObject; 808 if (mForEachSignatures) delete[] mForEachSignatures; 809 if (mBoundAllocs) delete[] mBoundAllocs; 810 if (mScriptSO) { 811 dlclose(mScriptSO); 812 } 813#endif 814} 815 816Allocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const { 817 if (!ptr) { 818 return NULL; 819 } 820 821 for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) { 822 Allocation *a = mBoundAllocs[ct]; 823 if (!a) continue; 824 if (a->mHal.drvState.lod[0].mallocPtr == ptr) { 825 return a; 826 } 827 } 828 ALOGE("rsGetAllocation, failed to find %p", ptr); 829 return NULL; 830} 831 832 833} 834} 835