rsdBcc.cpp revision 0db650c7aff639f24e9c6a651abd4539cb943609
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 "rsdCore.h" 18#include "rsdBcc.h" 19#include "rsdRuntime.h" 20#include "rsdAllocation.h" 21 22#include <bcinfo/MetadataExtractor.h> 23 24#include "rsContext.h" 25#include "rsElement.h" 26#include "rsScriptC.h" 27 28#include "utils/Timers.h" 29#include "utils/StopWatch.h" 30 31using namespace android; 32using namespace android::renderscript; 33 34struct DrvScript { 35 int (*mRoot)(); 36 int (*mRootExpand)(); 37 void (*mInit)(); 38 void (*mFreeChildren)(); 39 40 BCCScriptRef mBccScript; 41 42 bcinfo::MetadataExtractor *ME; 43 44 InvokeFunc_t *mInvokeFunctions; 45 ForEachFunc_t *mForEachFunctions; 46 void ** mFieldAddress; 47 bool * mFieldIsObject; 48 const uint32_t *mExportForEachSignatureList; 49 50 const uint8_t * mScriptText; 51 uint32_t mScriptTextLength; 52 Allocation **mBoundAllocs; 53}; 54 55typedef void (*outer_foreach_t)( 56 const android::renderscript::RsForEachStubParamStruct *, 57 uint32_t x1, uint32_t x2, 58 uint32_t instep, uint32_t outstep); 59 60static Script * setTLS(Script *sc) { 61 ScriptTLSStruct * tls = (ScriptTLSStruct *)pthread_getspecific(rsdgThreadTLSKey); 62 rsAssert(tls); 63 Script *old = tls->mScript; 64 tls->mScript = sc; 65 return old; 66} 67 68 69bool rsdScriptInit(const Context *rsc, 70 ScriptC *script, 71 char const *resName, 72 char const *cacheDir, 73 uint8_t const *bitcode, 74 size_t bitcodeSize, 75 uint32_t flags) { 76 //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc); 77 78 pthread_mutex_lock(&rsdgInitMutex); 79 80 size_t exportFuncCount = 0; 81 size_t exportVarCount = 0; 82 size_t objectSlotCount = 0; 83 size_t exportForEachSignatureCount = 0; 84 85 const char* coreLib = "/system/lib/libclcore.bc"; 86 bcinfo::RSFloatPrecision prec; 87 88 DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript)); 89 if (drv == NULL) { 90 goto error; 91 } 92 script->mHal.drv = drv; 93 94 drv->mBccScript = bccCreateScript(); 95 script->mHal.info.isThreadable = true; 96 drv->mScriptText = bitcode; 97 drv->mScriptTextLength = bitcodeSize; 98 99 100 drv->ME = new bcinfo::MetadataExtractor((const char*)drv->mScriptText, 101 drv->mScriptTextLength); 102 if (!drv->ME->extract()) { 103 ALOGE("bcinfo: failed to read script metadata"); 104 goto error; 105 } 106 107 //ALOGE("mBccScript %p", script->mBccScript); 108 109 if (bccRegisterSymbolCallback(drv->mBccScript, &rsdLookupRuntimeStub, script) != 0) { 110 ALOGE("bcc: FAILS to register symbol callback"); 111 goto error; 112 } 113 114 if (bccReadBC(drv->mBccScript, 115 resName, 116 (char const *)drv->mScriptText, 117 drv->mScriptTextLength, 0) != 0) { 118 ALOGE("bcc: FAILS to read bitcode"); 119 goto error; 120 } 121 122 // NEON-capable devices can use an accelerated math library for all 123 // reduced precision scripts. 124#if defined(ARCH_ARM_HAVE_NEON) 125 prec = drv->ME->getRSFloatPrecision(); 126 if (prec != bcinfo::RS_FP_Full) { 127 coreLib = "/system/lib/libclcore_neon.bc"; 128 } 129#endif 130 131 if (bccLinkFile(drv->mBccScript, coreLib, 0) != 0) { 132 ALOGE("bcc: FAILS to link bitcode"); 133 goto error; 134 } 135 136 if (bccPrepareExecutable(drv->mBccScript, cacheDir, resName, 0) != 0) { 137 ALOGE("bcc: FAILS to prepare executable"); 138 goto error; 139 } 140 141 drv->mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(drv->mBccScript, "root")); 142 drv->mRootExpand = reinterpret_cast<int (*)()>(bccGetFuncAddr(drv->mBccScript, "root.expand")); 143 drv->mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(drv->mBccScript, "init")); 144 drv->mFreeChildren = reinterpret_cast<void (*)()>(bccGetFuncAddr(drv->mBccScript, ".rs.dtor")); 145 146 exportFuncCount = drv->ME->getExportFuncCount(); 147 if (exportFuncCount > 0) { 148 drv->mInvokeFunctions = (InvokeFunc_t*) calloc(exportFuncCount, 149 sizeof(InvokeFunc_t)); 150 bccGetExportFuncList(drv->mBccScript, exportFuncCount, 151 (void **) drv->mInvokeFunctions); 152 } else { 153 drv->mInvokeFunctions = NULL; 154 } 155 156 exportVarCount = drv->ME->getExportVarCount(); 157 if (exportVarCount > 0) { 158 drv->mFieldAddress = (void **) calloc(exportVarCount, sizeof(void*)); 159 drv->mFieldIsObject = (bool *) calloc(exportVarCount, sizeof(bool)); 160 bccGetExportVarList(drv->mBccScript, exportVarCount, 161 (void **) drv->mFieldAddress); 162 } else { 163 drv->mFieldAddress = NULL; 164 drv->mFieldIsObject = NULL; 165 } 166 167 objectSlotCount = drv->ME->getObjectSlotCount(); 168 if (objectSlotCount > 0) { 169 const uint32_t *objectSlotList = drv->ME->getObjectSlotList(); 170 for (uint32_t ct=0; ct < objectSlotCount; ct++) { 171 drv->mFieldIsObject[objectSlotList[ct]] = true; 172 } 173 } 174 175 exportForEachSignatureCount = drv->ME->getExportForEachSignatureCount(); 176 drv->mExportForEachSignatureList = drv->ME->getExportForEachSignatureList(); 177 if (exportForEachSignatureCount > 0) { 178 drv->mForEachFunctions = 179 (ForEachFunc_t*) calloc(exportForEachSignatureCount, 180 sizeof(ForEachFunc_t)); 181 bccGetExportForEachList(drv->mBccScript, exportForEachSignatureCount, 182 (void **) drv->mForEachFunctions); 183 } else { 184 drv->mForEachFunctions = NULL; 185 } 186 187 // Copy info over to runtime 188 script->mHal.info.exportedFunctionCount = drv->ME->getExportFuncCount(); 189 script->mHal.info.exportedVariableCount = drv->ME->getExportVarCount(); 190 script->mHal.info.exportedPragmaCount = drv->ME->getPragmaCount(); 191 script->mHal.info.exportedPragmaKeyList = drv->ME->getPragmaKeyList(); 192 script->mHal.info.exportedPragmaValueList = drv->ME->getPragmaValueList(); 193 194 if (drv->mRootExpand) { 195 script->mHal.info.root = drv->mRootExpand; 196 } else { 197 script->mHal.info.root = drv->mRoot; 198 } 199 200 if (script->mHal.info.exportedVariableCount) { 201 drv->mBoundAllocs = new Allocation *[script->mHal.info.exportedVariableCount]; 202 memset(drv->mBoundAllocs, 0, sizeof(void *) * script->mHal.info.exportedVariableCount); 203 } 204 205 pthread_mutex_unlock(&rsdgInitMutex); 206 return true; 207 208error: 209 210 pthread_mutex_unlock(&rsdgInitMutex); 211 if (drv) { 212 if (drv->ME) { 213 delete drv->ME; 214 drv->ME = NULL; 215 } 216 delete[] drv->mBoundAllocs; 217 } 218 free(drv); 219 return false; 220 221} 222 223typedef struct { 224 Context *rsc; 225 Script *script; 226 ForEachFunc_t kernel; 227 uint32_t sig; 228 const Allocation * ain; 229 Allocation * aout; 230 const void * usr; 231 size_t usrLen; 232 233 uint32_t mSliceSize; 234 volatile int mSliceNum; 235 236 const uint8_t *ptrIn; 237 uint32_t eStrideIn; 238 uint8_t *ptrOut; 239 uint32_t eStrideOut; 240 241 uint32_t yStrideIn; 242 uint32_t yStrideOut; 243 244 uint32_t xStart; 245 uint32_t xEnd; 246 uint32_t yStart; 247 uint32_t yEnd; 248 uint32_t zStart; 249 uint32_t zEnd; 250 uint32_t arrayStart; 251 uint32_t arrayEnd; 252 253 uint32_t dimX; 254 uint32_t dimY; 255 uint32_t dimZ; 256 uint32_t dimArray; 257} MTLaunchStruct; 258typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t); 259 260static void wc_xy(void *usr, uint32_t idx) { 261 MTLaunchStruct *mtls = (MTLaunchStruct *)usr; 262 RsForEachStubParamStruct p; 263 memset(&p, 0, sizeof(p)); 264 p.usr = mtls->usr; 265 p.usr_len = mtls->usrLen; 266 RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv; 267 uint32_t sig = mtls->sig; 268 269 outer_foreach_t fn = (outer_foreach_t) mtls->kernel; 270 while (1) { 271 uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum); 272 uint32_t yStart = mtls->yStart + slice * mtls->mSliceSize; 273 uint32_t yEnd = yStart + mtls->mSliceSize; 274 yEnd = rsMin(yEnd, mtls->yEnd); 275 if (yEnd <= yStart) { 276 return; 277 } 278 279 //ALOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd); 280 //ALOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut); 281 for (p.y = yStart; p.y < yEnd; p.y++) { 282 p.out = mtls->ptrOut + (mtls->yStrideOut * p.y); 283 p.in = mtls->ptrIn + (mtls->yStrideIn * p.y); 284 fn(&p, mtls->xStart, mtls->xEnd, mtls->eStrideIn, mtls->eStrideOut); 285 } 286 } 287} 288 289static void wc_x(void *usr, uint32_t idx) { 290 MTLaunchStruct *mtls = (MTLaunchStruct *)usr; 291 RsForEachStubParamStruct p; 292 memset(&p, 0, sizeof(p)); 293 p.usr = mtls->usr; 294 p.usr_len = mtls->usrLen; 295 RsdHal * dc = (RsdHal *)mtls->rsc->mHal.drv; 296 uint32_t sig = mtls->sig; 297 298 outer_foreach_t fn = (outer_foreach_t) mtls->kernel; 299 while (1) { 300 uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum); 301 uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize; 302 uint32_t xEnd = xStart + mtls->mSliceSize; 303 xEnd = rsMin(xEnd, mtls->xEnd); 304 if (xEnd <= xStart) { 305 return; 306 } 307 308 //ALOGE("usr slice %i idx %i, x %i,%i", slice, idx, xStart, xEnd); 309 //ALOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut); 310 311 p.out = mtls->ptrOut + (mtls->eStrideOut * xStart); 312 p.in = mtls->ptrIn + (mtls->eStrideIn * xStart); 313 fn(&p, xStart, xEnd, mtls->eStrideIn, mtls->eStrideOut); 314 } 315} 316 317void rsdScriptInvokeForEach(const Context *rsc, 318 Script *s, 319 uint32_t slot, 320 const Allocation * ain, 321 Allocation * aout, 322 const void * usr, 323 uint32_t usrLen, 324 const RsScriptCall *sc) { 325 326 RsdHal * dc = (RsdHal *)rsc->mHal.drv; 327 328 MTLaunchStruct mtls; 329 memset(&mtls, 0, sizeof(mtls)); 330 331 DrvScript *drv = (DrvScript *)s->mHal.drv; 332 mtls.kernel = drv->mForEachFunctions[slot]; 333 rsAssert(mtls.kernel != NULL); 334 mtls.sig = 0x1f; // temp fix for old apps, full table in slang_rs_export_foreach.cpp 335 if (drv->mExportForEachSignatureList) { 336 mtls.sig = drv->mExportForEachSignatureList[slot]; 337 } 338 if (ain) { 339 mtls.dimX = ain->getType()->getDimX(); 340 mtls.dimY = ain->getType()->getDimY(); 341 mtls.dimZ = ain->getType()->getDimZ(); 342 //mtls.dimArray = ain->getType()->getDimArray(); 343 } else if (aout) { 344 mtls.dimX = aout->getType()->getDimX(); 345 mtls.dimY = aout->getType()->getDimY(); 346 mtls.dimZ = aout->getType()->getDimZ(); 347 //mtls.dimArray = aout->getType()->getDimArray(); 348 } else { 349 rsc->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations"); 350 return; 351 } 352 353 if (!sc || (sc->xEnd == 0)) { 354 mtls.xEnd = mtls.dimX; 355 } else { 356 rsAssert(sc->xStart < mtls.dimX); 357 rsAssert(sc->xEnd <= mtls.dimX); 358 rsAssert(sc->xStart < sc->xEnd); 359 mtls.xStart = rsMin(mtls.dimX, sc->xStart); 360 mtls.xEnd = rsMin(mtls.dimX, sc->xEnd); 361 if (mtls.xStart >= mtls.xEnd) return; 362 } 363 364 if (!sc || (sc->yEnd == 0)) { 365 mtls.yEnd = mtls.dimY; 366 } else { 367 rsAssert(sc->yStart < mtls.dimY); 368 rsAssert(sc->yEnd <= mtls.dimY); 369 rsAssert(sc->yStart < sc->yEnd); 370 mtls.yStart = rsMin(mtls.dimY, sc->yStart); 371 mtls.yEnd = rsMin(mtls.dimY, sc->yEnd); 372 if (mtls.yStart >= mtls.yEnd) return; 373 } 374 375 mtls.xEnd = rsMax((uint32_t)1, mtls.xEnd); 376 mtls.yEnd = rsMax((uint32_t)1, mtls.yEnd); 377 mtls.zEnd = rsMax((uint32_t)1, mtls.zEnd); 378 mtls.arrayEnd = rsMax((uint32_t)1, mtls.arrayEnd); 379 380 rsAssert(!ain || (ain->getType()->getDimZ() == 0)); 381 382 Context *mrsc = (Context *)rsc; 383 Script * oldTLS = setTLS(s); 384 385 mtls.rsc = mrsc; 386 mtls.ain = ain; 387 mtls.aout = aout; 388 mtls.script = s; 389 mtls.usr = usr; 390 mtls.usrLen = usrLen; 391 mtls.mSliceSize = 10; 392 mtls.mSliceNum = 0; 393 394 mtls.ptrIn = NULL; 395 mtls.eStrideIn = 0; 396 if (ain) { 397 DrvAllocation *aindrv = (DrvAllocation *)ain->mHal.drv; 398 mtls.ptrIn = (const uint8_t *)aindrv->lod[0].mallocPtr; 399 mtls.eStrideIn = ain->getType()->getElementSizeBytes(); 400 mtls.yStrideIn = aindrv->lod[0].stride; 401 } 402 403 mtls.ptrOut = NULL; 404 mtls.eStrideOut = 0; 405 if (aout) { 406 DrvAllocation *aoutdrv = (DrvAllocation *)aout->mHal.drv; 407 mtls.ptrOut = (uint8_t *)aoutdrv->lod[0].mallocPtr; 408 mtls.eStrideOut = aout->getType()->getElementSizeBytes(); 409 mtls.yStrideOut = aoutdrv->lod[0].stride; 410 } 411 412 if ((dc->mWorkers.mCount > 1) && s->mHal.info.isThreadable && !dc->mInForEach) { 413 dc->mInForEach = true; 414 if (mtls.dimY > 1) { 415 rsdLaunchThreads(mrsc, wc_xy, &mtls); 416 } else { 417 rsdLaunchThreads(mrsc, wc_x, &mtls); 418 } 419 dc->mInForEach = false; 420 421 //ALOGE("launch 1"); 422 } else { 423 RsForEachStubParamStruct p; 424 memset(&p, 0, sizeof(p)); 425 p.usr = mtls.usr; 426 p.usr_len = mtls.usrLen; 427 uint32_t sig = mtls.sig; 428 429 //ALOGE("launch 3"); 430 outer_foreach_t fn = (outer_foreach_t) mtls.kernel; 431 for (p.ar[0] = mtls.arrayStart; p.ar[0] < mtls.arrayEnd; p.ar[0]++) { 432 for (p.z = mtls.zStart; p.z < mtls.zEnd; p.z++) { 433 for (p.y = mtls.yStart; p.y < mtls.yEnd; p.y++) { 434 uint32_t offset = mtls.dimX * mtls.dimY * mtls.dimZ * p.ar[0] + 435 mtls.dimX * mtls.dimY * p.z + 436 mtls.dimX * p.y; 437 p.out = mtls.ptrOut + (mtls.eStrideOut * offset); 438 p.in = mtls.ptrIn + (mtls.eStrideIn * offset); 439 fn(&p, mtls.xStart, mtls.xEnd, mtls.eStrideIn, 440 mtls.eStrideOut); 441 } 442 } 443 } 444 } 445 446 setTLS(oldTLS); 447} 448 449 450int rsdScriptInvokeRoot(const Context *dc, Script *script) { 451 DrvScript *drv = (DrvScript *)script->mHal.drv; 452 453 Script * oldTLS = setTLS(script); 454 int ret = drv->mRoot(); 455 setTLS(oldTLS); 456 457 return ret; 458} 459 460void rsdScriptInvokeInit(const Context *dc, Script *script) { 461 DrvScript *drv = (DrvScript *)script->mHal.drv; 462 463 if (drv->mInit) { 464 drv->mInit(); 465 } 466} 467 468void rsdScriptInvokeFreeChildren(const Context *dc, Script *script) { 469 DrvScript *drv = (DrvScript *)script->mHal.drv; 470 471 if (drv->mFreeChildren) { 472 drv->mFreeChildren(); 473 } 474} 475 476void rsdScriptInvokeFunction(const Context *dc, Script *script, 477 uint32_t slot, 478 const void *params, 479 size_t paramLength) { 480 DrvScript *drv = (DrvScript *)script->mHal.drv; 481 //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength); 482 483 Script * oldTLS = setTLS(script); 484 ((void (*)(const void *, uint32_t)) 485 drv->mInvokeFunctions[slot])(params, paramLength); 486 setTLS(oldTLS); 487} 488 489void rsdScriptSetGlobalVar(const Context *dc, const Script *script, 490 uint32_t slot, void *data, size_t dataLength) { 491 DrvScript *drv = (DrvScript *)script->mHal.drv; 492 //rsAssert(!script->mFieldIsObject[slot]); 493 //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength); 494 495 int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot]; 496 if (!destPtr) { 497 //ALOGV("Calling setVar on slot = %i which is null", slot); 498 return; 499 } 500 501 memcpy(destPtr, data, dataLength); 502} 503 504void rsdScriptSetGlobalVarWithElemDims( 505 const android::renderscript::Context *dc, 506 const android::renderscript::Script *script, 507 uint32_t slot, void *data, size_t dataLength, 508 const android::renderscript::Element *elem, 509 const size_t *dims, size_t dimLength) { 510 DrvScript *drv = (DrvScript *)script->mHal.drv; 511 512 int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot]; 513 if (!destPtr) { 514 //ALOGV("Calling setVar on slot = %i which is null", slot); 515 return; 516 } 517 518 // We want to look at dimension in terms of integer components, 519 // but dimLength is given in terms of bytes. 520 dimLength /= sizeof(int); 521 522 // Only a single dimension is currently supported. 523 rsAssert(dimLength == 1); 524 if (dimLength == 1) { 525 // First do the increment loop. 526 size_t stride = elem->getSizeBytes(); 527 char *cVal = reinterpret_cast<char *>(data); 528 for (size_t i = 0; i < dims[0]; i++) { 529 elem->incRefs(cVal); 530 cVal += stride; 531 } 532 533 // Decrement loop comes after (to prevent race conditions). 534 char *oldVal = reinterpret_cast<char *>(destPtr); 535 for (size_t i = 0; i < dims[0]; i++) { 536 elem->decRefs(oldVal); 537 oldVal += stride; 538 } 539 } 540 541 memcpy(destPtr, data, dataLength); 542} 543 544void rsdScriptSetGlobalBind(const Context *dc, const Script *script, uint32_t slot, Allocation *data) { 545 DrvScript *drv = (DrvScript *)script->mHal.drv; 546 547 //rsAssert(!script->mFieldIsObject[slot]); 548 //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data); 549 550 int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot]; 551 if (!destPtr) { 552 //ALOGV("Calling setVar on slot = %i which is null", slot); 553 return; 554 } 555 556 void *ptr = NULL; 557 drv->mBoundAllocs[slot] = data; 558 if(data) { 559 DrvAllocation *allocDrv = (DrvAllocation *)data->mHal.drv; 560 ptr = allocDrv->lod[0].mallocPtr; 561 } 562 memcpy(destPtr, &ptr, sizeof(void *)); 563} 564 565void rsdScriptSetGlobalObj(const Context *dc, const Script *script, uint32_t slot, ObjectBase *data) { 566 DrvScript *drv = (DrvScript *)script->mHal.drv; 567 //rsAssert(script->mFieldIsObject[slot]); 568 //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data); 569 570 int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot]; 571 if (!destPtr) { 572 //ALOGV("Calling setVar on slot = %i which is null", slot); 573 return; 574 } 575 576 rsrSetObject(dc, script, (ObjectBase **)destPtr, data); 577} 578 579void rsdScriptDestroy(const Context *dc, Script *script) { 580 DrvScript *drv = (DrvScript *)script->mHal.drv; 581 582 if (drv->mFieldAddress) { 583 size_t exportVarCount = drv->ME->getExportVarCount(); 584 for (size_t ct = 0; ct < exportVarCount; ct++) { 585 if (drv->mFieldIsObject[ct]) { 586 // The field address can be NULL if the script-side has 587 // optimized the corresponding global variable away. 588 if (drv->mFieldAddress[ct]) { 589 rsrClearObject(dc, script, (ObjectBase **)drv->mFieldAddress[ct]); 590 } 591 } 592 } 593 free(drv->mFieldAddress); 594 drv->mFieldAddress = NULL; 595 free(drv->mFieldIsObject); 596 drv->mFieldIsObject = NULL; } 597 598 if (drv->mInvokeFunctions) { 599 free(drv->mInvokeFunctions); 600 drv->mInvokeFunctions = NULL; 601 } 602 603 if (drv->mForEachFunctions) { 604 free(drv->mForEachFunctions); 605 drv->mForEachFunctions = NULL; 606 } 607 608 delete drv->ME; 609 drv->ME = NULL; 610 611 delete[] drv->mBoundAllocs; 612 free(drv); 613 script->mHal.drv = NULL; 614 615} 616 617Allocation * rsdScriptGetAllocationForPointer(const android::renderscript::Context *dc, 618 const android::renderscript::Script *sc, 619 const void *ptr) { 620 DrvScript *drv = (DrvScript *)sc->mHal.drv; 621 if (!ptr) { 622 return NULL; 623 } 624 625 for (uint32_t ct=0; ct < sc->mHal.info.exportedVariableCount; ct++) { 626 Allocation *a = drv->mBoundAllocs[ct]; 627 if (!a) continue; 628 DrvAllocation *adrv = (DrvAllocation *)a->mHal.drv; 629 if (adrv->lod[0].mallocPtr == ptr) { 630 return a; 631 } 632 } 633 ALOGE("rsGetAllocation, failed to find %p", ptr); 634 return NULL; 635} 636 637