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 "rsCpuCore.h"
18 #include "rsCpuScript.h"
19
20 #ifdef RS_COMPATIBILITY_LIB
21 #include <set>
22 #include <string>
23 #include <dlfcn.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #else
30 #include <bcc/BCCContext.h>
31 #include <bcc/Config/Config.h>
32 #include <bcc/Renderscript/RSCompilerDriver.h>
33 #include <bcc/Renderscript/RSExecutable.h>
34 #include <bcc/Renderscript/RSInfo.h>
35 #include <bcinfo/MetadataExtractor.h>
36 #include <cutils/properties.h>
37
38 #include <sys/types.h>
39 #include <sys/wait.h>
40 #include <unistd.h>
41
42 #include <string>
43 #include <vector>
44 #endif
45
46 namespace {
47 #ifdef RS_COMPATIBILITY_LIB
48
49 // Create a len length string containing random characters from [A-Za-z0-9].
getRandomString(size_t len)50 static std::string getRandomString(size_t len) {
51 char buf[len + 1];
52 for (size_t i = 0; i < len; i++) {
53 uint32_t r = arc4random() & 0xffff;
54 r %= 62;
55 if (r < 26) {
56 // lowercase
57 buf[i] = 'a' + r;
58 } else if (r < 52) {
59 // uppercase
60 buf[i] = 'A' + (r - 26);
61 } else {
62 // Use a number
63 buf[i] = '0' + (r - 52);
64 }
65 }
66 buf[len] = '\0';
67 return std::string(buf);
68 }
69
70 // Check if a path exists and attempt to create it if it doesn't.
ensureCacheDirExists(const char * path)71 static bool ensureCacheDirExists(const char *path) {
72 if (access(path, R_OK | W_OK | X_OK) == 0) {
73 // Done if we can rwx the directory
74 return true;
75 }
76 if (mkdir(path, 0700) == 0) {
77 return true;
78 }
79 return false;
80 }
81
82 // Attempt to load the shared library from origName, but then fall back to
83 // creating the symlinked shared library if necessary (to ensure instancing).
84 // This function returns the dlopen()-ed handle if successful.
loadSOHelper(const char * origName,const char * cacheDir,const char * resName)85 static void *loadSOHelper(const char *origName, const char *cacheDir,
86 const char *resName) {
87 // Keep track of which .so libraries have been loaded. Once a library is
88 // in the set (per-process granularity), we must instead make a symlink to
89 // the original shared object (randomly named .so file) and load that one
90 // instead. If we don't do this, we end up aliasing global data between
91 // the various Script instances (which are supposed to be completely
92 // independent).
93 static std::set<std::string> LoadedLibraries;
94
95 void *loaded = NULL;
96
97 // Skip everything if we don't even have the original library available.
98 if (access(origName, F_OK) != 0) {
99 return NULL;
100 }
101
102 // Common path is that we have not loaded this Script/library before.
103 if (LoadedLibraries.find(origName) == LoadedLibraries.end()) {
104 loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL);
105 if (loaded) {
106 LoadedLibraries.insert(origName);
107 }
108 return loaded;
109 }
110
111 std::string newName(cacheDir);
112 newName.append("/com.android.renderscript.cache/");
113
114 if (!ensureCacheDirExists(newName.c_str())) {
115 ALOGE("Could not verify or create cache dir: %s", cacheDir);
116 return NULL;
117 }
118
119 // Construct an appropriately randomized filename for the symlink.
120 newName.append("librs.");
121 newName.append(resName);
122 newName.append("#");
123 newName.append(getRandomString(6)); // 62^6 potential filename variants.
124 newName.append(".so");
125
126 int r = symlink(origName, newName.c_str());
127 if (r != 0) {
128 ALOGE("Could not create symlink %s -> %s", newName.c_str(), origName);
129 return NULL;
130 }
131 loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL);
132 r = unlink(newName.c_str());
133 if (r != 0) {
134 ALOGE("Could not unlink symlink %s", newName.c_str());
135 }
136 if (loaded) {
137 LoadedLibraries.insert(newName.c_str());
138 }
139
140 return loaded;
141 }
142
143 // Load the shared library referred to by cacheDir and resName. If we have
144 // already loaded this library, we instead create a new symlink (in the
145 // cache dir) and then load that. We then immediately destroy the symlink.
146 // This is required behavior to implement script instancing for the support
147 // library, since shared objects are loaded and de-duped by name only.
loadSharedLibrary(const char * cacheDir,const char * resName)148 static void *loadSharedLibrary(const char *cacheDir, const char *resName) {
149 void *loaded = NULL;
150 //arc4random_stir();
151 #ifndef RS_SERVER
152 std::string scriptSOName(cacheDir);
153 size_t cutPos = scriptSOName.rfind("cache");
154 if (cutPos != std::string::npos) {
155 scriptSOName.erase(cutPos);
156 } else {
157 ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir);
158 }
159 scriptSOName.append("/lib/librs.");
160 #else
161 std::string scriptSOName("lib");
162 #endif
163 scriptSOName.append(resName);
164 scriptSOName.append(".so");
165
166 // We should check if we can load the library from the standard app
167 // location for shared libraries first.
168 loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName);
169
170 if (loaded == NULL) {
171 ALOGE("Unable to open shared library (%s): %s",
172 scriptSOName.c_str(), dlerror());
173
174 // One final attempt to find the library in "/system/lib".
175 // We do this to allow bundled applications to use the compatibility
176 // library fallback path. Those applications don't have a private
177 // library path, so they need to install to the system directly.
178 // Note that this is really just a testing path.
179 android::String8 scriptSONameSystem("/system/lib/librs.");
180 scriptSONameSystem.append(resName);
181 scriptSONameSystem.append(".so");
182 loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir,
183 resName);
184 if (loaded == NULL) {
185 ALOGE("Unable to open system shared library (%s): %s",
186 scriptSONameSystem.c_str(), dlerror());
187 }
188 }
189
190 return loaded;
191 }
192
193 #else // RS_COMPATIBILITY_LIB is not defined
194
195 static bool is_force_recompile() {
196 #ifdef RS_SERVER
197 return false;
198 #else
199 char buf[PROPERTY_VALUE_MAX];
200
201 // Re-compile if floating point precision has been overridden.
202 property_get("debug.rs.precision", buf, "");
203 if (buf[0] != '\0') {
204 return true;
205 }
206
207 // Re-compile if debug.rs.forcerecompile is set.
208 property_get("debug.rs.forcerecompile", buf, "0");
209 if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) {
210 return true;
211 } else {
212 return false;
213 }
214 #endif // RS_SERVER
215 }
216
217 const static char *BCC_EXE_PATH = "/system/bin/bcc";
218
219 static void setCompileArguments(std::vector<const char*>* args, const android::String8& bcFileName,
220 const char* cacheDir, const char* resName, const char* core_lib,
221 bool useRSDebugContext, const char* bccPluginName) {
222 rsAssert(cacheDir && resName && core_lib);
223 args->push_back(BCC_EXE_PATH);
224 args->push_back("-o");
225 args->push_back(resName);
226 args->push_back("-output_path");
227 args->push_back(cacheDir);
228 args->push_back("-bclib");
229 args->push_back(core_lib);
230 args->push_back("-mtriple");
231 args->push_back(DEFAULT_TARGET_TRIPLE_STRING);
232
233 // Enable workaround for A53 codegen by default.
234 #if defined(__aarch64__) && !defined(DISABLE_A53_WORKAROUND)
235 args->push_back("-aarch64-fix-cortex-a53-835769");
236 #endif
237
238 // Execute the bcc compiler.
239 if (useRSDebugContext) {
240 args->push_back("-rs-debug-ctx");
241 } else {
242 // Only load additional libraries for compiles that don't use
243 // the debug context.
244 if (bccPluginName && strlen(bccPluginName) > 0) {
245 args->push_back("-load");
246 args->push_back(bccPluginName);
247 }
248 }
249
250 args->push_back(bcFileName.string());
251 args->push_back(NULL);
252 }
253
254 static bool compileBitcode(const android::String8& bcFileName,
255 const char *bitcode,
256 size_t bitcodeSize,
257 const char** compileArguments,
258 const std::string& compileCommandLine) {
259 rsAssert(bitcode && bitcodeSize);
260
261 FILE *bcfile = fopen(bcFileName.string(), "w");
262 if (!bcfile) {
263 ALOGE("Could not write to %s", bcFileName.string());
264 return false;
265 }
266 size_t nwritten = fwrite(bitcode, 1, bitcodeSize, bcfile);
267 fclose(bcfile);
268 if (nwritten != bitcodeSize) {
269 ALOGE("Could not write %zu bytes to %s", bitcodeSize,
270 bcFileName.string());
271 return false;
272 }
273
274 pid_t pid = fork();
275
276 switch (pid) {
277 case -1: { // Error occurred (we attempt no recovery)
278 ALOGE("Couldn't fork for bcc compiler execution");
279 return false;
280 }
281 case 0: { // Child process
282 ALOGV("Invoking BCC with: %s", compileCommandLine.c_str());
283 execv(BCC_EXE_PATH, (char* const*)compileArguments);
284
285 ALOGE("execv() failed: %s", strerror(errno));
286 abort();
287 return false;
288 }
289 default: { // Parent process (actual driver)
290 // Wait on child process to finish compiling the source.
291 int status = 0;
292 pid_t w = waitpid(pid, &status, 0);
293 if (w == -1) {
294 ALOGE("Could not wait for bcc compiler");
295 return false;
296 }
297
298 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
299 return true;
300 }
301
302 ALOGE("bcc compiler terminated unexpectedly");
303 return false;
304 }
305 }
306 }
307
308 #endif // !defined(RS_COMPATIBILITY_LIB)
309 } // namespace
310
311 namespace android {
312 namespace renderscript {
313
314 #ifdef RS_COMPATIBILITY_LIB
315 #define MAXLINE 500
316 #define MAKE_STR_HELPER(S) #S
317 #define MAKE_STR(S) MAKE_STR_HELPER(S)
318 #define EXPORT_VAR_STR "exportVarCount: "
319 #define EXPORT_FUNC_STR "exportFuncCount: "
320 #define EXPORT_FOREACH_STR "exportForEachCount: "
321 #define OBJECT_SLOT_STR "objectSlotCount: "
322
323 // Copy up to a newline or size chars from str -> s, updating str
324 // Returns s when successful and NULL when '\0' is finally reached.
strgets(char * s,int size,const char ** ppstr)325 static char* strgets(char *s, int size, const char **ppstr) {
326 if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
327 return NULL;
328 }
329
330 int i;
331 for (i = 0; i < (size - 1); i++) {
332 s[i] = **ppstr;
333 (*ppstr)++;
334 if (s[i] == '\0') {
335 return s;
336 } else if (s[i] == '\n') {
337 s[i+1] = '\0';
338 return s;
339 }
340 }
341
342 // size has been exceeded.
343 s[i] = '\0';
344
345 return s;
346 }
347 #endif
348
RsdCpuScriptImpl(RsdCpuReferenceImpl * ctx,const Script * s)349 RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) {
350 mCtx = ctx;
351 mScript = s;
352
353 #ifdef RS_COMPATIBILITY_LIB
354 mScriptSO = NULL;
355 mInvokeFunctions = NULL;
356 mForEachFunctions = NULL;
357 mFieldAddress = NULL;
358 mFieldIsObject = NULL;
359 mForEachSignatures = NULL;
360 #else
361 mCompilerContext = NULL;
362 mCompilerDriver = NULL;
363 mExecutable = NULL;
364 #endif
365
366
367 mRoot = NULL;
368 mRootExpand = NULL;
369 mInit = NULL;
370 mFreeChildren = NULL;
371
372
373 mBoundAllocs = NULL;
374 mIntrinsicData = NULL;
375 mIsThreadable = true;
376 }
377
378
init(char const * resName,char const * cacheDir,uint8_t const * bitcode,size_t bitcodeSize,uint32_t flags,char const * bccPluginName)379 bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
380 uint8_t const *bitcode, size_t bitcodeSize,
381 uint32_t flags, char const *bccPluginName) {
382 //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
383 //ALOGE("rsdScriptInit %p %p", rsc, script);
384
385 mCtx->lockMutex();
386 #ifndef RS_COMPATIBILITY_LIB
387 bool useRSDebugContext = false;
388
389 mCompilerContext = NULL;
390 mCompilerDriver = NULL;
391 mExecutable = NULL;
392
393 mCompilerContext = new bcc::BCCContext();
394 if (mCompilerContext == NULL) {
395 ALOGE("bcc: FAILS to create compiler context (out of memory)");
396 mCtx->unlockMutex();
397 return false;
398 }
399
400 mCompilerDriver = new bcc::RSCompilerDriver();
401 if (mCompilerDriver == NULL) {
402 ALOGE("bcc: FAILS to create compiler driver (out of memory)");
403 mCtx->unlockMutex();
404 return false;
405 }
406
407 // Configure symbol resolvers (via compiler-rt and the RS runtime).
408 mRSRuntime.setLookupFunction(lookupRuntimeStub);
409 mRSRuntime.setContext(this);
410 mResolver.chainResolver(mCompilerRuntime);
411 mResolver.chainResolver(mRSRuntime);
412
413 // Run any compiler setup functions we have been provided with.
414 RSSetupCompilerCallback setupCompilerCallback =
415 mCtx->getSetupCompilerCallback();
416 if (setupCompilerCallback != NULL) {
417 setupCompilerCallback(mCompilerDriver);
418 }
419
420 bcinfo::MetadataExtractor bitcodeMetadata((const char *) bitcode, bitcodeSize);
421 if (!bitcodeMetadata.extract()) {
422 ALOGE("Could not extract metadata from bitcode");
423 mCtx->unlockMutex();
424 return false;
425 }
426
427 const char* core_lib = findCoreLib(bitcodeMetadata, (const char*)bitcode, bitcodeSize);
428
429 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
430 mCompilerDriver->setDebugContext(true);
431 useRSDebugContext = true;
432 }
433
434 android::String8 bcFileName(cacheDir);
435 bcFileName.append("/");
436 bcFileName.append(resName);
437 bcFileName.append(".bc");
438
439 std::vector<const char*> compileArguments;
440 setCompileArguments(&compileArguments, bcFileName, cacheDir, resName, core_lib,
441 useRSDebugContext, bccPluginName);
442 // The last argument of compileArguments ia a NULL, so remove 1 from the size.
443 std::string compileCommandLine =
444 bcc::getCommandLine(compileArguments.size() - 1, compileArguments.data());
445
446 if (!is_force_recompile()) {
447 // Load the compiled script that's in the cache, if any.
448 mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode,
449 bitcodeSize, compileCommandLine.c_str(),
450 mResolver);
451 }
452
453 // If we can't, it's either not there or out of date. We compile the bit code and try loading
454 // again.
455 if (mExecutable == NULL) {
456 if (!compileBitcode(bcFileName, (const char*)bitcode, bitcodeSize, compileArguments.data(),
457 compileCommandLine)) {
458 ALOGE("bcc: FAILS to compile '%s'", resName);
459 mCtx->unlockMutex();
460 return false;
461 }
462 mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode,
463 bitcodeSize, compileCommandLine.c_str(),
464 mResolver);
465 if (mExecutable == NULL) {
466 ALOGE("bcc: FAILS to load freshly compiled executable for '%s'", resName);
467 mCtx->unlockMutex();
468 return false;
469 }
470 }
471
472 mExecutable->setThreadable(mIsThreadable);
473 if (!mExecutable->syncInfo()) {
474 ALOGW("bcc: FAILS to synchronize the RS info file to the disk");
475 }
476
477 mRoot = reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root"));
478 mRootExpand =
479 reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root.expand"));
480 mInit = reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress("init"));
481 mFreeChildren =
482 reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress(".rs.dtor"));
483
484
485 if (bitcodeMetadata.getExportVarCount()) {
486 mBoundAllocs = new Allocation *[bitcodeMetadata.getExportVarCount()];
487 memset(mBoundAllocs, 0, sizeof(void *) * bitcodeMetadata.getExportVarCount());
488 }
489
490 for (size_t i = 0; i < bitcodeMetadata.getExportForEachSignatureCount(); i++) {
491 char* name = new char[strlen(bitcodeMetadata.getExportForEachNameList()[i]) + 1];
492 mExportedForEachFuncList.push_back(
493 std::make_pair(name, bitcodeMetadata.getExportForEachSignatureList()[i]));
494 }
495
496 #else // RS_COMPATIBILITY_LIB is defined
497
498 mScriptSO = loadSharedLibrary(cacheDir, resName);
499
500 if (mScriptSO) {
501 char line[MAXLINE];
502 mRoot = (RootFunc_t) dlsym(mScriptSO, "root");
503 if (mRoot) {
504 //ALOGE("Found root(): %p", mRoot);
505 }
506 mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand");
507 if (mRootExpand) {
508 //ALOGE("Found root.expand(): %p", mRootExpand);
509 }
510 mInit = (InvokeFunc_t) dlsym(mScriptSO, "init");
511 if (mInit) {
512 //ALOGE("Found init(): %p", mInit);
513 }
514 mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor");
515 if (mFreeChildren) {
516 //ALOGE("Found .rs.dtor(): %p", mFreeChildren);
517 }
518
519 const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info");
520 if (rsInfo) {
521 //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo);
522 }
523
524 size_t varCount = 0;
525 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
526 goto error;
527 }
528 if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
529 ALOGE("Invalid export var count!: %s", line);
530 goto error;
531 }
532
533 mExportedVariableCount = varCount;
534 //ALOGE("varCount: %zu", varCount);
535 if (varCount > 0) {
536 // Start by creating/zeroing this member, since we don't want to
537 // accidentally clean up invalid pointers later (if we error out).
538 mFieldIsObject = new bool[varCount];
539 if (mFieldIsObject == NULL) {
540 goto error;
541 }
542 memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject));
543 mFieldAddress = new void*[varCount];
544 if (mFieldAddress == NULL) {
545 goto error;
546 }
547 for (size_t i = 0; i < varCount; ++i) {
548 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
549 goto error;
550 }
551 char *c = strrchr(line, '\n');
552 if (c) {
553 *c = '\0';
554 }
555 mFieldAddress[i] = dlsym(mScriptSO, line);
556 if (mFieldAddress[i] == NULL) {
557 ALOGE("Failed to find variable address for %s: %s",
558 line, dlerror());
559 // Not a critical error if we don't find a global variable.
560 }
561 else {
562 //ALOGE("Found variable %s at %p", line,
563 //mFieldAddress[i]);
564 }
565 }
566 }
567
568 size_t funcCount = 0;
569 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
570 goto error;
571 }
572 if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
573 ALOGE("Invalid export func count!: %s", line);
574 goto error;
575 }
576
577 mExportedFunctionCount = funcCount;
578 //ALOGE("funcCount: %zu", funcCount);
579
580 if (funcCount > 0) {
581 mInvokeFunctions = new InvokeFunc_t[funcCount];
582 if (mInvokeFunctions == NULL) {
583 goto error;
584 }
585 for (size_t i = 0; i < funcCount; ++i) {
586 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
587 goto error;
588 }
589 char *c = strrchr(line, '\n');
590 if (c) {
591 *c = '\0';
592 }
593
594 mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line);
595 if (mInvokeFunctions[i] == NULL) {
596 ALOGE("Failed to get function address for %s(): %s",
597 line, dlerror());
598 goto error;
599 }
600 else {
601 //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]);
602 }
603 }
604 }
605
606 size_t forEachCount = 0;
607 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
608 goto error;
609 }
610 if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
611 ALOGE("Invalid export forEach count!: %s", line);
612 goto error;
613 }
614
615 if (forEachCount > 0) {
616
617 mForEachSignatures = new uint32_t[forEachCount];
618 if (mForEachSignatures == NULL) {
619 goto error;
620 }
621 mForEachFunctions = new ForEachFunc_t[forEachCount];
622 if (mForEachFunctions == NULL) {
623 goto error;
624 }
625 for (size_t i = 0; i < forEachCount; ++i) {
626 unsigned int tmpSig = 0;
627 char tmpName[MAXLINE];
628
629 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
630 goto error;
631 }
632 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
633 &tmpSig, tmpName) != 2) {
634 ALOGE("Invalid export forEach!: %s", line);
635 goto error;
636 }
637
638 // Lookup the expanded ForEach kernel.
639 strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
640 mForEachSignatures[i] = tmpSig;
641 mForEachFunctions[i] =
642 (ForEachFunc_t) dlsym(mScriptSO, tmpName);
643 if (i != 0 && mForEachFunctions[i] == NULL) {
644 // Ignore missing root.expand functions.
645 // root() is always specified at location 0.
646 ALOGE("Failed to find forEach function address for %s: %s",
647 tmpName, dlerror());
648 goto error;
649 }
650 else {
651 //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]);
652 }
653 }
654 }
655
656 size_t objectSlotCount = 0;
657 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
658 goto error;
659 }
660 if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
661 ALOGE("Invalid object slot count!: %s", line);
662 goto error;
663 }
664
665 if (objectSlotCount > 0) {
666 rsAssert(varCount > 0);
667 for (size_t i = 0; i < objectSlotCount; ++i) {
668 uint32_t varNum = 0;
669 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
670 goto error;
671 }
672 if (sscanf(line, "%u", &varNum) != 1) {
673 ALOGE("Invalid object slot!: %s", line);
674 goto error;
675 }
676
677 if (varNum < varCount) {
678 mFieldIsObject[varNum] = true;
679 }
680 }
681 }
682
683 if (varCount > 0) {
684 mBoundAllocs = new Allocation *[varCount];
685 memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs));
686 }
687
688 if (mScriptSO == (void*)1) {
689 //rsdLookupRuntimeStub(script, "acos");
690 }
691 } else {
692 goto error;
693 }
694 #endif
695 mCtx->unlockMutex();
696 return true;
697
698 #ifdef RS_COMPATIBILITY_LIB
699 error:
700
701 mCtx->unlockMutex();
702 delete[] mInvokeFunctions;
703 delete[] mForEachFunctions;
704 delete[] mFieldAddress;
705 delete[] mFieldIsObject;
706 delete[] mForEachSignatures;
707 delete[] mBoundAllocs;
708 if (mScriptSO) {
709 dlclose(mScriptSO);
710 }
711 return false;
712 #endif
713 }
714
715 #ifndef RS_COMPATIBILITY_LIB
716
717 #ifdef __LP64__
718 #define SYSLIBPATH "/system/lib64"
719 #else
720 #define SYSLIBPATH "/system/lib"
721 #endif
722
findCoreLib(const bcinfo::MetadataExtractor & ME,const char * bitcode,size_t bitcodeSize)723 const char* RsdCpuScriptImpl::findCoreLib(const bcinfo::MetadataExtractor& ME, const char* bitcode,
724 size_t bitcodeSize) {
725 const char* defaultLib = SYSLIBPATH"/libclcore.bc";
726
727 // If we're debugging, use the debug library.
728 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
729 return SYSLIBPATH"/libclcore_debug.bc";
730 }
731
732 // If a callback has been registered to specify a library, use that.
733 RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback();
734 if (selectRTCallback != NULL) {
735 return selectRTCallback((const char*)bitcode, bitcodeSize);
736 }
737
738 // Check for a platform specific library
739 #if defined(ARCH_ARM_HAVE_NEON) && !defined(DISABLE_CLCORE_NEON)
740 enum bcinfo::RSFloatPrecision prec = ME.getRSFloatPrecision();
741 if (prec == bcinfo::RS_FP_Relaxed) {
742 // NEON-capable ARMv7a devices can use an accelerated math library
743 // for all reduced precision scripts.
744 // ARMv8 does not use NEON, as ASIMD can be used with all precision
745 // levels.
746 return SYSLIBPATH"/libclcore_neon.bc";
747 } else {
748 return defaultLib;
749 }
750 #elif defined(__i386__) || defined(__x86_64__)
751 // x86 devices will use an optimized library.
752 return SYSLIBPATH"/libclcore_x86.bc";
753 #else
754 return defaultLib;
755 #endif
756 }
757
758 #endif
759
populateScript(Script * script)760 void RsdCpuScriptImpl::populateScript(Script *script) {
761 #ifndef RS_COMPATIBILITY_LIB
762 // Copy info over to runtime
763 script->mHal.info.exportedFunctionCount = mExecutable->getExportFuncAddrs().size();
764 script->mHal.info.exportedVariableCount = mExecutable->getExportVarAddrs().size();
765 script->mHal.info.exportedForeachFuncList = &mExportedForEachFuncList[0];
766 script->mHal.info.exportedPragmaCount = mExecutable->getPragmaKeys().size();
767 script->mHal.info.exportedPragmaKeyList =
768 const_cast<const char**>(mExecutable->getPragmaKeys().array());
769 script->mHal.info.exportedPragmaValueList =
770 const_cast<const char**>(mExecutable->getPragmaValues().array());
771
772 if (mRootExpand) {
773 script->mHal.info.root = mRootExpand;
774 } else {
775 script->mHal.info.root = mRoot;
776 }
777 #else
778 // Copy info over to runtime
779 script->mHal.info.exportedFunctionCount = mExportedFunctionCount;
780 script->mHal.info.exportedVariableCount = mExportedVariableCount;
781 script->mHal.info.exportedPragmaCount = 0;
782 script->mHal.info.exportedPragmaKeyList = 0;
783 script->mHal.info.exportedPragmaValueList = 0;
784
785 // Bug, need to stash in metadata
786 if (mRootExpand) {
787 script->mHal.info.root = mRootExpand;
788 } else {
789 script->mHal.info.root = mRoot;
790 }
791 #endif
792 }
793
794
795 typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
796
forEachMtlsSetup(const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc,MTLaunchStruct * mtls)797 void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation * ain, Allocation * aout,
798 const void * usr, uint32_t usrLen,
799 const RsScriptCall *sc,
800 MTLaunchStruct *mtls) {
801
802 memset(mtls, 0, sizeof(MTLaunchStruct));
803
804 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface
805 if (ain && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) {
806 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null in allocations");
807 return;
808 }
809 if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) {
810 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null out allocations");
811 return;
812 }
813
814 if (ain != NULL) {
815 const Type *inType = ain->getType();
816
817 mtls->fep.dimX = inType->getDimX();
818 mtls->fep.dimY = inType->getDimY();
819 mtls->fep.dimZ = inType->getDimZ();
820
821 } else if (aout != NULL) {
822 const Type *outType = aout->getType();
823
824 mtls->fep.dimX = outType->getDimX();
825 mtls->fep.dimY = outType->getDimY();
826 mtls->fep.dimZ = outType->getDimZ();
827
828 } else {
829 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
830 return;
831 }
832
833 if (ain != NULL && aout != NULL) {
834 if (!ain->hasSameDims(aout)) {
835 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
836 "Failed to launch kernel; dimensions of input and output allocations do not match.");
837
838 return;
839 }
840 }
841
842 if (!sc || (sc->xEnd == 0)) {
843 mtls->xEnd = mtls->fep.dimX;
844 } else {
845 rsAssert(sc->xStart < mtls->fep.dimX);
846 rsAssert(sc->xEnd <= mtls->fep.dimX);
847 rsAssert(sc->xStart < sc->xEnd);
848 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
849 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
850 if (mtls->xStart >= mtls->xEnd) return;
851 }
852
853 if (!sc || (sc->yEnd == 0)) {
854 mtls->yEnd = mtls->fep.dimY;
855 } else {
856 rsAssert(sc->yStart < mtls->fep.dimY);
857 rsAssert(sc->yEnd <= mtls->fep.dimY);
858 rsAssert(sc->yStart < sc->yEnd);
859 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
860 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
861 if (mtls->yStart >= mtls->yEnd) return;
862 }
863
864 if (!sc || (sc->zEnd == 0)) {
865 mtls->zEnd = mtls->fep.dimZ;
866 } else {
867 rsAssert(sc->zStart < mtls->fep.dimZ);
868 rsAssert(sc->zEnd <= mtls->fep.dimZ);
869 rsAssert(sc->zStart < sc->zEnd);
870 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart);
871 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd);
872 if (mtls->zStart >= mtls->zEnd) return;
873 }
874
875 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
876 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
877 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
878 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
879
880 rsAssert(!ain || (ain->getType()->getDimZ() == 0));
881
882 mtls->rsc = mCtx;
883 mtls->ain = ain;
884 mtls->aout = aout;
885 mtls->fep.usr = usr;
886 mtls->fep.usrLen = usrLen;
887 mtls->mSliceSize = 1;
888 mtls->mSliceNum = 0;
889
890 mtls->fep.ptrIn = NULL;
891 mtls->fep.eStrideIn = 0;
892 mtls->isThreadable = mIsThreadable;
893
894 if (ain) {
895 mtls->fep.ptrIn = (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr;
896 mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes();
897 mtls->fep.yStrideIn = ain->mHal.drvState.lod[0].stride;
898 }
899
900 mtls->fep.ptrOut = NULL;
901 mtls->fep.eStrideOut = 0;
902 if (aout) {
903 mtls->fep.ptrOut = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
904 mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes();
905 mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride;
906 }
907 }
908
forEachMtlsSetup(const Allocation ** ains,uint32_t inLen,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc,MTLaunchStruct * mtls)909 void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation ** ains, uint32_t inLen,
910 Allocation * aout,
911 const void * usr, uint32_t usrLen,
912 const RsScriptCall *sc,
913 MTLaunchStruct *mtls) {
914
915 memset(mtls, 0, sizeof(MTLaunchStruct));
916
917 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface
918 if (ains != NULL) {
919 for (int index = inLen; --index >= 0;) {
920 const Allocation* ain = ains[index];
921
922 if (ain != NULL && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) {
923 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null in allocations");
924 return;
925 }
926 }
927 }
928
929 if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) {
930 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null out allocations");
931 return;
932 }
933
934 if (ains != NULL) {
935 const Allocation *ain0 = ains[0];
936 const Type *inType = ain0->getType();
937
938 mtls->fep.dimX = inType->getDimX();
939 mtls->fep.dimY = inType->getDimY();
940 mtls->fep.dimZ = inType->getDimZ();
941
942 for (int Index = inLen; --Index >= 1;) {
943 if (!ain0->hasSameDims(ains[Index])) {
944 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
945 "Failed to launch kernel; dimensions of input and output allocations do not match.");
946
947 return;
948 }
949 }
950
951 } else if (aout != NULL) {
952 const Type *outType = aout->getType();
953
954 mtls->fep.dimX = outType->getDimX();
955 mtls->fep.dimY = outType->getDimY();
956 mtls->fep.dimZ = outType->getDimZ();
957
958 } else {
959 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
960 return;
961 }
962
963 if (ains != NULL && aout != NULL) {
964 if (!ains[0]->hasSameDims(aout)) {
965 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
966 "Failed to launch kernel; dimensions of input and output allocations do not match.");
967
968 return;
969 }
970 }
971
972 if (!sc || (sc->xEnd == 0)) {
973 mtls->xEnd = mtls->fep.dimX;
974 } else {
975 rsAssert(sc->xStart < mtls->fep.dimX);
976 rsAssert(sc->xEnd <= mtls->fep.dimX);
977 rsAssert(sc->xStart < sc->xEnd);
978 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
979 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
980 if (mtls->xStart >= mtls->xEnd) return;
981 }
982
983 if (!sc || (sc->yEnd == 0)) {
984 mtls->yEnd = mtls->fep.dimY;
985 } else {
986 rsAssert(sc->yStart < mtls->fep.dimY);
987 rsAssert(sc->yEnd <= mtls->fep.dimY);
988 rsAssert(sc->yStart < sc->yEnd);
989 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
990 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
991 if (mtls->yStart >= mtls->yEnd) return;
992 }
993
994 if (!sc || (sc->zEnd == 0)) {
995 mtls->zEnd = mtls->fep.dimZ;
996 } else {
997 rsAssert(sc->zStart < mtls->fep.dimZ);
998 rsAssert(sc->zEnd <= mtls->fep.dimZ);
999 rsAssert(sc->zStart < sc->zEnd);
1000 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart);
1001 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd);
1002 if (mtls->zStart >= mtls->zEnd) return;
1003 }
1004
1005 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
1006 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
1007 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
1008 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
1009
1010 rsAssert(!ains || (ains[0]->getType()->getDimZ() == 0));
1011
1012 mtls->rsc = mCtx;
1013 mtls->ains = ains;
1014 mtls->aout = aout;
1015 mtls->fep.usr = usr;
1016 mtls->fep.usrLen = usrLen;
1017 mtls->mSliceSize = 1;
1018 mtls->mSliceNum = 0;
1019
1020 mtls->fep.ptrIns = NULL;
1021 mtls->fep.eStrideIn = 0;
1022 mtls->isThreadable = mIsThreadable;
1023
1024 if (ains) {
1025 mtls->fep.ptrIns = new const uint8_t*[inLen];
1026 mtls->fep.inStrides = new StridePair[inLen];
1027
1028 for (int index = inLen; --index >= 0;) {
1029 const Allocation *ain = ains[index];
1030
1031 mtls->fep.ptrIns[index] =
1032 (const uint8_t*)ain->mHal.drvState.lod[0].mallocPtr;
1033
1034 mtls->fep.inStrides[index].eStride =
1035 ain->getType()->getElementSizeBytes();
1036 mtls->fep.inStrides[index].yStride =
1037 ain->mHal.drvState.lod[0].stride;
1038 }
1039 }
1040
1041 mtls->fep.ptrOut = NULL;
1042 mtls->fep.eStrideOut = 0;
1043 if (aout) {
1044 mtls->fep.ptrOut = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
1045 mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes();
1046 mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride;
1047 }
1048 }
1049
1050
invokeForEach(uint32_t slot,const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc)1051 void RsdCpuScriptImpl::invokeForEach(uint32_t slot,
1052 const Allocation * ain,
1053 Allocation * aout,
1054 const void * usr,
1055 uint32_t usrLen,
1056 const RsScriptCall *sc) {
1057
1058 MTLaunchStruct mtls;
1059 forEachMtlsSetup(ain, aout, usr, usrLen, sc, &mtls);
1060 forEachKernelSetup(slot, &mtls);
1061
1062 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
1063 mCtx->launchThreads(ain, aout, sc, &mtls);
1064 mCtx->setTLS(oldTLS);
1065 }
1066
invokeForEachMulti(uint32_t slot,const Allocation ** ains,uint32_t inLen,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc)1067 void RsdCpuScriptImpl::invokeForEachMulti(uint32_t slot,
1068 const Allocation ** ains,
1069 uint32_t inLen,
1070 Allocation * aout,
1071 const void * usr,
1072 uint32_t usrLen,
1073 const RsScriptCall *sc) {
1074
1075 MTLaunchStruct mtls;
1076
1077 forEachMtlsSetup(ains, inLen, aout, usr, usrLen, sc, &mtls);
1078 forEachKernelSetup(slot, &mtls);
1079
1080 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
1081 mCtx->launchThreads(ains, inLen, aout, sc, &mtls);
1082 mCtx->setTLS(oldTLS);
1083 }
1084
forEachKernelSetup(uint32_t slot,MTLaunchStruct * mtls)1085 void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) {
1086 mtls->script = this;
1087 mtls->fep.slot = slot;
1088 #ifndef RS_COMPATIBILITY_LIB
1089 rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size());
1090 mtls->kernel = reinterpret_cast<ForEachFunc_t>(
1091 mExecutable->getExportForeachFuncAddrs()[slot]);
1092 rsAssert(mtls->kernel != NULL);
1093 mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second;
1094 #else
1095 mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]);
1096 rsAssert(mtls->kernel != NULL);
1097 mtls->sig = mForEachSignatures[slot];
1098 #endif
1099 }
1100
invokeRoot()1101 int RsdCpuScriptImpl::invokeRoot() {
1102 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
1103 int ret = mRoot();
1104 mCtx->setTLS(oldTLS);
1105 return ret;
1106 }
1107
invokeInit()1108 void RsdCpuScriptImpl::invokeInit() {
1109 if (mInit) {
1110 mInit();
1111 }
1112 }
1113
invokeFreeChildren()1114 void RsdCpuScriptImpl::invokeFreeChildren() {
1115 if (mFreeChildren) {
1116 mFreeChildren();
1117 }
1118 }
1119
invokeFunction(uint32_t slot,const void * params,size_t paramLength)1120 void RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params,
1121 size_t paramLength) {
1122 //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
1123
1124 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
1125 reinterpret_cast<void (*)(const void *, uint32_t)>(
1126 #ifndef RS_COMPATIBILITY_LIB
1127 mExecutable->getExportFuncAddrs()[slot])(params, paramLength);
1128 #else
1129 mInvokeFunctions[slot])(params, paramLength);
1130 #endif
1131 mCtx->setTLS(oldTLS);
1132 }
1133
setGlobalVar(uint32_t slot,const void * data,size_t dataLength)1134 void RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) {
1135 //rsAssert(!script->mFieldIsObject[slot]);
1136 //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
1137
1138 //if (mIntrinsicID) {
1139 //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
1140 //return;
1141 //}
1142
1143 #ifndef RS_COMPATIBILITY_LIB
1144 int32_t *destPtr = reinterpret_cast<int32_t *>(
1145 mExecutable->getExportVarAddrs()[slot]);
1146 #else
1147 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1148 #endif
1149 if (!destPtr) {
1150 //ALOGV("Calling setVar on slot = %i which is null", slot);
1151 return;
1152 }
1153
1154 memcpy(destPtr, data, dataLength);
1155 }
1156
getGlobalVar(uint32_t slot,void * data,size_t dataLength)1157 void RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) {
1158 //rsAssert(!script->mFieldIsObject[slot]);
1159 //ALOGE("getGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
1160
1161 #ifndef RS_COMPATIBILITY_LIB
1162 int32_t *srcPtr = reinterpret_cast<int32_t *>(
1163 mExecutable->getExportVarAddrs()[slot]);
1164 #else
1165 int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1166 #endif
1167 if (!srcPtr) {
1168 //ALOGV("Calling setVar on slot = %i which is null", slot);
1169 return;
1170 }
1171 memcpy(data, srcPtr, dataLength);
1172 }
1173
1174
setGlobalVarWithElemDims(uint32_t slot,const void * data,size_t dataLength,const Element * elem,const uint32_t * dims,size_t dimLength)1175 void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength,
1176 const Element *elem,
1177 const uint32_t *dims, size_t dimLength) {
1178
1179 #ifndef RS_COMPATIBILITY_LIB
1180 int32_t *destPtr = reinterpret_cast<int32_t *>(
1181 mExecutable->getExportVarAddrs()[slot]);
1182 #else
1183 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1184 #endif
1185 if (!destPtr) {
1186 //ALOGV("Calling setVar on slot = %i which is null", slot);
1187 return;
1188 }
1189
1190 // We want to look at dimension in terms of integer components,
1191 // but dimLength is given in terms of bytes.
1192 dimLength /= sizeof(int);
1193
1194 // Only a single dimension is currently supported.
1195 rsAssert(dimLength == 1);
1196 if (dimLength == 1) {
1197 // First do the increment loop.
1198 size_t stride = elem->getSizeBytes();
1199 const char *cVal = reinterpret_cast<const char *>(data);
1200 for (uint32_t i = 0; i < dims[0]; i++) {
1201 elem->incRefs(cVal);
1202 cVal += stride;
1203 }
1204
1205 // Decrement loop comes after (to prevent race conditions).
1206 char *oldVal = reinterpret_cast<char *>(destPtr);
1207 for (uint32_t i = 0; i < dims[0]; i++) {
1208 elem->decRefs(oldVal);
1209 oldVal += stride;
1210 }
1211 }
1212
1213 memcpy(destPtr, data, dataLength);
1214 }
1215
setGlobalBind(uint32_t slot,Allocation * data)1216 void RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) {
1217
1218 //rsAssert(!script->mFieldIsObject[slot]);
1219 //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
1220
1221 #ifndef RS_COMPATIBILITY_LIB
1222 int32_t *destPtr = reinterpret_cast<int32_t *>(
1223 mExecutable->getExportVarAddrs()[slot]);
1224 #else
1225 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1226 #endif
1227 if (!destPtr) {
1228 //ALOGV("Calling setVar on slot = %i which is null", slot);
1229 return;
1230 }
1231
1232 void *ptr = NULL;
1233 mBoundAllocs[slot] = data;
1234 if(data) {
1235 ptr = data->mHal.drvState.lod[0].mallocPtr;
1236 }
1237 memcpy(destPtr, &ptr, sizeof(void *));
1238 }
1239
setGlobalObj(uint32_t slot,ObjectBase * data)1240 void RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) {
1241
1242 //rsAssert(script->mFieldIsObject[slot]);
1243 //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
1244
1245 #ifndef RS_COMPATIBILITY_LIB
1246 int32_t *destPtr = reinterpret_cast<int32_t *>(
1247 mExecutable->getExportVarAddrs()[slot]);
1248 #else
1249 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1250 #endif
1251
1252 if (!destPtr) {
1253 //ALOGV("Calling setVar on slot = %i which is null", slot);
1254 return;
1255 }
1256
1257 rsrSetObject(mCtx->getContext(), (rs_object_base *)destPtr, data);
1258 }
1259
~RsdCpuScriptImpl()1260 RsdCpuScriptImpl::~RsdCpuScriptImpl() {
1261 #ifndef RS_COMPATIBILITY_LIB
1262 if (mExecutable) {
1263 Vector<void *>::const_iterator var_addr_iter =
1264 mExecutable->getExportVarAddrs().begin();
1265 Vector<void *>::const_iterator var_addr_end =
1266 mExecutable->getExportVarAddrs().end();
1267
1268 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter =
1269 mExecutable->getInfo().getObjectSlots().begin();
1270 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end =
1271 mExecutable->getInfo().getObjectSlots().end();
1272
1273 while ((var_addr_iter != var_addr_end) &&
1274 (is_object_iter != is_object_end)) {
1275 // The field address can be NULL if the script-side has optimized
1276 // the corresponding global variable away.
1277 rs_object_base *obj_addr =
1278 reinterpret_cast<rs_object_base *>(*var_addr_iter);
1279 if (*is_object_iter) {
1280 if (*var_addr_iter != NULL && mCtx->getContext() != NULL) {
1281 rsrClearObject(mCtx->getContext(), obj_addr);
1282 }
1283 }
1284 var_addr_iter++;
1285 is_object_iter++;
1286 }
1287 }
1288
1289 if (mCompilerContext) {
1290 delete mCompilerContext;
1291 }
1292 if (mCompilerDriver) {
1293 delete mCompilerDriver;
1294 }
1295 if (mExecutable) {
1296 delete mExecutable;
1297 }
1298 if (mBoundAllocs) {
1299 delete[] mBoundAllocs;
1300 }
1301
1302 for (size_t i = 0; i < mExportedForEachFuncList.size(); i++) {
1303 delete[] mExportedForEachFuncList[i].first;
1304 }
1305 #else
1306 if (mFieldIsObject) {
1307 for (size_t i = 0; i < mExportedVariableCount; ++i) {
1308 if (mFieldIsObject[i]) {
1309 if (mFieldAddress[i] != NULL) {
1310 rs_object_base *obj_addr =
1311 reinterpret_cast<rs_object_base *>(mFieldAddress[i]);
1312 rsrClearObject(mCtx->getContext(), obj_addr);
1313 }
1314 }
1315 }
1316 }
1317
1318 if (mInvokeFunctions) delete[] mInvokeFunctions;
1319 if (mForEachFunctions) delete[] mForEachFunctions;
1320 if (mFieldAddress) delete[] mFieldAddress;
1321 if (mFieldIsObject) delete[] mFieldIsObject;
1322 if (mForEachSignatures) delete[] mForEachSignatures;
1323 if (mBoundAllocs) delete[] mBoundAllocs;
1324 if (mScriptSO) {
1325 dlclose(mScriptSO);
1326 }
1327 #endif
1328 }
1329
getAllocationForPointer(const void * ptr) const1330 Allocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const {
1331 if (!ptr) {
1332 return NULL;
1333 }
1334
1335 for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) {
1336 Allocation *a = mBoundAllocs[ct];
1337 if (!a) continue;
1338 if (a->mHal.drvState.lod[0].mallocPtr == ptr) {
1339 return a;
1340 }
1341 }
1342 ALOGE("rsGetAllocation, failed to find %p", ptr);
1343 return NULL;
1344 }
1345
preLaunch(uint32_t slot,const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc)1346 void RsdCpuScriptImpl::preLaunch(uint32_t slot, const Allocation * ain,
1347 Allocation * aout, const void * usr,
1348 uint32_t usrLen, const RsScriptCall *sc)
1349 {
1350 }
1351
postLaunch(uint32_t slot,const Allocation * ain,Allocation * aout,const void * usr,uint32_t usrLen,const RsScriptCall * sc)1352 void RsdCpuScriptImpl::postLaunch(uint32_t slot, const Allocation * ain,
1353 Allocation * aout, const void * usr,
1354 uint32_t usrLen, const RsScriptCall *sc)
1355 {
1356 }
1357
1358
1359 }
1360 }
1361