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