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 #include "rsCpuCore.h" 18 #include "rsCpuScript.h" 19 20 #ifdef RS_COMPATIBILITY_LIB 21 #include <set> 22 #include <string> 23 #include <dlfcn.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <sys/stat.h> 28 #include <unistd.h> 29 #else 30 #include <bcc/BCCContext.h> 31 #include <bcc/Config/Config.h> 32 #include <bcc/Renderscript/RSCompilerDriver.h> 33 #include <bcc/Renderscript/RSExecutable.h> 34 #include <bcc/Renderscript/RSInfo.h> 35 #include <bcinfo/MetadataExtractor.h> 36 #include <cutils/properties.h> 37 38 #include <sys/types.h> 39 #include <sys/wait.h> 40 #include <unistd.h> 41 42 #include <string> 43 #include <vector> 44 #endif 45 46 namespace { 47 #ifdef RS_COMPATIBILITY_LIB 48 49 // Create a len length string containing random characters from [A-Za-z0-9]. 50 static std::string getRandomString(size_t len) { 51 char buf[len + 1]; 52 for (size_t i = 0; i < len; i++) { 53 uint32_t r = arc4random() & 0xffff; 54 r %= 62; 55 if (r < 26) { 56 // lowercase 57 buf[i] = 'a' + r; 58 } else if (r < 52) { 59 // uppercase 60 buf[i] = 'A' + (r - 26); 61 } else { 62 // Use a number 63 buf[i] = '0' + (r - 52); 64 } 65 } 66 buf[len] = '\0'; 67 return std::string(buf); 68 } 69 70 // Check if a path exists and attempt to create it if it doesn't. 71 static bool ensureCacheDirExists(const char *path) { 72 if (access(path, R_OK | W_OK | X_OK) == 0) { 73 // Done if we can rwx the directory 74 return true; 75 } 76 if (mkdir(path, 0700) == 0) { 77 return true; 78 } 79 return false; 80 } 81 82 // Attempt to load the shared library from origName, but then fall back to 83 // creating the symlinked shared library if necessary (to ensure instancing). 84 // This function returns the dlopen()-ed handle if successful. 85 static void *loadSOHelper(const char *origName, const char *cacheDir, 86 const char *resName) { 87 // Keep track of which .so libraries have been loaded. Once a library is 88 // in the set (per-process granularity), we must instead make a symlink to 89 // the original shared object (randomly named .so file) and load that one 90 // instead. If we don't do this, we end up aliasing global data between 91 // the various Script instances (which are supposed to be completely 92 // independent). 93 static std::set<std::string> LoadedLibraries; 94 95 void *loaded = NULL; 96 97 // Skip everything if we don't even have the original library available. 98 if (access(origName, F_OK) != 0) { 99 return NULL; 100 } 101 102 // Common path is that we have not loaded this Script/library before. 103 if (LoadedLibraries.find(origName) == LoadedLibraries.end()) { 104 loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL); 105 if (loaded) { 106 LoadedLibraries.insert(origName); 107 } 108 return loaded; 109 } 110 111 std::string newName(cacheDir); 112 newName.append("/com.android.renderscript.cache/"); 113 114 if (!ensureCacheDirExists(newName.c_str())) { 115 ALOGE("Could not verify or create cache dir: %s", cacheDir); 116 return NULL; 117 } 118 119 // Construct an appropriately randomized filename for the symlink. 120 newName.append("librs."); 121 newName.append(resName); 122 newName.append("#"); 123 newName.append(getRandomString(6)); // 62^6 potential filename variants. 124 newName.append(".so"); 125 126 int r = symlink(origName, newName.c_str()); 127 if (r != 0) { 128 ALOGE("Could not create symlink %s -> %s", newName.c_str(), origName); 129 return NULL; 130 } 131 loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL); 132 r = unlink(newName.c_str()); 133 if (r != 0) { 134 ALOGE("Could not unlink symlink %s", newName.c_str()); 135 } 136 if (loaded) { 137 LoadedLibraries.insert(newName.c_str()); 138 } 139 140 return loaded; 141 } 142 143 // Load the shared library referred to by cacheDir and resName. If we have 144 // already loaded this library, we instead create a new symlink (in the 145 // cache dir) and then load that. We then immediately destroy the symlink. 146 // This is required behavior to implement script instancing for the support 147 // library, since shared objects are loaded and de-duped by name only. 148 static void *loadSharedLibrary(const char *cacheDir, const char *resName) { 149 void *loaded = NULL; 150 //arc4random_stir(); 151 #ifndef RS_SERVER 152 std::string scriptSOName(cacheDir); 153 size_t cutPos = scriptSOName.rfind("cache"); 154 if (cutPos != std::string::npos) { 155 scriptSOName.erase(cutPos); 156 } else { 157 ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir); 158 } 159 scriptSOName.append("/lib/librs."); 160 #else 161 std::string scriptSOName("lib"); 162 #endif 163 scriptSOName.append(resName); 164 scriptSOName.append(".so"); 165 166 // We should check if we can load the library from the standard app 167 // location for shared libraries first. 168 loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName); 169 170 if (loaded == NULL) { 171 ALOGE("Unable to open shared library (%s): %s", 172 scriptSOName.c_str(), dlerror()); 173 174 // One final attempt to find the library in "/system/lib". 175 // We do this to allow bundled applications to use the compatibility 176 // library fallback path. Those applications don't have a private 177 // library path, so they need to install to the system directly. 178 // Note that this is really just a testing path. 179 android::String8 scriptSONameSystem("/system/lib/librs."); 180 scriptSONameSystem.append(resName); 181 scriptSONameSystem.append(".so"); 182 loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir, 183 resName); 184 if (loaded == NULL) { 185 ALOGE("Unable to open system shared library (%s): %s", 186 scriptSONameSystem.c_str(), dlerror()); 187 } 188 } 189 190 return loaded; 191 } 192 193 #else // RS_COMPATIBILITY_LIB is not defined 194 195 static bool is_force_recompile() { 196 #ifdef RS_SERVER 197 return false; 198 #else 199 char buf[PROPERTY_VALUE_MAX]; 200 201 // Re-compile if floating point precision has been overridden. 202 property_get("debug.rs.precision", buf, ""); 203 if (buf[0] != '\0') { 204 return true; 205 } 206 207 // Re-compile if debug.rs.forcerecompile is set. 208 property_get("debug.rs.forcerecompile", buf, "0"); 209 if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) { 210 return true; 211 } else { 212 return false; 213 } 214 #endif // RS_SERVER 215 } 216 217 const static char *BCC_EXE_PATH = "/system/bin/bcc"; 218 219 static void setCompileArguments(std::vector<const char*>* args, const android::String8& bcFileName, 220 const char* cacheDir, const char* resName, const char* core_lib, 221 bool useRSDebugContext, const char* bccPluginName) { 222 rsAssert(cacheDir && resName && core_lib); 223 args->push_back(BCC_EXE_PATH); 224 args->push_back("-o"); 225 args->push_back(resName); 226 args->push_back("-output_path"); 227 args->push_back(cacheDir); 228 args->push_back("-bclib"); 229 args->push_back(core_lib); 230 args->push_back("-mtriple"); 231 args->push_back(DEFAULT_TARGET_TRIPLE_STRING); 232 233 // Execute the bcc compiler. 234 if (useRSDebugContext) { 235 args->push_back("-rs-debug-ctx"); 236 } else { 237 // Only load additional libraries for compiles that don't use 238 // the debug context. 239 if (bccPluginName && strlen(bccPluginName) > 0) { 240 args->push_back("-load"); 241 args->push_back(bccPluginName); 242 } 243 } 244 245 args->push_back(bcFileName.string()); 246 args->push_back(NULL); 247 } 248 249 static bool compileBitcode(const android::String8& bcFileName, 250 const char *bitcode, 251 size_t bitcodeSize, 252 const char** compileArguments, 253 const std::string& compileCommandLine) { 254 rsAssert(bitcode && bitcodeSize); 255 256 FILE *bcfile = fopen(bcFileName.string(), "w"); 257 if (!bcfile) { 258 ALOGE("Could not write to %s", bcFileName.string()); 259 return false; 260 } 261 size_t nwritten = fwrite(bitcode, 1, bitcodeSize, bcfile); 262 fclose(bcfile); 263 if (nwritten != bitcodeSize) { 264 ALOGE("Could not write %zu bytes to %s", bitcodeSize, 265 bcFileName.string()); 266 return false; 267 } 268 269 pid_t pid = fork(); 270 271 switch (pid) { 272 case -1: { // Error occurred (we attempt no recovery) 273 ALOGE("Couldn't fork for bcc compiler execution"); 274 return false; 275 } 276 case 0: { // Child process 277 ALOGV("Invoking BCC with: %s", compileCommandLine.c_str()); 278 execv(BCC_EXE_PATH, (char* const*)compileArguments); 279 280 ALOGE("execv() failed: %s", strerror(errno)); 281 abort(); 282 return false; 283 } 284 default: { // Parent process (actual driver) 285 // Wait on child process to finish compiling the source. 286 int status = 0; 287 pid_t w = waitpid(pid, &status, 0); 288 if (w == -1) { 289 ALOGE("Could not wait for bcc compiler"); 290 return false; 291 } 292 293 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 294 return true; 295 } 296 297 ALOGE("bcc compiler terminated unexpectedly"); 298 return false; 299 } 300 } 301 } 302 303 #endif // !defined(RS_COMPATIBILITY_LIB) 304 } // namespace 305 306 namespace android { 307 namespace renderscript { 308 309 #ifdef RS_COMPATIBILITY_LIB 310 #define MAXLINE 500 311 #define MAKE_STR_HELPER(S) #S 312 #define MAKE_STR(S) MAKE_STR_HELPER(S) 313 #define EXPORT_VAR_STR "exportVarCount: " 314 #define EXPORT_FUNC_STR "exportFuncCount: " 315 #define EXPORT_FOREACH_STR "exportForEachCount: " 316 #define OBJECT_SLOT_STR "objectSlotCount: " 317 318 // Copy up to a newline or size chars from str -> s, updating str 319 // Returns s when successful and NULL when '\0' is finally reached. 320 static char* strgets(char *s, int size, const char **ppstr) { 321 if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) { 322 return NULL; 323 } 324 325 int i; 326 for (i = 0; i < (size - 1); i++) { 327 s[i] = **ppstr; 328 (*ppstr)++; 329 if (s[i] == '\0') { 330 return s; 331 } else if (s[i] == '\n') { 332 s[i+1] = '\0'; 333 return s; 334 } 335 } 336 337 // size has been exceeded. 338 s[i] = '\0'; 339 340 return s; 341 } 342 #endif 343 344 RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) { 345 mCtx = ctx; 346 mScript = s; 347 348 #ifdef RS_COMPATIBILITY_LIB 349 mScriptSO = NULL; 350 mInvokeFunctions = NULL; 351 mForEachFunctions = NULL; 352 mFieldAddress = NULL; 353 mFieldIsObject = NULL; 354 mForEachSignatures = NULL; 355 #else 356 mCompilerContext = NULL; 357 mCompilerDriver = NULL; 358 mExecutable = NULL; 359 #endif 360 361 362 mRoot = NULL; 363 mRootExpand = NULL; 364 mInit = NULL; 365 mFreeChildren = NULL; 366 367 368 mBoundAllocs = NULL; 369 mIntrinsicData = NULL; 370 mIsThreadable = true; 371 } 372 373 374 bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir, 375 uint8_t const *bitcode, size_t bitcodeSize, 376 uint32_t flags, char const *bccPluginName) { 377 //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc); 378 //ALOGE("rsdScriptInit %p %p", rsc, script); 379 380 mCtx->lockMutex(); 381 #ifndef RS_COMPATIBILITY_LIB 382 bool useRSDebugContext = false; 383 384 mCompilerContext = NULL; 385 mCompilerDriver = NULL; 386 mExecutable = NULL; 387 388 mCompilerContext = new bcc::BCCContext(); 389 if (mCompilerContext == NULL) { 390 ALOGE("bcc: FAILS to create compiler context (out of memory)"); 391 mCtx->unlockMutex(); 392 return false; 393 } 394 395 mCompilerDriver = new bcc::RSCompilerDriver(); 396 if (mCompilerDriver == NULL) { 397 ALOGE("bcc: FAILS to create compiler driver (out of memory)"); 398 mCtx->unlockMutex(); 399 return false; 400 } 401 402 // Configure symbol resolvers (via compiler-rt and the RS runtime). 403 mRSRuntime.setLookupFunction(lookupRuntimeStub); 404 mRSRuntime.setContext(this); 405 mResolver.chainResolver(mCompilerRuntime); 406 mResolver.chainResolver(mRSRuntime); 407 408 // Run any compiler setup functions we have been provided with. 409 RSSetupCompilerCallback setupCompilerCallback = 410 mCtx->getSetupCompilerCallback(); 411 if (setupCompilerCallback != NULL) { 412 setupCompilerCallback(mCompilerDriver); 413 } 414 415 bcinfo::MetadataExtractor bitcodeMetadata((const char *) bitcode, bitcodeSize); 416 if (!bitcodeMetadata.extract()) { 417 ALOGE("Could not extract metadata from bitcode"); 418 mCtx->unlockMutex(); 419 return false; 420 } 421 422 const char* core_lib = findCoreLib(bitcodeMetadata, (const char*)bitcode, bitcodeSize); 423 424 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) { 425 mCompilerDriver->setDebugContext(true); 426 useRSDebugContext = true; 427 } 428 429 android::String8 bcFileName(cacheDir); 430 bcFileName.append("/"); 431 bcFileName.append(resName); 432 bcFileName.append(".bc"); 433 434 std::vector<const char*> compileArguments; 435 setCompileArguments(&compileArguments, bcFileName, cacheDir, resName, core_lib, 436 useRSDebugContext, bccPluginName); 437 // The last argument of compileArguments ia a NULL, so remove 1 from the size. 438 std::string compileCommandLine = 439 bcc::getCommandLine(compileArguments.size() - 1, compileArguments.data()); 440 441 if (!is_force_recompile()) { 442 // Load the compiled script that's in the cache, if any. 443 mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode, 444 bitcodeSize, compileCommandLine.c_str(), 445 mResolver); 446 } 447 448 // If we can't, it's either not there or out of date. We compile the bit code and try loading 449 // again. 450 if (mExecutable == NULL) { 451 if (!compileBitcode(bcFileName, (const char*)bitcode, bitcodeSize, compileArguments.data(), 452 compileCommandLine)) { 453 ALOGE("bcc: FAILS to compile '%s'", resName); 454 mCtx->unlockMutex(); 455 return false; 456 } 457 mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode, 458 bitcodeSize, compileCommandLine.c_str(), 459 mResolver); 460 if (mExecutable == NULL) { 461 ALOGE("bcc: FAILS to load freshly compiled executable for '%s'", resName); 462 mCtx->unlockMutex(); 463 return false; 464 } 465 } 466 467 mExecutable->setThreadable(mIsThreadable); 468 if (!mExecutable->syncInfo()) { 469 ALOGW("bcc: FAILS to synchronize the RS info file to the disk"); 470 } 471 472 mRoot = reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root")); 473 mRootExpand = 474 reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root.expand")); 475 mInit = reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress("init")); 476 mFreeChildren = 477 reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress(".rs.dtor")); 478 479 480 if (bitcodeMetadata.getExportVarCount()) { 481 mBoundAllocs = new Allocation *[bitcodeMetadata.getExportVarCount()]; 482 memset(mBoundAllocs, 0, sizeof(void *) * bitcodeMetadata.getExportVarCount()); 483 } 484 485 for (size_t i = 0; i < bitcodeMetadata.getExportForEachSignatureCount(); i++) { 486 char* name = new char[strlen(bitcodeMetadata.getExportForEachNameList()[i]) + 1]; 487 mExportedForEachFuncList.push_back( 488 std::make_pair(name, bitcodeMetadata.getExportForEachSignatureList()[i])); 489 } 490 491 #else // RS_COMPATIBILITY_LIB is defined 492 493 mScriptSO = loadSharedLibrary(cacheDir, resName); 494 495 if (mScriptSO) { 496 char line[MAXLINE]; 497 mRoot = (RootFunc_t) dlsym(mScriptSO, "root"); 498 if (mRoot) { 499 //ALOGE("Found root(): %p", mRoot); 500 } 501 mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand"); 502 if (mRootExpand) { 503 //ALOGE("Found root.expand(): %p", mRootExpand); 504 } 505 mInit = (InvokeFunc_t) dlsym(mScriptSO, "init"); 506 if (mInit) { 507 //ALOGE("Found init(): %p", mInit); 508 } 509 mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor"); 510 if (mFreeChildren) { 511 //ALOGE("Found .rs.dtor(): %p", mFreeChildren); 512 } 513 514 const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info"); 515 if (rsInfo) { 516 //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo); 517 } 518 519 size_t varCount = 0; 520 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 521 goto error; 522 } 523 if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) { 524 ALOGE("Invalid export var count!: %s", line); 525 goto error; 526 } 527 528 mExportedVariableCount = varCount; 529 //ALOGE("varCount: %zu", varCount); 530 if (varCount > 0) { 531 // Start by creating/zeroing this member, since we don't want to 532 // accidentally clean up invalid pointers later (if we error out). 533 mFieldIsObject = new bool[varCount]; 534 if (mFieldIsObject == NULL) { 535 goto error; 536 } 537 memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject)); 538 mFieldAddress = new void*[varCount]; 539 if (mFieldAddress == NULL) { 540 goto error; 541 } 542 for (size_t i = 0; i < varCount; ++i) { 543 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 544 goto error; 545 } 546 char *c = strrchr(line, '\n'); 547 if (c) { 548 *c = '\0'; 549 } 550 mFieldAddress[i] = dlsym(mScriptSO, line); 551 if (mFieldAddress[i] == NULL) { 552 ALOGE("Failed to find variable address for %s: %s", 553 line, dlerror()); 554 // Not a critical error if we don't find a global variable. 555 } 556 else { 557 //ALOGE("Found variable %s at %p", line, 558 //mFieldAddress[i]); 559 } 560 } 561 } 562 563 size_t funcCount = 0; 564 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 565 goto error; 566 } 567 if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) { 568 ALOGE("Invalid export func count!: %s", line); 569 goto error; 570 } 571 572 mExportedFunctionCount = funcCount; 573 //ALOGE("funcCount: %zu", funcCount); 574 575 if (funcCount > 0) { 576 mInvokeFunctions = new InvokeFunc_t[funcCount]; 577 if (mInvokeFunctions == NULL) { 578 goto error; 579 } 580 for (size_t i = 0; i < funcCount; ++i) { 581 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 582 goto error; 583 } 584 char *c = strrchr(line, '\n'); 585 if (c) { 586 *c = '\0'; 587 } 588 589 mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line); 590 if (mInvokeFunctions[i] == NULL) { 591 ALOGE("Failed to get function address for %s(): %s", 592 line, dlerror()); 593 goto error; 594 } 595 else { 596 //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]); 597 } 598 } 599 } 600 601 size_t forEachCount = 0; 602 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 603 goto error; 604 } 605 if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) { 606 ALOGE("Invalid export forEach count!: %s", line); 607 goto error; 608 } 609 610 if (forEachCount > 0) { 611 612 mForEachSignatures = new uint32_t[forEachCount]; 613 if (mForEachSignatures == NULL) { 614 goto error; 615 } 616 mForEachFunctions = new ForEachFunc_t[forEachCount]; 617 if (mForEachFunctions == NULL) { 618 goto error; 619 } 620 for (size_t i = 0; i < forEachCount; ++i) { 621 unsigned int tmpSig = 0; 622 char tmpName[MAXLINE]; 623 624 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 625 goto error; 626 } 627 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s", 628 &tmpSig, tmpName) != 2) { 629 ALOGE("Invalid export forEach!: %s", line); 630 goto error; 631 } 632 633 // Lookup the expanded ForEach kernel. 634 strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName)); 635 mForEachSignatures[i] = tmpSig; 636 mForEachFunctions[i] = 637 (ForEachFunc_t) dlsym(mScriptSO, tmpName); 638 if (i != 0 && mForEachFunctions[i] == NULL) { 639 // Ignore missing root.expand functions. 640 // root() is always specified at location 0. 641 ALOGE("Failed to find forEach function address for %s: %s", 642 tmpName, dlerror()); 643 goto error; 644 } 645 else { 646 //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]); 647 } 648 } 649 } 650 651 size_t objectSlotCount = 0; 652 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 653 goto error; 654 } 655 if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) { 656 ALOGE("Invalid object slot count!: %s", line); 657 goto error; 658 } 659 660 if (objectSlotCount > 0) { 661 rsAssert(varCount > 0); 662 for (size_t i = 0; i < objectSlotCount; ++i) { 663 uint32_t varNum = 0; 664 if (strgets(line, MAXLINE, &rsInfo) == NULL) { 665 goto error; 666 } 667 if (sscanf(line, "%u", &varNum) != 1) { 668 ALOGE("Invalid object slot!: %s", line); 669 goto error; 670 } 671 672 if (varNum < varCount) { 673 mFieldIsObject[varNum] = true; 674 } 675 } 676 } 677 678 if (varCount > 0) { 679 mBoundAllocs = new Allocation *[varCount]; 680 memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs)); 681 } 682 683 if (mScriptSO == (void*)1) { 684 //rsdLookupRuntimeStub(script, "acos"); 685 } 686 } else { 687 goto error; 688 } 689 #endif 690 mCtx->unlockMutex(); 691 return true; 692 693 #ifdef RS_COMPATIBILITY_LIB 694 error: 695 696 mCtx->unlockMutex(); 697 delete[] mInvokeFunctions; 698 delete[] mForEachFunctions; 699 delete[] mFieldAddress; 700 delete[] mFieldIsObject; 701 delete[] mForEachSignatures; 702 delete[] mBoundAllocs; 703 if (mScriptSO) { 704 dlclose(mScriptSO); 705 } 706 return false; 707 #endif 708 } 709 710 #ifndef RS_COMPATIBILITY_LIB 711 712 #ifdef __LP64__ 713 #define SYSLIBPATH "/system/lib64" 714 #else 715 #define SYSLIBPATH "/system/lib" 716 #endif 717 718 const char* RsdCpuScriptImpl::findCoreLib(const bcinfo::MetadataExtractor& ME, const char* bitcode, 719 size_t bitcodeSize) { 720 const char* defaultLib = SYSLIBPATH"/libclcore.bc"; 721 722 // If we're debugging, use the debug library. 723 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) { 724 return SYSLIBPATH"/libclcore_debug.bc"; 725 } 726 727 // If a callback has been registered to specify a library, use that. 728 RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback(); 729 if (selectRTCallback != NULL) { 730 return selectRTCallback((const char*)bitcode, bitcodeSize); 731 } 732 733 // Check for a platform specific library 734 #if defined(ARCH_ARM_HAVE_NEON) && !defined(DISABLE_CLCORE_NEON) 735 enum bcinfo::RSFloatPrecision prec = ME.getRSFloatPrecision(); 736 if (prec == bcinfo::RS_FP_Relaxed) { 737 // NEON-capable ARMv7a devices can use an accelerated math library 738 // for all reduced precision scripts. 739 // ARMv8 does not use NEON, as ASIMD can be used with all precision 740 // levels. 741 return SYSLIBPATH"/libclcore_neon.bc"; 742 } else { 743 return defaultLib; 744 } 745 #elif defined(__i386__) || defined(__x86_64__) 746 // x86 devices will use an optimized library. 747 return SYSLIBPATH"/libclcore_x86.bc"; 748 #else 749 return defaultLib; 750 #endif 751 } 752 753 #endif 754 755 void RsdCpuScriptImpl::populateScript(Script *script) { 756 #ifndef RS_COMPATIBILITY_LIB 757 // Copy info over to runtime 758 script->mHal.info.exportedFunctionCount = mExecutable->getExportFuncAddrs().size(); 759 script->mHal.info.exportedVariableCount = mExecutable->getExportVarAddrs().size(); 760 script->mHal.info.exportedForeachFuncList = &mExportedForEachFuncList[0]; 761 script->mHal.info.exportedPragmaCount = mExecutable->getPragmaKeys().size(); 762 script->mHal.info.exportedPragmaKeyList = 763 const_cast<const char**>(mExecutable->getPragmaKeys().array()); 764 script->mHal.info.exportedPragmaValueList = 765 const_cast<const char**>(mExecutable->getPragmaValues().array()); 766 767 if (mRootExpand) { 768 script->mHal.info.root = mRootExpand; 769 } else { 770 script->mHal.info.root = mRoot; 771 } 772 #else 773 // Copy info over to runtime 774 script->mHal.info.exportedFunctionCount = mExportedFunctionCount; 775 script->mHal.info.exportedVariableCount = mExportedVariableCount; 776 script->mHal.info.exportedPragmaCount = 0; 777 script->mHal.info.exportedPragmaKeyList = 0; 778 script->mHal.info.exportedPragmaValueList = 0; 779 780 // Bug, need to stash in metadata 781 if (mRootExpand) { 782 script->mHal.info.root = mRootExpand; 783 } else { 784 script->mHal.info.root = mRoot; 785 } 786 #endif 787 } 788 789 790 typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t); 791 792 void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation * ain, Allocation * aout, 793 const void * usr, uint32_t usrLen, 794 const RsScriptCall *sc, 795 MTLaunchStruct *mtls) { 796 797 memset(mtls, 0, sizeof(MTLaunchStruct)); 798 799 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface 800 if (ain && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) { 801 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null in allocations"); 802 return; 803 } 804 if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) { 805 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null out allocations"); 806 return; 807 } 808 809 if (ain != NULL) { 810 const Type *inType = ain->getType(); 811 812 mtls->fep.dimX = inType->getDimX(); 813 mtls->fep.dimY = inType->getDimY(); 814 mtls->fep.dimZ = inType->getDimZ(); 815 816 } else if (aout != NULL) { 817 const Type *outType = aout->getType(); 818 819 mtls->fep.dimX = outType->getDimX(); 820 mtls->fep.dimY = outType->getDimY(); 821 mtls->fep.dimZ = outType->getDimZ(); 822 823 } else { 824 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations"); 825 return; 826 } 827 828 if (ain != NULL && aout != NULL) { 829 if (!ain->hasSameDims(aout)) { 830 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, 831 "Failed to launch kernel; dimensions of input and output allocations do not match."); 832 833 return; 834 } 835 } 836 837 if (!sc || (sc->xEnd == 0)) { 838 mtls->xEnd = mtls->fep.dimX; 839 } else { 840 rsAssert(sc->xStart < mtls->fep.dimX); 841 rsAssert(sc->xEnd <= mtls->fep.dimX); 842 rsAssert(sc->xStart < sc->xEnd); 843 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart); 844 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd); 845 if (mtls->xStart >= mtls->xEnd) return; 846 } 847 848 if (!sc || (sc->yEnd == 0)) { 849 mtls->yEnd = mtls->fep.dimY; 850 } else { 851 rsAssert(sc->yStart < mtls->fep.dimY); 852 rsAssert(sc->yEnd <= mtls->fep.dimY); 853 rsAssert(sc->yStart < sc->yEnd); 854 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart); 855 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd); 856 if (mtls->yStart >= mtls->yEnd) return; 857 } 858 859 if (!sc || (sc->zEnd == 0)) { 860 mtls->zEnd = mtls->fep.dimZ; 861 } else { 862 rsAssert(sc->zStart < mtls->fep.dimZ); 863 rsAssert(sc->zEnd <= mtls->fep.dimZ); 864 rsAssert(sc->zStart < sc->zEnd); 865 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart); 866 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd); 867 if (mtls->zStart >= mtls->zEnd) return; 868 } 869 870 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd); 871 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd); 872 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd); 873 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd); 874 875 rsAssert(!ain || (ain->getType()->getDimZ() == 0)); 876 877 mtls->rsc = mCtx; 878 mtls->ain = ain; 879 mtls->aout = aout; 880 mtls->fep.usr = usr; 881 mtls->fep.usrLen = usrLen; 882 mtls->mSliceSize = 1; 883 mtls->mSliceNum = 0; 884 885 mtls->fep.ptrIn = NULL; 886 mtls->fep.eStrideIn = 0; 887 mtls->isThreadable = mIsThreadable; 888 889 if (ain) { 890 mtls->fep.ptrIn = (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr; 891 mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes(); 892 mtls->fep.yStrideIn = ain->mHal.drvState.lod[0].stride; 893 } 894 895 mtls->fep.ptrOut = NULL; 896 mtls->fep.eStrideOut = 0; 897 if (aout) { 898 mtls->fep.ptrOut = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr; 899 mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes(); 900 mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride; 901 } 902 } 903 904 void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation ** ains, uint32_t inLen, 905 Allocation * aout, 906 const void * usr, uint32_t usrLen, 907 const RsScriptCall *sc, 908 MTLaunchStruct *mtls) { 909 910 memset(mtls, 0, sizeof(MTLaunchStruct)); 911 912 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface 913 if (ains != NULL) { 914 for (int index = inLen; --index >= 0;) { 915 const Allocation* ain = ains[index]; 916 917 if (ain != NULL && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) { 918 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null in allocations"); 919 return; 920 } 921 } 922 } 923 924 if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) { 925 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null out allocations"); 926 return; 927 } 928 929 if (ains != NULL) { 930 const Allocation *ain0 = ains[0]; 931 const Type *inType = ain0->getType(); 932 933 mtls->fep.dimX = inType->getDimX(); 934 mtls->fep.dimY = inType->getDimY(); 935 mtls->fep.dimZ = inType->getDimZ(); 936 937 for (int Index = inLen; --Index >= 1;) { 938 if (!ain0->hasSameDims(ains[Index])) { 939 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, 940 "Failed to launch kernel; dimensions of input and output allocations do not match."); 941 942 return; 943 } 944 } 945 946 } else if (aout != NULL) { 947 const Type *outType = aout->getType(); 948 949 mtls->fep.dimX = outType->getDimX(); 950 mtls->fep.dimY = outType->getDimY(); 951 mtls->fep.dimZ = outType->getDimZ(); 952 953 } else { 954 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations"); 955 return; 956 } 957 958 if (ains != NULL && aout != NULL) { 959 if (!ains[0]->hasSameDims(aout)) { 960 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, 961 "Failed to launch kernel; dimensions of input and output allocations do not match."); 962 963 return; 964 } 965 } 966 967 if (!sc || (sc->xEnd == 0)) { 968 mtls->xEnd = mtls->fep.dimX; 969 } else { 970 rsAssert(sc->xStart < mtls->fep.dimX); 971 rsAssert(sc->xEnd <= mtls->fep.dimX); 972 rsAssert(sc->xStart < sc->xEnd); 973 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart); 974 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd); 975 if (mtls->xStart >= mtls->xEnd) return; 976 } 977 978 if (!sc || (sc->yEnd == 0)) { 979 mtls->yEnd = mtls->fep.dimY; 980 } else { 981 rsAssert(sc->yStart < mtls->fep.dimY); 982 rsAssert(sc->yEnd <= mtls->fep.dimY); 983 rsAssert(sc->yStart < sc->yEnd); 984 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart); 985 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd); 986 if (mtls->yStart >= mtls->yEnd) return; 987 } 988 989 if (!sc || (sc->zEnd == 0)) { 990 mtls->zEnd = mtls->fep.dimZ; 991 } else { 992 rsAssert(sc->zStart < mtls->fep.dimZ); 993 rsAssert(sc->zEnd <= mtls->fep.dimZ); 994 rsAssert(sc->zStart < sc->zEnd); 995 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart); 996 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd); 997 if (mtls->zStart >= mtls->zEnd) return; 998 } 999 1000 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd); 1001 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd); 1002 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd); 1003 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd); 1004 1005 rsAssert(!ains || (ains[0]->getType()->getDimZ() == 0)); 1006 1007 mtls->rsc = mCtx; 1008 mtls->ains = ains; 1009 mtls->aout = aout; 1010 mtls->fep.usr = usr; 1011 mtls->fep.usrLen = usrLen; 1012 mtls->mSliceSize = 1; 1013 mtls->mSliceNum = 0; 1014 1015 mtls->fep.ptrIns = NULL; 1016 mtls->fep.eStrideIn = 0; 1017 mtls->isThreadable = mIsThreadable; 1018 1019 if (ains) { 1020 mtls->fep.ptrIns = new const uint8_t*[inLen]; 1021 mtls->fep.inStrides = new StridePair[inLen]; 1022 1023 for (int index = inLen; --index >= 0;) { 1024 const Allocation *ain = ains[index]; 1025 1026 mtls->fep.ptrIns[index] = 1027 (const uint8_t*)ain->mHal.drvState.lod[0].mallocPtr; 1028 1029 mtls->fep.inStrides[index].eStride = 1030 ain->getType()->getElementSizeBytes(); 1031 mtls->fep.inStrides[index].yStride = 1032 ain->mHal.drvState.lod[0].stride; 1033 } 1034 } 1035 1036 mtls->fep.ptrOut = NULL; 1037 mtls->fep.eStrideOut = 0; 1038 if (aout) { 1039 mtls->fep.ptrOut = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr; 1040 mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes(); 1041 mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride; 1042 } 1043 } 1044 1045 1046 void RsdCpuScriptImpl::invokeForEach(uint32_t slot, 1047 const Allocation * ain, 1048 Allocation * aout, 1049 const void * usr, 1050 uint32_t usrLen, 1051 const RsScriptCall *sc) { 1052 1053 MTLaunchStruct mtls; 1054 forEachMtlsSetup(ain, aout, usr, usrLen, sc, &mtls); 1055 forEachKernelSetup(slot, &mtls); 1056 1057 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 1058 mCtx->launchThreads(ain, aout, sc, &mtls); 1059 mCtx->setTLS(oldTLS); 1060 } 1061 1062 void RsdCpuScriptImpl::invokeForEachMulti(uint32_t slot, 1063 const Allocation ** ains, 1064 uint32_t inLen, 1065 Allocation * aout, 1066 const void * usr, 1067 uint32_t usrLen, 1068 const RsScriptCall *sc) { 1069 1070 MTLaunchStruct mtls; 1071 1072 forEachMtlsSetup(ains, inLen, aout, usr, usrLen, sc, &mtls); 1073 forEachKernelSetup(slot, &mtls); 1074 1075 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 1076 mCtx->launchThreads(ains, inLen, aout, sc, &mtls); 1077 mCtx->setTLS(oldTLS); 1078 } 1079 1080 void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) { 1081 mtls->script = this; 1082 mtls->fep.slot = slot; 1083 #ifndef RS_COMPATIBILITY_LIB 1084 rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size()); 1085 mtls->kernel = reinterpret_cast<ForEachFunc_t>( 1086 mExecutable->getExportForeachFuncAddrs()[slot]); 1087 rsAssert(mtls->kernel != NULL); 1088 mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second; 1089 #else 1090 mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]); 1091 rsAssert(mtls->kernel != NULL); 1092 mtls->sig = mForEachSignatures[slot]; 1093 #endif 1094 } 1095 1096 int RsdCpuScriptImpl::invokeRoot() { 1097 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 1098 int ret = mRoot(); 1099 mCtx->setTLS(oldTLS); 1100 return ret; 1101 } 1102 1103 void RsdCpuScriptImpl::invokeInit() { 1104 if (mInit) { 1105 mInit(); 1106 } 1107 } 1108 1109 void RsdCpuScriptImpl::invokeFreeChildren() { 1110 if (mFreeChildren) { 1111 mFreeChildren(); 1112 } 1113 } 1114 1115 void RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params, 1116 size_t paramLength) { 1117 //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength); 1118 1119 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this); 1120 reinterpret_cast<void (*)(const void *, uint32_t)>( 1121 #ifndef RS_COMPATIBILITY_LIB 1122 mExecutable->getExportFuncAddrs()[slot])(params, paramLength); 1123 #else 1124 mInvokeFunctions[slot])(params, paramLength); 1125 #endif 1126 mCtx->setTLS(oldTLS); 1127 } 1128 1129 void RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) { 1130 //rsAssert(!script->mFieldIsObject[slot]); 1131 //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength); 1132 1133 //if (mIntrinsicID) { 1134 //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength); 1135 //return; 1136 //} 1137 1138 #ifndef RS_COMPATIBILITY_LIB 1139 int32_t *destPtr = reinterpret_cast<int32_t *>( 1140 mExecutable->getExportVarAddrs()[slot]); 1141 #else 1142 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 1143 #endif 1144 if (!destPtr) { 1145 //ALOGV("Calling setVar on slot = %i which is null", slot); 1146 return; 1147 } 1148 1149 memcpy(destPtr, data, dataLength); 1150 } 1151 1152 void RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) { 1153 //rsAssert(!script->mFieldIsObject[slot]); 1154 //ALOGE("getGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength); 1155 1156 #ifndef RS_COMPATIBILITY_LIB 1157 int32_t *srcPtr = reinterpret_cast<int32_t *>( 1158 mExecutable->getExportVarAddrs()[slot]); 1159 #else 1160 int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 1161 #endif 1162 if (!srcPtr) { 1163 //ALOGV("Calling setVar on slot = %i which is null", slot); 1164 return; 1165 } 1166 memcpy(data, srcPtr, dataLength); 1167 } 1168 1169 1170 void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength, 1171 const Element *elem, 1172 const uint32_t *dims, size_t dimLength) { 1173 1174 #ifndef RS_COMPATIBILITY_LIB 1175 int32_t *destPtr = reinterpret_cast<int32_t *>( 1176 mExecutable->getExportVarAddrs()[slot]); 1177 #else 1178 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 1179 #endif 1180 if (!destPtr) { 1181 //ALOGV("Calling setVar on slot = %i which is null", slot); 1182 return; 1183 } 1184 1185 // We want to look at dimension in terms of integer components, 1186 // but dimLength is given in terms of bytes. 1187 dimLength /= sizeof(int); 1188 1189 // Only a single dimension is currently supported. 1190 rsAssert(dimLength == 1); 1191 if (dimLength == 1) { 1192 // First do the increment loop. 1193 size_t stride = elem->getSizeBytes(); 1194 const char *cVal = reinterpret_cast<const char *>(data); 1195 for (uint32_t i = 0; i < dims[0]; i++) { 1196 elem->incRefs(cVal); 1197 cVal += stride; 1198 } 1199 1200 // Decrement loop comes after (to prevent race conditions). 1201 char *oldVal = reinterpret_cast<char *>(destPtr); 1202 for (uint32_t i = 0; i < dims[0]; i++) { 1203 elem->decRefs(oldVal); 1204 oldVal += stride; 1205 } 1206 } 1207 1208 memcpy(destPtr, data, dataLength); 1209 } 1210 1211 void RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) { 1212 1213 //rsAssert(!script->mFieldIsObject[slot]); 1214 //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data); 1215 1216 #ifndef RS_COMPATIBILITY_LIB 1217 int32_t *destPtr = reinterpret_cast<int32_t *>( 1218 mExecutable->getExportVarAddrs()[slot]); 1219 #else 1220 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 1221 #endif 1222 if (!destPtr) { 1223 //ALOGV("Calling setVar on slot = %i which is null", slot); 1224 return; 1225 } 1226 1227 void *ptr = NULL; 1228 mBoundAllocs[slot] = data; 1229 if(data) { 1230 ptr = data->mHal.drvState.lod[0].mallocPtr; 1231 } 1232 memcpy(destPtr, &ptr, sizeof(void *)); 1233 } 1234 1235 void RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) { 1236 1237 //rsAssert(script->mFieldIsObject[slot]); 1238 //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data); 1239 1240 #ifndef RS_COMPATIBILITY_LIB 1241 int32_t *destPtr = reinterpret_cast<int32_t *>( 1242 mExecutable->getExportVarAddrs()[slot]); 1243 #else 1244 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]); 1245 #endif 1246 1247 if (!destPtr) { 1248 //ALOGV("Calling setVar on slot = %i which is null", slot); 1249 return; 1250 } 1251 1252 rsrSetObject(mCtx->getContext(), (rs_object_base *)destPtr, data); 1253 } 1254 1255 RsdCpuScriptImpl::~RsdCpuScriptImpl() { 1256 #ifndef RS_COMPATIBILITY_LIB 1257 if (mExecutable) { 1258 Vector<void *>::const_iterator var_addr_iter = 1259 mExecutable->getExportVarAddrs().begin(); 1260 Vector<void *>::const_iterator var_addr_end = 1261 mExecutable->getExportVarAddrs().end(); 1262 1263 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter = 1264 mExecutable->getInfo().getObjectSlots().begin(); 1265 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end = 1266 mExecutable->getInfo().getObjectSlots().end(); 1267 1268 while ((var_addr_iter != var_addr_end) && 1269 (is_object_iter != is_object_end)) { 1270 // The field address can be NULL if the script-side has optimized 1271 // the corresponding global variable away. 1272 rs_object_base *obj_addr = 1273 reinterpret_cast<rs_object_base *>(*var_addr_iter); 1274 if (*is_object_iter) { 1275 if (*var_addr_iter != NULL && mCtx->getContext() != NULL) { 1276 rsrClearObject(mCtx->getContext(), obj_addr); 1277 } 1278 } 1279 var_addr_iter++; 1280 is_object_iter++; 1281 } 1282 } 1283 1284 if (mCompilerContext) { 1285 delete mCompilerContext; 1286 } 1287 if (mCompilerDriver) { 1288 delete mCompilerDriver; 1289 } 1290 if (mExecutable) { 1291 delete mExecutable; 1292 } 1293 if (mBoundAllocs) { 1294 delete[] mBoundAllocs; 1295 } 1296 1297 for (size_t i = 0; i < mExportedForEachFuncList.size(); i++) { 1298 delete[] mExportedForEachFuncList[i].first; 1299 } 1300 #else 1301 if (mFieldIsObject) { 1302 for (size_t i = 0; i < mExportedVariableCount; ++i) { 1303 if (mFieldIsObject[i]) { 1304 if (mFieldAddress[i] != NULL) { 1305 rs_object_base *obj_addr = 1306 reinterpret_cast<rs_object_base *>(mFieldAddress[i]); 1307 rsrClearObject(mCtx->getContext(), obj_addr); 1308 } 1309 } 1310 } 1311 } 1312 1313 if (mInvokeFunctions) delete[] mInvokeFunctions; 1314 if (mForEachFunctions) delete[] mForEachFunctions; 1315 if (mFieldAddress) delete[] mFieldAddress; 1316 if (mFieldIsObject) delete[] mFieldIsObject; 1317 if (mForEachSignatures) delete[] mForEachSignatures; 1318 if (mBoundAllocs) delete[] mBoundAllocs; 1319 if (mScriptSO) { 1320 dlclose(mScriptSO); 1321 } 1322 #endif 1323 } 1324 1325 Allocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const { 1326 if (!ptr) { 1327 return NULL; 1328 } 1329 1330 for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) { 1331 Allocation *a = mBoundAllocs[ct]; 1332 if (!a) continue; 1333 if (a->mHal.drvState.lod[0].mallocPtr == ptr) { 1334 return a; 1335 } 1336 } 1337 ALOGE("rsGetAllocation, failed to find %p", ptr); 1338 return NULL; 1339 } 1340 1341 void RsdCpuScriptImpl::preLaunch(uint32_t slot, const Allocation * ain, 1342 Allocation * aout, const void * usr, 1343 uint32_t usrLen, const RsScriptCall *sc) 1344 { 1345 } 1346 1347 void RsdCpuScriptImpl::postLaunch(uint32_t slot, const Allocation * ain, 1348 Allocation * aout, const void * usr, 1349 uint32_t usrLen, const RsScriptCall *sc) 1350 { 1351 } 1352 1353 1354 } 1355 } 1356