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