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