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