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