blob: 4ba60d32d2f7a32d2a5d82905ab90ee4949342a9 [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>
Stephen Hinesba17ae42013-06-05 17:18:04 -070041 #include <cutils/properties.h>
Jason Sams110f1812013-03-14 16:02:18 -070042#endif
Jason Sams709a0972012-11-15 18:18:04 -080043
Stephen Hinesba17ae42013-06-05 17:18:04 -070044#ifndef RS_COMPATIBILITY_LIB
45namespace {
46static bool is_force_recompile() {
47#ifdef RS_SERVER
48 return false;
49#else
50 char buf[PROPERTY_VALUE_MAX];
51
52 // Re-compile if floating point precision has been overridden.
53 property_get("debug.rs.precision", buf, "");
54 if (buf[0] != '\0') {
55 return true;
56 }
57
58 // Re-compile if debug.rs.forcerecompile is set.
59 property_get("debug.rs.forcerecompile", buf, "0");
60 if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) {
61 return true;
62 } else {
63 return false;
64 }
65#endif // RS_SERVER
66}
67} // namespace
68#endif // !defined(RS_COMPATIBILITY_LIB)
69
Jason Sams709a0972012-11-15 18:18:04 -080070namespace android {
71namespace renderscript {
72
73
Jason Sams110f1812013-03-14 16:02:18 -070074#ifdef RS_COMPATIBILITY_LIB
75#define MAXLINE 500
76#define MAKE_STR_HELPER(S) #S
77#define MAKE_STR(S) MAKE_STR_HELPER(S)
78#define EXPORT_VAR_STR "exportVarCount: "
79#define EXPORT_VAR_STR_LEN strlen(EXPORT_VAR_STR)
80#define EXPORT_FUNC_STR "exportFuncCount: "
81#define EXPORT_FUNC_STR_LEN strlen(EXPORT_FUNC_STR)
82#define EXPORT_FOREACH_STR "exportForEachCount: "
83#define EXPORT_FOREACH_STR_LEN strlen(EXPORT_FOREACH_STR)
84#define OBJECT_SLOT_STR "objectSlotCount: "
85#define OBJECT_SLOT_STR_LEN strlen(OBJECT_SLOT_STR)
86
87// Copy up to a newline or size chars from str -> s, updating str
88// Returns s when successful and NULL when '\0' is finally reached.
89static char* strgets(char *s, int size, const char **ppstr) {
90 if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
91 return NULL;
92 }
93
94 int i;
95 for (i = 0; i < (size - 1); i++) {
96 s[i] = **ppstr;
97 (*ppstr)++;
98 if (s[i] == '\0') {
99 return s;
100 } else if (s[i] == '\n') {
101 s[i+1] = '\0';
102 return s;
103 }
104 }
105
106 // size has been exceeded.
107 s[i] = '\0';
108
109 return s;
110}
111#endif
Jason Sams709a0972012-11-15 18:18:04 -0800112
113RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) {
114 mCtx = ctx;
115 mScript = s;
116
Jason Sams110f1812013-03-14 16:02:18 -0700117#ifdef RS_COMPATIBILITY_LIB
118 mScriptSO = NULL;
119 mInvokeFunctions = NULL;
120 mForEachFunctions = NULL;
121 mFieldAddress = NULL;
122 mFieldIsObject = NULL;
123 mForEachSignatures = NULL;
124#else
125 mCompilerContext = NULL;
126 mCompilerDriver = NULL;
127 mExecutable = NULL;
128#endif
129
Jason Sams709a0972012-11-15 18:18:04 -0800130 mRoot = NULL;
131 mRootExpand = NULL;
132 mInit = NULL;
133 mFreeChildren = NULL;
134
Jason Sams709a0972012-11-15 18:18:04 -0800135
136 mBoundAllocs = NULL;
137 mIntrinsicData = NULL;
138 mIsThreadable = true;
139}
140
141
142bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
143 uint8_t const *bitcode, size_t bitcodeSize,
144 uint32_t flags) {
145 //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
146 //ALOGE("rsdScriptInit %p %p", rsc, script);
147
148 mCtx->lockMutex();
149
Jason Sams110f1812013-03-14 16:02:18 -0700150#ifndef RS_COMPATIBILITY_LIB
Stephen Hinesba17ae42013-06-05 17:18:04 -0700151 bcc::RSExecutable *exec = NULL;
Jason Sams709a0972012-11-15 18:18:04 -0800152
153 mCompilerContext = NULL;
154 mCompilerDriver = NULL;
155 mExecutable = NULL;
156
157 mCompilerContext = new bcc::BCCContext();
158 if (mCompilerContext == NULL) {
159 ALOGE("bcc: FAILS to create compiler context (out of memory)");
160 mCtx->unlockMutex();
161 return false;
162 }
163
164 mCompilerDriver = new bcc::RSCompilerDriver();
165 if (mCompilerDriver == NULL) {
166 ALOGE("bcc: FAILS to create compiler driver (out of memory)");
167 mCtx->unlockMutex();
168 return false;
169 }
170
171 mCompilerDriver->setRSRuntimeLookupFunction(lookupRuntimeStub);
172 mCompilerDriver->setRSRuntimeLookupContext(this);
173
Stephen Hinesb7d9c802013-04-29 19:13:09 -0700174 // Run any compiler setup functions we have been provided with.
175 RSSetupCompilerCallback setupCompilerCallback =
176 mCtx->getSetupCompilerCallback();
177 if (setupCompilerCallback != NULL) {
178 setupCompilerCallback(mCompilerDriver);
179 }
180
Stephen Hines1d476622013-03-29 22:08:49 -0700181 const char *core_lib = NULL;
182 RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback();
183 if (selectRTCallback != NULL) {
184 core_lib = selectRTCallback((const char *)bitcode, bitcodeSize);
185 }
Stephen Hinescca3d6c2013-04-15 01:06:39 -0700186
187 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
188 // Use the libclcore_debug.bc instead of the default library.
189 core_lib = bcc::RSInfo::LibCLCoreDebugPath;
Stephen Hinesf47e8b42013-04-18 01:06:29 -0700190 mCompilerDriver->setDebugContext(true);
Stephen Hinesba17ae42013-06-05 17:18:04 -0700191 // Skip the cache lookup
192 } else if (!is_force_recompile()) {
193 // Attempt to just load the script from cache first if we can.
194 exec = mCompilerDriver->loadScript(cacheDir, resName,
195 (const char *)bitcode, bitcodeSize);
Stephen Hinescca3d6c2013-04-15 01:06:39 -0700196 }
Stephen Hinesba17ae42013-06-05 17:18:04 -0700197
198 // TODO(srhines): This is being refactored, but it simply wraps the
199 // build (compile) and load steps together.
200 if (exec == NULL) {
201 bool built = mCompilerDriver->build(*mCompilerContext, cacheDir,
202 resName, (const char *)bitcode,
203 bitcodeSize, core_lib,
204 mCtx->getLinkRuntimeCallback());
205 if (built) {
206 exec = mCompilerDriver->loadScript(cacheDir, resName,
207 (const char *)bitcode,
208 bitcodeSize);
209 }
210 }
Jason Sams709a0972012-11-15 18:18:04 -0800211
212 if (exec == NULL) {
213 ALOGE("bcc: FAILS to prepare executable for '%s'", resName);
214 mCtx->unlockMutex();
215 return false;
216 }
217
218 mExecutable = exec;
219
220 exec->setThreadable(mIsThreadable);
221 if (!exec->syncInfo()) {
222 ALOGW("bcc: FAILS to synchronize the RS info file to the disk");
223 }
224
225 mRoot = reinterpret_cast<int (*)()>(exec->getSymbolAddress("root"));
226 mRootExpand =
227 reinterpret_cast<int (*)()>(exec->getSymbolAddress("root.expand"));
228 mInit = reinterpret_cast<void (*)()>(exec->getSymbolAddress("init"));
229 mFreeChildren =
230 reinterpret_cast<void (*)()>(exec->getSymbolAddress(".rs.dtor"));
231
232
Stephen Hines1d476622013-03-29 22:08:49 -0700233 const bcc::RSInfo *info = &mExecutable->getInfo();
Jason Sams709a0972012-11-15 18:18:04 -0800234 if (info->getExportVarNames().size()) {
235 mBoundAllocs = new Allocation *[info->getExportVarNames().size()];
236 memset(mBoundAllocs, 0, sizeof(void *) * info->getExportVarNames().size());
237 }
238
Jason Sams110f1812013-03-14 16:02:18 -0700239#else
240
Tim Murray0b575de2013-03-15 15:56:43 -0700241#ifndef RS_SERVER
Jason Sams110f1812013-03-14 16:02:18 -0700242 String8 scriptSOName(cacheDir);
243 scriptSOName = scriptSOName.getPathDir();
244 scriptSOName.appendPath("lib");
245 scriptSOName.append("/librs.");
Tim Murray0b575de2013-03-15 15:56:43 -0700246#else
247 String8 scriptSOName("lib");
248#endif
Jason Sams110f1812013-03-14 16:02:18 -0700249 scriptSOName.append(resName);
250 scriptSOName.append(".so");
251
252 //script->mHal.drv = drv;
253
254 //ALOGV("Opening up shared object: %s", scriptSOName.string());
255 mScriptSO = dlopen(scriptSOName.string(), RTLD_NOW | RTLD_LOCAL);
256 if (mScriptSO == NULL) {
257 ALOGE("Unable to open shared library (%s): %s",
258 scriptSOName.string(), dlerror());
259
260 // One final attempt to find the library in "/system/lib".
261 // We do this to allow bundled applications to use the compatibility
262 // library fallback path. Those applications don't have a private
263 // library path, so they need to install to the system directly.
264 String8 scriptSONameSystem("/system/lib/librs.");
265 scriptSONameSystem.append(resName);
266 scriptSONameSystem.append(".so");
267 mScriptSO = dlopen(scriptSONameSystem.string(), RTLD_NOW | RTLD_LOCAL);
268 if (mScriptSO == NULL) {
269 ALOGE("Unable to open system shared library (%s): %s",
270 scriptSONameSystem.string(), dlerror());
271 goto error;
272 }
273 }
274
275 if (mScriptSO) {
276 char line[MAXLINE];
277 mRoot = (RootFunc_t) dlsym(mScriptSO, "root");
278 if (mRoot) {
279 //ALOGE("Found root(): %p", mRoot);
280 }
281 mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand");
282 if (mRootExpand) {
283 //ALOGE("Found root.expand(): %p", mRootExpand);
284 }
285 mInit = (InvokeFunc_t) dlsym(mScriptSO, "init");
286 if (mInit) {
287 //ALOGE("Found init(): %p", mInit);
288 }
289 mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor");
290 if (mFreeChildren) {
291 //ALOGE("Found .rs.dtor(): %p", mFreeChildren);
292 }
293
294 const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info");
295 if (rsInfo) {
296 //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo);
297 }
298
299 size_t varCount = 0;
300 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
301 goto error;
302 }
303 if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
304 ALOGE("Invalid export var count!: %s", line);
305 goto error;
306 }
307
308 mExportedVariableCount = varCount;
309 //ALOGE("varCount: %zu", varCount);
310 if (varCount > 0) {
311 // Start by creating/zeroing this member, since we don't want to
312 // accidentally clean up invalid pointers later (if we error out).
313 mFieldIsObject = new bool[varCount];
314 if (mFieldIsObject == NULL) {
315 goto error;
316 }
317 memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject));
318 mFieldAddress = new void*[varCount];
319 if (mFieldAddress == NULL) {
320 goto error;
321 }
322 for (size_t i = 0; i < varCount; ++i) {
323 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
324 goto error;
325 }
326 char *c = strrchr(line, '\n');
327 if (c) {
328 *c = '\0';
329 }
330 mFieldAddress[i] = dlsym(mScriptSO, line);
331 if (mFieldAddress[i] == NULL) {
332 ALOGE("Failed to find variable address for %s: %s",
333 line, dlerror());
334 // Not a critical error if we don't find a global variable.
335 }
336 else {
337 //ALOGE("Found variable %s at %p", line,
338 //mFieldAddress[i]);
339 }
340 }
341 }
342
343 size_t funcCount = 0;
344 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
345 goto error;
346 }
347 if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
348 ALOGE("Invalid export func count!: %s", line);
349 goto error;
350 }
351
352 mExportedFunctionCount = funcCount;
353 //ALOGE("funcCount: %zu", funcCount);
354
355 if (funcCount > 0) {
356 mInvokeFunctions = new InvokeFunc_t[funcCount];
357 if (mInvokeFunctions == NULL) {
358 goto error;
359 }
360 for (size_t i = 0; i < funcCount; ++i) {
361 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
362 goto error;
363 }
364 char *c = strrchr(line, '\n');
365 if (c) {
366 *c = '\0';
367 }
368
369 mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line);
370 if (mInvokeFunctions[i] == NULL) {
371 ALOGE("Failed to get function address for %s(): %s",
372 line, dlerror());
373 goto error;
374 }
375 else {
376 //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]);
377 }
378 }
379 }
380
381 size_t forEachCount = 0;
382 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
383 goto error;
384 }
385 if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
386 ALOGE("Invalid export forEach count!: %s", line);
387 goto error;
388 }
389
390 if (forEachCount > 0) {
391
392 mForEachSignatures = new uint32_t[forEachCount];
393 if (mForEachSignatures == NULL) {
394 goto error;
395 }
396 mForEachFunctions = new ForEachFunc_t[forEachCount];
397 if (mForEachFunctions == NULL) {
398 goto error;
399 }
400 for (size_t i = 0; i < forEachCount; ++i) {
401 unsigned int tmpSig = 0;
402 char tmpName[MAXLINE];
403
404 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
405 goto error;
406 }
407 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
408 &tmpSig, tmpName) != 2) {
409 ALOGE("Invalid export forEach!: %s", line);
410 goto error;
411 }
412
413 // Lookup the expanded ForEach kernel.
414 strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
415 mForEachSignatures[i] = tmpSig;
416 mForEachFunctions[i] =
417 (ForEachFunc_t) dlsym(mScriptSO, tmpName);
Stephen Hinesef7481e2013-04-09 19:05:27 -0700418 if (i != 0 && mForEachFunctions[i] == NULL) {
Jason Sams110f1812013-03-14 16:02:18 -0700419 // Ignore missing root.expand functions.
420 // root() is always specified at location 0.
Stephen Hinesef7481e2013-04-09 19:05:27 -0700421 ALOGE("Failed to find forEach function address for %s: %s",
422 tmpName, dlerror());
423 goto error;
Jason Sams110f1812013-03-14 16:02:18 -0700424 }
425 else {
426 //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]);
427 }
428 }
429 }
430
431 size_t objectSlotCount = 0;
432 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
433 goto error;
434 }
435 if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
436 ALOGE("Invalid object slot count!: %s", line);
437 goto error;
438 }
439
440 if (objectSlotCount > 0) {
441 rsAssert(varCount > 0);
442 for (size_t i = 0; i < objectSlotCount; ++i) {
443 uint32_t varNum = 0;
444 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
445 goto error;
446 }
447 if (sscanf(line, "%u", &varNum) != 1) {
448 ALOGE("Invalid object slot!: %s", line);
449 goto error;
450 }
451
452 if (varNum < varCount) {
453 mFieldIsObject[varNum] = true;
454 }
455 }
456 }
457
458 if (varCount > 0) {
459 mBoundAllocs = new Allocation *[varCount];
460 memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs));
461 }
462
463 if (mScriptSO == (void*)1) {
464 //rsdLookupRuntimeStub(script, "acos");
465 }
466 }
467#endif
468
Jason Sams709a0972012-11-15 18:18:04 -0800469 mCtx->unlockMutex();
470 return true;
Jason Sams110f1812013-03-14 16:02:18 -0700471
472#ifdef RS_COMPATIBILITY_LIB
473error:
474
475 mCtx->unlockMutex();
476 delete[] mInvokeFunctions;
477 delete[] mForEachFunctions;
478 delete[] mFieldAddress;
479 delete[] mFieldIsObject;
480 delete[] mForEachSignatures;
481 delete[] mBoundAllocs;
482 if (mScriptSO) {
483 dlclose(mScriptSO);
484 }
485 return false;
486#endif
Jason Sams709a0972012-11-15 18:18:04 -0800487}
488
489void RsdCpuScriptImpl::populateScript(Script *script) {
Jason Sams110f1812013-03-14 16:02:18 -0700490#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800491 const bcc::RSInfo *info = &mExecutable->getInfo();
492
493 // Copy info over to runtime
494 script->mHal.info.exportedFunctionCount = info->getExportFuncNames().size();
495 script->mHal.info.exportedVariableCount = info->getExportVarNames().size();
496 script->mHal.info.exportedPragmaCount = info->getPragmas().size();
497 script->mHal.info.exportedPragmaKeyList =
498 const_cast<const char**>(mExecutable->getPragmaKeys().array());
499 script->mHal.info.exportedPragmaValueList =
500 const_cast<const char**>(mExecutable->getPragmaValues().array());
501
502 if (mRootExpand) {
503 script->mHal.info.root = mRootExpand;
504 } else {
505 script->mHal.info.root = mRoot;
506 }
Jason Sams110f1812013-03-14 16:02:18 -0700507#else
508 // Copy info over to runtime
509 script->mHal.info.exportedFunctionCount = mExportedFunctionCount;
510 script->mHal.info.exportedVariableCount = mExportedVariableCount;
511 script->mHal.info.exportedPragmaCount = 0;
512 script->mHal.info.exportedPragmaKeyList = 0;
513 script->mHal.info.exportedPragmaValueList = 0;
514
515 // Bug, need to stash in metadata
516 if (mRootExpand) {
517 script->mHal.info.root = mRootExpand;
518 } else {
519 script->mHal.info.root = mRoot;
520 }
521#endif
Jason Sams709a0972012-11-15 18:18:04 -0800522}
523
Jason Sams709a0972012-11-15 18:18:04 -0800524
525typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
526
527void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation * ain, Allocation * aout,
528 const void * usr, uint32_t usrLen,
529 const RsScriptCall *sc,
530 MTLaunchStruct *mtls) {
531
532 memset(mtls, 0, sizeof(MTLaunchStruct));
533
Tim Murray3a25fdd2013-02-22 17:56:56 -0800534 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface
535 if (ain && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) {
536 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
537 return;
538 }
539 if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) {
540 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
541 return;
542 }
543
Jason Sams709a0972012-11-15 18:18:04 -0800544 if (ain) {
545 mtls->fep.dimX = ain->getType()->getDimX();
546 mtls->fep.dimY = ain->getType()->getDimY();
547 mtls->fep.dimZ = ain->getType()->getDimZ();
548 //mtls->dimArray = ain->getType()->getDimArray();
549 } else if (aout) {
550 mtls->fep.dimX = aout->getType()->getDimX();
551 mtls->fep.dimY = aout->getType()->getDimY();
552 mtls->fep.dimZ = aout->getType()->getDimZ();
553 //mtls->dimArray = aout->getType()->getDimArray();
554 } else {
555 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
556 return;
557 }
558
559 if (!sc || (sc->xEnd == 0)) {
560 mtls->xEnd = mtls->fep.dimX;
561 } else {
562 rsAssert(sc->xStart < mtls->fep.dimX);
563 rsAssert(sc->xEnd <= mtls->fep.dimX);
564 rsAssert(sc->xStart < sc->xEnd);
565 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
566 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
567 if (mtls->xStart >= mtls->xEnd) return;
568 }
569
570 if (!sc || (sc->yEnd == 0)) {
571 mtls->yEnd = mtls->fep.dimY;
572 } else {
573 rsAssert(sc->yStart < mtls->fep.dimY);
574 rsAssert(sc->yEnd <= mtls->fep.dimY);
575 rsAssert(sc->yStart < sc->yEnd);
576 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
577 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
578 if (mtls->yStart >= mtls->yEnd) return;
579 }
580
Tim Murrayd4ecb172013-02-07 12:17:03 -0800581 if (!sc || (sc->zEnd == 0)) {
582 mtls->zEnd = mtls->fep.dimZ;
583 } else {
584 rsAssert(sc->zStart < mtls->fep.dimZ);
585 rsAssert(sc->zEnd <= mtls->fep.dimZ);
586 rsAssert(sc->zStart < sc->zEnd);
587 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart);
588 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd);
589 if (mtls->zStart >= mtls->zEnd) return;
590 }
591
Jason Sams709a0972012-11-15 18:18:04 -0800592 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
593 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
594 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
595 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
596
597 rsAssert(!ain || (ain->getType()->getDimZ() == 0));
598
599 mtls->rsc = mCtx;
600 mtls->ain = ain;
601 mtls->aout = aout;
602 mtls->fep.usr = usr;
603 mtls->fep.usrLen = usrLen;
604 mtls->mSliceSize = 1;
605 mtls->mSliceNum = 0;
606
607 mtls->fep.ptrIn = NULL;
608 mtls->fep.eStrideIn = 0;
609 mtls->isThreadable = mIsThreadable;
610
611 if (ain) {
612 mtls->fep.ptrIn = (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr;
613 mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes();
614 mtls->fep.yStrideIn = ain->mHal.drvState.lod[0].stride;
615 }
616
617 mtls->fep.ptrOut = NULL;
618 mtls->fep.eStrideOut = 0;
619 if (aout) {
620 mtls->fep.ptrOut = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
621 mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes();
622 mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride;
623 }
624}
625
626
627void RsdCpuScriptImpl::invokeForEach(uint32_t slot,
628 const Allocation * ain,
629 Allocation * aout,
630 const void * usr,
631 uint32_t usrLen,
632 const RsScriptCall *sc) {
633
634 MTLaunchStruct mtls;
635 forEachMtlsSetup(ain, aout, usr, usrLen, sc, &mtls);
636 forEachKernelSetup(slot, &mtls);
637
638 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
639 mCtx->launchThreads(ain, aout, sc, &mtls);
640 mCtx->setTLS(oldTLS);
641}
642
643void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) {
Jason Sams709a0972012-11-15 18:18:04 -0800644 mtls->script = this;
645 mtls->fep.slot = slot;
Jason Sams110f1812013-03-14 16:02:18 -0700646#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800647 rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size());
648 mtls->kernel = reinterpret_cast<ForEachFunc_t>(
649 mExecutable->getExportForeachFuncAddrs()[slot]);
650 rsAssert(mtls->kernel != NULL);
651 mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second;
Jason Sams110f1812013-03-14 16:02:18 -0700652#else
653 mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]);
654 rsAssert(mtls->kernel != NULL);
655 mtls->sig = mForEachSignatures[slot];
656#endif
Jason Sams709a0972012-11-15 18:18:04 -0800657}
658
659int RsdCpuScriptImpl::invokeRoot() {
660 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
661 int ret = mRoot();
662 mCtx->setTLS(oldTLS);
663 return ret;
664}
665
666void RsdCpuScriptImpl::invokeInit() {
667 if (mInit) {
668 mInit();
669 }
670}
671
672void RsdCpuScriptImpl::invokeFreeChildren() {
673 if (mFreeChildren) {
674 mFreeChildren();
675 }
676}
677
678void RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params,
679 size_t paramLength) {
680 //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
681
682 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
683 reinterpret_cast<void (*)(const void *, uint32_t)>(
Jason Sams110f1812013-03-14 16:02:18 -0700684#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800685 mExecutable->getExportFuncAddrs()[slot])(params, paramLength);
Jason Sams110f1812013-03-14 16:02:18 -0700686#else
687 mInvokeFunctions[slot])(params, paramLength);
688#endif
Jason Sams709a0972012-11-15 18:18:04 -0800689 mCtx->setTLS(oldTLS);
690}
691
692void RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) {
693 //rsAssert(!script->mFieldIsObject[slot]);
694 //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
695
696 //if (mIntrinsicID) {
697 //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
698 //return;
699 //}
700
Jason Sams110f1812013-03-14 16:02:18 -0700701#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800702 int32_t *destPtr = reinterpret_cast<int32_t *>(
703 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -0700704#else
705 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
706#endif
Jason Sams709a0972012-11-15 18:18:04 -0800707 if (!destPtr) {
708 //ALOGV("Calling setVar on slot = %i which is null", slot);
709 return;
710 }
711
712 memcpy(destPtr, data, dataLength);
713}
714
Tim Murray9c642392013-04-11 13:29:59 -0700715void RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) {
716 //rsAssert(!script->mFieldIsObject[slot]);
717 //ALOGE("getGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
718
719#ifndef RS_COMPATIBILITY_LIB
720 int32_t *srcPtr = reinterpret_cast<int32_t *>(
721 mExecutable->getExportVarAddrs()[slot]);
722#else
723 int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
724#endif
725 if (!srcPtr) {
726 //ALOGV("Calling setVar on slot = %i which is null", slot);
727 return;
728 }
729 memcpy(data, srcPtr, dataLength);
730}
731
732
Jason Sams709a0972012-11-15 18:18:04 -0800733void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength,
734 const Element *elem,
735 const size_t *dims, size_t dimLength) {
736
Jason Sams110f1812013-03-14 16:02:18 -0700737#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800738 int32_t *destPtr = reinterpret_cast<int32_t *>(
739 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -0700740#else
741 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
742#endif
Jason Sams709a0972012-11-15 18:18:04 -0800743 if (!destPtr) {
744 //ALOGV("Calling setVar on slot = %i which is null", slot);
745 return;
746 }
747
748 // We want to look at dimension in terms of integer components,
749 // but dimLength is given in terms of bytes.
750 dimLength /= sizeof(int);
751
752 // Only a single dimension is currently supported.
753 rsAssert(dimLength == 1);
754 if (dimLength == 1) {
755 // First do the increment loop.
756 size_t stride = elem->getSizeBytes();
757 const char *cVal = reinterpret_cast<const char *>(data);
758 for (size_t i = 0; i < dims[0]; i++) {
759 elem->incRefs(cVal);
760 cVal += stride;
761 }
762
763 // Decrement loop comes after (to prevent race conditions).
764 char *oldVal = reinterpret_cast<char *>(destPtr);
765 for (size_t i = 0; i < dims[0]; i++) {
766 elem->decRefs(oldVal);
767 oldVal += stride;
768 }
769 }
770
771 memcpy(destPtr, data, dataLength);
772}
773
774void RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) {
775
776 //rsAssert(!script->mFieldIsObject[slot]);
777 //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
778
Jason Sams110f1812013-03-14 16:02:18 -0700779#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800780 int32_t *destPtr = reinterpret_cast<int32_t *>(
781 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -0700782#else
783 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
784#endif
Jason Sams709a0972012-11-15 18:18:04 -0800785 if (!destPtr) {
786 //ALOGV("Calling setVar on slot = %i which is null", slot);
787 return;
788 }
789
790 void *ptr = NULL;
791 mBoundAllocs[slot] = data;
792 if(data) {
793 ptr = data->mHal.drvState.lod[0].mallocPtr;
794 }
795 memcpy(destPtr, &ptr, sizeof(void *));
796}
797
798void RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) {
799
800 //rsAssert(script->mFieldIsObject[slot]);
801 //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
802
803 //if (mIntrinsicID) {
804 //mIntrinsicFuncs.setVarObj(dc, script, drv->mIntrinsicData, slot, alloc);
805 //return;
806 //}
807
Jason Sams110f1812013-03-14 16:02:18 -0700808#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800809 int32_t *destPtr = reinterpret_cast<int32_t *>(
810 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -0700811#else
812 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
813#endif
Jason Sams709a0972012-11-15 18:18:04 -0800814 if (!destPtr) {
815 //ALOGV("Calling setVar on slot = %i which is null", slot);
816 return;
817 }
818
819 rsrSetObject(mCtx->getContext(), (ObjectBase **)destPtr, data);
820}
821
822RsdCpuScriptImpl::~RsdCpuScriptImpl() {
Jason Sams110f1812013-03-14 16:02:18 -0700823#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800824 if (mExecutable) {
825 Vector<void *>::const_iterator var_addr_iter =
826 mExecutable->getExportVarAddrs().begin();
827 Vector<void *>::const_iterator var_addr_end =
828 mExecutable->getExportVarAddrs().end();
829
830 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter =
831 mExecutable->getInfo().getObjectSlots().begin();
832 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end =
833 mExecutable->getInfo().getObjectSlots().end();
834
835 while ((var_addr_iter != var_addr_end) &&
836 (is_object_iter != is_object_end)) {
837 // The field address can be NULL if the script-side has optimized
838 // the corresponding global variable away.
839 ObjectBase **obj_addr =
840 reinterpret_cast<ObjectBase **>(*var_addr_iter);
841 if (*is_object_iter) {
842 if (*var_addr_iter != NULL) {
843 rsrClearObject(mCtx->getContext(), obj_addr);
844 }
845 }
846 var_addr_iter++;
847 is_object_iter++;
848 }
849 }
850
851 if (mCompilerContext) {
852 delete mCompilerContext;
853 }
854 if (mCompilerDriver) {
855 delete mCompilerDriver;
856 }
857 if (mExecutable) {
858 delete mExecutable;
859 }
860 if (mBoundAllocs) {
861 delete[] mBoundAllocs;
862 }
Jason Sams110f1812013-03-14 16:02:18 -0700863#else
864 if (mFieldIsObject) {
865 for (size_t i = 0; i < mExportedVariableCount; ++i) {
866 if (mFieldIsObject[i]) {
867 if (mFieldAddress[i] != NULL) {
868 ObjectBase **obj_addr =
869 reinterpret_cast<ObjectBase **>(mFieldAddress[i]);
870 rsrClearObject(mCtx->getContext(), obj_addr);
871 }
872 }
873 }
874 }
875
876 if (mInvokeFunctions) delete[] mInvokeFunctions;
877 if (mForEachFunctions) delete[] mForEachFunctions;
878 if (mFieldAddress) delete[] mFieldAddress;
879 if (mFieldIsObject) delete[] mFieldIsObject;
880 if (mForEachSignatures) delete[] mForEachSignatures;
881 if (mBoundAllocs) delete[] mBoundAllocs;
882 if (mScriptSO) {
883 dlclose(mScriptSO);
884 }
885#endif
Jason Sams709a0972012-11-15 18:18:04 -0800886}
887
888Allocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const {
889 if (!ptr) {
890 return NULL;
891 }
892
893 for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) {
894 Allocation *a = mBoundAllocs[ct];
895 if (!a) continue;
896 if (a->mHal.drvState.lod[0].mallocPtr == ptr) {
897 return a;
898 }
899 }
900 ALOGE("rsGetAllocation, failed to find %p", ptr);
901 return NULL;
902}
903
904
905}
906}