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