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