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