blob: 70c9d8f85f0c7d74095cdf6fec07a317f171052d [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
Tim Murraye195a3f2014-03-13 15:04:58 -07007< *
Jason Sams709a0972012-11-15 18:18:04 -08008 * 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
Jason Sams709a0972012-11-15 18:18:04 -080017#include "rsCpuCore.h"
Jason Sams709a0972012-11-15 18:18:04 -080018#include "rsCpuScript.h"
Jason Sams709a0972012-11-15 18:18:04 -080019
Tim Murraye195a3f2014-03-13 15:04:58 -070020#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -070021#ifdef RS_COMPATIBILITY_LIB
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070022 #include <set>
23 #include <string>
Jason Sams110f1812013-03-14 16:02:18 -070024 #include <dlfcn.h>
25 #include <stdio.h>
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070026 #include <stdlib.h>
Jason Sams110f1812013-03-14 16:02:18 -070027 #include <string.h>
Stephen Hinesee48c0b2013-10-30 17:48:30 -070028 #include <sys/stat.h>
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070029 #include <unistd.h>
Jason Sams110f1812013-03-14 16:02:18 -070030#else
31 #include <bcc/BCCContext.h>
Stephen Hines82e0a672014-05-05 15:40:56 -070032 #include <bcc/Config/Config.h>
Jason Sams110f1812013-03-14 16:02:18 -070033 #include <bcc/Renderscript/RSCompilerDriver.h>
34 #include <bcc/Renderscript/RSExecutable.h>
35 #include <bcc/Renderscript/RSInfo.h>
Stephen Hinesb58d9ad2013-06-19 19:26:19 -070036 #include <bcinfo/MetadataExtractor.h>
Stephen Hinesba17ae42013-06-05 17:18:04 -070037 #include <cutils/properties.h>
Stephen Hinesb58d9ad2013-06-19 19:26:19 -070038
39 #include <sys/types.h>
40 #include <sys/wait.h>
41 #include <unistd.h>
Stephen Hines00511322014-01-31 11:20:23 -080042
43 #include <string>
44 #include <vector>
Jason Sams110f1812013-03-14 16:02:18 -070045#endif
Tim Murraye195a3f2014-03-13 15:04:58 -070046#endif
Jason Sams709a0972012-11-15 18:18:04 -080047
Stephen Hinesba17ae42013-06-05 17:18:04 -070048namespace {
Tim Murraye195a3f2014-03-13 15:04:58 -070049#ifndef FAKE_ARM64_BUILD
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070050#ifdef RS_COMPATIBILITY_LIB
51
52// Create a len length string containing random characters from [A-Za-z0-9].
53static std::string getRandomString(size_t len) {
54 char buf[len + 1];
55 for (size_t i = 0; i < len; i++) {
56 uint32_t r = arc4random() & 0xffff;
57 r %= 62;
58 if (r < 26) {
59 // lowercase
60 buf[i] = 'a' + r;
61 } else if (r < 52) {
62 // uppercase
63 buf[i] = 'A' + (r - 26);
64 } else {
65 // Use a number
66 buf[i] = '0' + (r - 52);
67 }
68 }
69 buf[len] = '\0';
70 return std::string(buf);
71}
72
Stephen Hinesee48c0b2013-10-30 17:48:30 -070073// Check if a path exists and attempt to create it if it doesn't.
74static bool ensureCacheDirExists(const char *path) {
75 if (access(path, R_OK | W_OK | X_OK) == 0) {
76 // Done if we can rwx the directory
77 return true;
78 }
79 if (mkdir(path, 0700) == 0) {
80 return true;
81 }
82 return false;
83}
84
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070085// Attempt to load the shared library from origName, but then fall back to
86// creating the symlinked shared library if necessary (to ensure instancing).
87// This function returns the dlopen()-ed handle if successful.
88static void *loadSOHelper(const char *origName, const char *cacheDir,
89 const char *resName) {
90 // Keep track of which .so libraries have been loaded. Once a library is
91 // in the set (per-process granularity), we must instead make a symlink to
92 // the original shared object (randomly named .so file) and load that one
93 // instead. If we don't do this, we end up aliasing global data between
94 // the various Script instances (which are supposed to be completely
95 // independent).
96 static std::set<std::string> LoadedLibraries;
97
98 void *loaded = NULL;
99
100 // Skip everything if we don't even have the original library available.
101 if (access(origName, F_OK) != 0) {
102 return NULL;
103 }
104
105 // Common path is that we have not loaded this Script/library before.
106 if (LoadedLibraries.find(origName) == LoadedLibraries.end()) {
107 loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL);
108 if (loaded) {
109 LoadedLibraries.insert(origName);
110 }
111 return loaded;
112 }
113
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700114 std::string newName(cacheDir);
Stephen Hinesee48c0b2013-10-30 17:48:30 -0700115 newName.append("/com.android.renderscript.cache/");
116
117 if (!ensureCacheDirExists(newName.c_str())) {
118 ALOGE("Could not verify or create cache dir: %s", cacheDir);
119 return NULL;
120 }
121
122 // Construct an appropriately randomized filename for the symlink.
123 newName.append("librs.");
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700124 newName.append(resName);
125 newName.append("#");
126 newName.append(getRandomString(6)); // 62^6 potential filename variants.
127 newName.append(".so");
128
129 int r = symlink(origName, newName.c_str());
130 if (r != 0) {
131 ALOGE("Could not create symlink %s -> %s", newName.c_str(), origName);
132 return NULL;
133 }
134 loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL);
135 r = unlink(newName.c_str());
136 if (r != 0) {
137 ALOGE("Could not unlink symlink %s", newName.c_str());
138 }
139 if (loaded) {
140 LoadedLibraries.insert(newName.c_str());
141 }
142
143 return loaded;
144}
145
146// Load the shared library referred to by cacheDir and resName. If we have
147// already loaded this library, we instead create a new symlink (in the
148// cache dir) and then load that. We then immediately destroy the symlink.
149// This is required behavior to implement script instancing for the support
150// library, since shared objects are loaded and de-duped by name only.
151static void *loadSharedLibrary(const char *cacheDir, const char *resName) {
152 void *loaded = NULL;
153 //arc4random_stir();
154#ifndef RS_SERVER
155 std::string scriptSOName(cacheDir);
156 size_t cutPos = scriptSOName.rfind("cache");
157 if (cutPos != std::string::npos) {
158 scriptSOName.erase(cutPos);
159 } else {
160 ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir);
161 }
162 scriptSOName.append("/lib/librs.");
163#else
164 std::string scriptSOName("lib");
165#endif
166 scriptSOName.append(resName);
167 scriptSOName.append(".so");
168
169 // We should check if we can load the library from the standard app
170 // location for shared libraries first.
171 loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName);
172
173 if (loaded == NULL) {
174 ALOGE("Unable to open shared library (%s): %s",
175 scriptSOName.c_str(), dlerror());
176
177 // One final attempt to find the library in "/system/lib".
178 // We do this to allow bundled applications to use the compatibility
179 // library fallback path. Those applications don't have a private
180 // library path, so they need to install to the system directly.
181 // Note that this is really just a testing path.
182 android::String8 scriptSONameSystem("/system/lib/librs.");
183 scriptSONameSystem.append(resName);
184 scriptSONameSystem.append(".so");
185 loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir,
186 resName);
187 if (loaded == NULL) {
188 ALOGE("Unable to open system shared library (%s): %s",
189 scriptSONameSystem.c_str(), dlerror());
190 }
191 }
192
193 return loaded;
194}
195
196
197#else
Stephen Hinesba17ae42013-06-05 17:18:04 -0700198static bool is_force_recompile() {
199#ifdef RS_SERVER
200 return false;
201#else
202 char buf[PROPERTY_VALUE_MAX];
203
204 // Re-compile if floating point precision has been overridden.
205 property_get("debug.rs.precision", buf, "");
206 if (buf[0] != '\0') {
207 return true;
208 }
209
210 // Re-compile if debug.rs.forcerecompile is set.
211 property_get("debug.rs.forcerecompile", buf, "0");
212 if ((::strcmp(buf, "1") == 0) || (::strcmp(buf, "true") == 0)) {
213 return true;
214 } else {
215 return false;
216 }
217#endif // RS_SERVER
218}
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700219
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700220const static char *BCC_EXE_PATH = "/system/bin/bcc";
221
222static bool compileBitcode(const char *cacheDir,
223 const char *resName,
224 const char *bitcode,
225 size_t bitcodeSize,
Stephen Hines00511322014-01-31 11:20:23 -0800226 const char *core_lib,
227 bool useRSDebugContext,
228 const char *bccPluginName) {
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700229 rsAssert(cacheDir && resName && bitcode && bitcodeSize && core_lib);
230
231 android::String8 bcFilename(cacheDir);
232 bcFilename.append("/");
233 bcFilename.append(resName);
234 bcFilename.append(".bc");
235 FILE *bcfile = fopen(bcFilename.string(), "w");
236 if (!bcfile) {
237 ALOGE("Could not write to %s", bcFilename.string());
238 return false;
239 }
240 size_t nwritten = fwrite(bitcode, 1, bitcodeSize, bcfile);
241 fclose(bcfile);
242 if (nwritten != bitcodeSize) {
243 ALOGE("Could not write %zu bytes to %s", bitcodeSize,
244 bcFilename.string());
245 return false;
246 }
247
248 pid_t pid = fork();
Stephen Hines00511322014-01-31 11:20:23 -0800249
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700250 switch (pid) {
251 case -1: { // Error occurred (we attempt no recovery)
252 ALOGE("Couldn't fork for bcc compiler execution");
253 return false;
254 }
255 case 0: { // Child process
Stephen Hines00511322014-01-31 11:20:23 -0800256 std::vector<std::string> args;
257 args.push_back(BCC_EXE_PATH);
258 args.push_back("-o");
259 args.push_back(resName);
260 args.push_back("-output_path");
261 args.push_back(cacheDir);
262 args.push_back("-bclib");
263 args.push_back(core_lib);
Stephen Hines82e0a672014-05-05 15:40:56 -0700264 args.push_back("-mtriple");
265 args.push_back(DEFAULT_TARGET_TRIPLE_STRING);
Stephen Hines00511322014-01-31 11:20:23 -0800266
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700267 // Execute the bcc compiler.
Stephen Hines00511322014-01-31 11:20:23 -0800268 if (useRSDebugContext) {
269 args.push_back("-rs-debug-ctx");
270 } else {
271 // Only load additional libraries for compiles that don't use
272 // the debug context.
273 if (bccPluginName && strlen(bccPluginName) > 0) {
274 args.push_back("-load");
275 args.push_back(bccPluginName);
276 }
277 }
278
279 args.push_back(bcFilename.string());
280
281 const char **cargs = new const char *[args.size() + 1];
282 for (uint32_t i = 0; i < args.size(); i++) {
283 cargs[i] = args[i].c_str();
284 }
285 cargs[args.size()] = NULL;
286
287 execv(BCC_EXE_PATH, (char *const *)cargs);
288
289 delete [] cargs;
290 ALOGE("execv() failed: %s", strerror(errno));
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700291 abort();
292 return false;
293 }
294 default: { // Parent process (actual driver)
295 // Wait on child process to finish compiling the source.
296 int status = 0;
297 pid_t w = waitpid(pid, &status, 0);
298 if (w == -1) {
299 ALOGE("Could not wait for bcc compiler");
300 return false;
301 }
302
303 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
304 return true;
305 }
306
307 ALOGE("bcc compiler terminated unexpectedly");
308 return false;
309 }
310 }
311}
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700312
Stephen Hinesba17ae42013-06-05 17:18:04 -0700313#endif // !defined(RS_COMPATIBILITY_LIB)
Tim Murraye195a3f2014-03-13 15:04:58 -0700314#endif
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700315} // namespace
Stephen Hinesba17ae42013-06-05 17:18:04 -0700316
Jason Sams709a0972012-11-15 18:18:04 -0800317namespace android {
318namespace renderscript {
319
Jason Sams110f1812013-03-14 16:02:18 -0700320#ifdef RS_COMPATIBILITY_LIB
321#define MAXLINE 500
322#define MAKE_STR_HELPER(S) #S
323#define MAKE_STR(S) MAKE_STR_HELPER(S)
324#define EXPORT_VAR_STR "exportVarCount: "
325#define EXPORT_VAR_STR_LEN strlen(EXPORT_VAR_STR)
326#define EXPORT_FUNC_STR "exportFuncCount: "
327#define EXPORT_FUNC_STR_LEN strlen(EXPORT_FUNC_STR)
328#define EXPORT_FOREACH_STR "exportForEachCount: "
329#define EXPORT_FOREACH_STR_LEN strlen(EXPORT_FOREACH_STR)
330#define OBJECT_SLOT_STR "objectSlotCount: "
331#define OBJECT_SLOT_STR_LEN strlen(OBJECT_SLOT_STR)
332
333// Copy up to a newline or size chars from str -> s, updating str
334// Returns s when successful and NULL when '\0' is finally reached.
335static char* strgets(char *s, int size, const char **ppstr) {
336 if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
337 return NULL;
338 }
339
340 int i;
341 for (i = 0; i < (size - 1); i++) {
342 s[i] = **ppstr;
343 (*ppstr)++;
344 if (s[i] == '\0') {
345 return s;
346 } else if (s[i] == '\n') {
347 s[i+1] = '\0';
348 return s;
349 }
350 }
351
352 // size has been exceeded.
353 s[i] = '\0';
354
355 return s;
356}
357#endif
Jason Sams709a0972012-11-15 18:18:04 -0800358
359RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) {
360 mCtx = ctx;
361 mScript = s;
362
Tim Murraye195a3f2014-03-13 15:04:58 -0700363#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -0700364#ifdef RS_COMPATIBILITY_LIB
365 mScriptSO = NULL;
366 mInvokeFunctions = NULL;
367 mForEachFunctions = NULL;
368 mFieldAddress = NULL;
369 mFieldIsObject = NULL;
370 mForEachSignatures = NULL;
371#else
372 mCompilerContext = NULL;
373 mCompilerDriver = NULL;
374 mExecutable = NULL;
375#endif
376
Tim Murraye195a3f2014-03-13 15:04:58 -0700377
Jason Sams709a0972012-11-15 18:18:04 -0800378 mRoot = NULL;
379 mRootExpand = NULL;
380 mInit = NULL;
381 mFreeChildren = NULL;
382
Jason Sams709a0972012-11-15 18:18:04 -0800383
384 mBoundAllocs = NULL;
385 mIntrinsicData = NULL;
386 mIsThreadable = true;
Tim Murraye195a3f2014-03-13 15:04:58 -0700387#endif
Jason Sams709a0972012-11-15 18:18:04 -0800388}
389
390
391bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
392 uint8_t const *bitcode, size_t bitcodeSize,
Stephen Hines00511322014-01-31 11:20:23 -0800393 uint32_t flags, char const *bccPluginName) {
Jason Sams709a0972012-11-15 18:18:04 -0800394 //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
395 //ALOGE("rsdScriptInit %p %p", rsc, script);
396
397 mCtx->lockMutex();
Tim Murraye195a3f2014-03-13 15:04:58 -0700398#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -0700399#ifndef RS_COMPATIBILITY_LIB
Stephen Hinesba17ae42013-06-05 17:18:04 -0700400 bcc::RSExecutable *exec = NULL;
Stephen Hines00511322014-01-31 11:20:23 -0800401 bool useRSDebugContext = false;
Jason Sams709a0972012-11-15 18:18:04 -0800402
403 mCompilerContext = NULL;
404 mCompilerDriver = NULL;
405 mExecutable = NULL;
406
407 mCompilerContext = new bcc::BCCContext();
408 if (mCompilerContext == NULL) {
409 ALOGE("bcc: FAILS to create compiler context (out of memory)");
410 mCtx->unlockMutex();
411 return false;
412 }
413
414 mCompilerDriver = new bcc::RSCompilerDriver();
415 if (mCompilerDriver == NULL) {
416 ALOGE("bcc: FAILS to create compiler driver (out of memory)");
417 mCtx->unlockMutex();
418 return false;
419 }
420
421 mCompilerDriver->setRSRuntimeLookupFunction(lookupRuntimeStub);
422 mCompilerDriver->setRSRuntimeLookupContext(this);
423
Stephen Hinesb7d9c802013-04-29 19:13:09 -0700424 // Run any compiler setup functions we have been provided with.
425 RSSetupCompilerCallback setupCompilerCallback =
426 mCtx->getSetupCompilerCallback();
427 if (setupCompilerCallback != NULL) {
428 setupCompilerCallback(mCompilerDriver);
429 }
430
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700431 const char *core_lib = bcc::RSInfo::LibCLCorePath;
432
433 bcinfo::MetadataExtractor ME((const char *) bitcode, bitcodeSize);
434 if (!ME.extract()) {
435 ALOGE("Could not extract metadata from bitcode");
436 return false;
437 }
438
439 enum bcinfo::RSFloatPrecision prec = ME.getRSFloatPrecision();
440 switch (prec) {
441 case bcinfo::RS_FP_Imprecise:
442 case bcinfo::RS_FP_Relaxed:
443#if defined(ARCH_ARM_HAVE_NEON)
444 // NEON-capable devices can use an accelerated math library for all
445 // reduced precision scripts.
446 core_lib = bcc::RSInfo::LibCLCoreNEONPath;
447#endif
448 break;
449 case bcinfo::RS_FP_Full:
450 break;
451 default:
452 ALOGE("Unknown precision for bitcode");
453 return false;
454 }
455
Stephen Hines4da42502013-10-03 14:57:51 -0700456#if defined(__i386__)
457 // x86 devices will use an optimized library.
Tim Murraye195a3f2014-03-13 15:04:58 -0700458 core_lib = bcc::RSInfo::LibCLCoreX86Path;
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700459#endif
460
Stephen Hines1d476622013-03-29 22:08:49 -0700461 RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback();
462 if (selectRTCallback != NULL) {
463 core_lib = selectRTCallback((const char *)bitcode, bitcodeSize);
464 }
Stephen Hinescca3d6c2013-04-15 01:06:39 -0700465
466 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
467 // Use the libclcore_debug.bc instead of the default library.
468 core_lib = bcc::RSInfo::LibCLCoreDebugPath;
Stephen Hinesf47e8b42013-04-18 01:06:29 -0700469 mCompilerDriver->setDebugContext(true);
Stephen Hines00511322014-01-31 11:20:23 -0800470 useRSDebugContext = true;
Stephen Hinesba17ae42013-06-05 17:18:04 -0700471 // Skip the cache lookup
472 } else if (!is_force_recompile()) {
473 // Attempt to just load the script from cache first if we can.
474 exec = mCompilerDriver->loadScript(cacheDir, resName,
475 (const char *)bitcode, bitcodeSize);
Stephen Hinescca3d6c2013-04-15 01:06:39 -0700476 }
Stephen Hinesba17ae42013-06-05 17:18:04 -0700477
Stephen Hinesba17ae42013-06-05 17:18:04 -0700478 if (exec == NULL) {
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700479 bool built = compileBitcode(cacheDir, resName, (const char *)bitcode,
Stephen Hines00511322014-01-31 11:20:23 -0800480 bitcodeSize, core_lib, useRSDebugContext,
481 bccPluginName);
Stephen Hinesba17ae42013-06-05 17:18:04 -0700482 if (built) {
483 exec = mCompilerDriver->loadScript(cacheDir, resName,
484 (const char *)bitcode,
485 bitcodeSize);
486 }
487 }
Jason Sams709a0972012-11-15 18:18:04 -0800488
489 if (exec == NULL) {
490 ALOGE("bcc: FAILS to prepare executable for '%s'", resName);
491 mCtx->unlockMutex();
492 return false;
493 }
494
495 mExecutable = exec;
496
497 exec->setThreadable(mIsThreadable);
498 if (!exec->syncInfo()) {
499 ALOGW("bcc: FAILS to synchronize the RS info file to the disk");
500 }
501
502 mRoot = reinterpret_cast<int (*)()>(exec->getSymbolAddress("root"));
503 mRootExpand =
504 reinterpret_cast<int (*)()>(exec->getSymbolAddress("root.expand"));
505 mInit = reinterpret_cast<void (*)()>(exec->getSymbolAddress("init"));
506 mFreeChildren =
507 reinterpret_cast<void (*)()>(exec->getSymbolAddress(".rs.dtor"));
508
509
Stephen Hines1d476622013-03-29 22:08:49 -0700510 const bcc::RSInfo *info = &mExecutable->getInfo();
Jason Sams709a0972012-11-15 18:18:04 -0800511 if (info->getExportVarNames().size()) {
512 mBoundAllocs = new Allocation *[info->getExportVarNames().size()];
513 memset(mBoundAllocs, 0, sizeof(void *) * info->getExportVarNames().size());
514 }
515
Jason Sams110f1812013-03-14 16:02:18 -0700516#else
517
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700518 mScriptSO = loadSharedLibrary(cacheDir, resName);
Jason Sams110f1812013-03-14 16:02:18 -0700519
520 if (mScriptSO) {
521 char line[MAXLINE];
522 mRoot = (RootFunc_t) dlsym(mScriptSO, "root");
523 if (mRoot) {
524 //ALOGE("Found root(): %p", mRoot);
525 }
526 mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand");
527 if (mRootExpand) {
528 //ALOGE("Found root.expand(): %p", mRootExpand);
529 }
530 mInit = (InvokeFunc_t) dlsym(mScriptSO, "init");
531 if (mInit) {
532 //ALOGE("Found init(): %p", mInit);
533 }
534 mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor");
535 if (mFreeChildren) {
536 //ALOGE("Found .rs.dtor(): %p", mFreeChildren);
537 }
538
539 const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info");
540 if (rsInfo) {
541 //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo);
542 }
543
544 size_t varCount = 0;
545 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
546 goto error;
547 }
548 if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
549 ALOGE("Invalid export var count!: %s", line);
550 goto error;
551 }
552
553 mExportedVariableCount = varCount;
554 //ALOGE("varCount: %zu", varCount);
555 if (varCount > 0) {
556 // Start by creating/zeroing this member, since we don't want to
557 // accidentally clean up invalid pointers later (if we error out).
558 mFieldIsObject = new bool[varCount];
559 if (mFieldIsObject == NULL) {
560 goto error;
561 }
562 memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject));
563 mFieldAddress = new void*[varCount];
564 if (mFieldAddress == NULL) {
565 goto error;
566 }
567 for (size_t i = 0; i < varCount; ++i) {
568 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
569 goto error;
570 }
571 char *c = strrchr(line, '\n');
572 if (c) {
573 *c = '\0';
574 }
575 mFieldAddress[i] = dlsym(mScriptSO, line);
576 if (mFieldAddress[i] == NULL) {
577 ALOGE("Failed to find variable address for %s: %s",
578 line, dlerror());
579 // Not a critical error if we don't find a global variable.
580 }
581 else {
582 //ALOGE("Found variable %s at %p", line,
583 //mFieldAddress[i]);
584 }
585 }
586 }
587
588 size_t funcCount = 0;
589 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
590 goto error;
591 }
592 if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
593 ALOGE("Invalid export func count!: %s", line);
594 goto error;
595 }
596
597 mExportedFunctionCount = funcCount;
598 //ALOGE("funcCount: %zu", funcCount);
599
600 if (funcCount > 0) {
601 mInvokeFunctions = new InvokeFunc_t[funcCount];
602 if (mInvokeFunctions == NULL) {
603 goto error;
604 }
605 for (size_t i = 0; i < funcCount; ++i) {
606 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
607 goto error;
608 }
609 char *c = strrchr(line, '\n');
610 if (c) {
611 *c = '\0';
612 }
613
614 mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line);
615 if (mInvokeFunctions[i] == NULL) {
616 ALOGE("Failed to get function address for %s(): %s",
617 line, dlerror());
618 goto error;
619 }
620 else {
621 //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]);
622 }
623 }
624 }
625
626 size_t forEachCount = 0;
627 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
628 goto error;
629 }
630 if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
631 ALOGE("Invalid export forEach count!: %s", line);
632 goto error;
633 }
634
635 if (forEachCount > 0) {
636
637 mForEachSignatures = new uint32_t[forEachCount];
638 if (mForEachSignatures == NULL) {
639 goto error;
640 }
641 mForEachFunctions = new ForEachFunc_t[forEachCount];
642 if (mForEachFunctions == NULL) {
643 goto error;
644 }
645 for (size_t i = 0; i < forEachCount; ++i) {
646 unsigned int tmpSig = 0;
647 char tmpName[MAXLINE];
648
649 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
650 goto error;
651 }
652 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
653 &tmpSig, tmpName) != 2) {
654 ALOGE("Invalid export forEach!: %s", line);
655 goto error;
656 }
657
658 // Lookup the expanded ForEach kernel.
659 strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
660 mForEachSignatures[i] = tmpSig;
661 mForEachFunctions[i] =
662 (ForEachFunc_t) dlsym(mScriptSO, tmpName);
Stephen Hinesef7481e2013-04-09 19:05:27 -0700663 if (i != 0 && mForEachFunctions[i] == NULL) {
Jason Sams110f1812013-03-14 16:02:18 -0700664 // Ignore missing root.expand functions.
665 // root() is always specified at location 0.
Stephen Hinesef7481e2013-04-09 19:05:27 -0700666 ALOGE("Failed to find forEach function address for %s: %s",
667 tmpName, dlerror());
668 goto error;
Jason Sams110f1812013-03-14 16:02:18 -0700669 }
670 else {
671 //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]);
672 }
673 }
674 }
675
676 size_t objectSlotCount = 0;
677 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
678 goto error;
679 }
680 if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
681 ALOGE("Invalid object slot count!: %s", line);
682 goto error;
683 }
684
685 if (objectSlotCount > 0) {
686 rsAssert(varCount > 0);
687 for (size_t i = 0; i < objectSlotCount; ++i) {
688 uint32_t varNum = 0;
689 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
690 goto error;
691 }
692 if (sscanf(line, "%u", &varNum) != 1) {
693 ALOGE("Invalid object slot!: %s", line);
694 goto error;
695 }
696
697 if (varNum < varCount) {
698 mFieldIsObject[varNum] = true;
699 }
700 }
701 }
702
703 if (varCount > 0) {
704 mBoundAllocs = new Allocation *[varCount];
705 memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs));
706 }
707
708 if (mScriptSO == (void*)1) {
709 //rsdLookupRuntimeStub(script, "acos");
710 }
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700711 } else {
712 goto error;
Jason Sams110f1812013-03-14 16:02:18 -0700713 }
714#endif
Tim Murraye195a3f2014-03-13 15:04:58 -0700715#endif // FAKE_ARM64_BUILD
Jason Sams709a0972012-11-15 18:18:04 -0800716 mCtx->unlockMutex();
717 return true;
Jason Sams110f1812013-03-14 16:02:18 -0700718
719#ifdef RS_COMPATIBILITY_LIB
720error:
721
722 mCtx->unlockMutex();
723 delete[] mInvokeFunctions;
724 delete[] mForEachFunctions;
725 delete[] mFieldAddress;
726 delete[] mFieldIsObject;
727 delete[] mForEachSignatures;
728 delete[] mBoundAllocs;
729 if (mScriptSO) {
730 dlclose(mScriptSO);
731 }
732 return false;
733#endif
Jason Sams709a0972012-11-15 18:18:04 -0800734}
735
736void RsdCpuScriptImpl::populateScript(Script *script) {
Tim Murraye195a3f2014-03-13 15:04:58 -0700737#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -0700738#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800739 const bcc::RSInfo *info = &mExecutable->getInfo();
740
741 // Copy info over to runtime
742 script->mHal.info.exportedFunctionCount = info->getExportFuncNames().size();
743 script->mHal.info.exportedVariableCount = info->getExportVarNames().size();
Tobias Grosser47935ac2013-06-17 11:47:26 -0700744 script->mHal.info.exportedForeachFuncList = info->getExportForeachFuncs().array();
Jason Sams709a0972012-11-15 18:18:04 -0800745 script->mHal.info.exportedPragmaCount = info->getPragmas().size();
746 script->mHal.info.exportedPragmaKeyList =
747 const_cast<const char**>(mExecutable->getPragmaKeys().array());
748 script->mHal.info.exportedPragmaValueList =
749 const_cast<const char**>(mExecutable->getPragmaValues().array());
750
751 if (mRootExpand) {
752 script->mHal.info.root = mRootExpand;
753 } else {
754 script->mHal.info.root = mRoot;
755 }
Jason Sams110f1812013-03-14 16:02:18 -0700756#else
757 // Copy info over to runtime
758 script->mHal.info.exportedFunctionCount = mExportedFunctionCount;
759 script->mHal.info.exportedVariableCount = mExportedVariableCount;
760 script->mHal.info.exportedPragmaCount = 0;
761 script->mHal.info.exportedPragmaKeyList = 0;
762 script->mHal.info.exportedPragmaValueList = 0;
763
764 // Bug, need to stash in metadata
765 if (mRootExpand) {
766 script->mHal.info.root = mRootExpand;
767 } else {
768 script->mHal.info.root = mRoot;
769 }
770#endif
Tim Murraye195a3f2014-03-13 15:04:58 -0700771#endif
Jason Sams709a0972012-11-15 18:18:04 -0800772}
773
Jason Sams709a0972012-11-15 18:18:04 -0800774
775typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
776
777void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation * ain, Allocation * aout,
778 const void * usr, uint32_t usrLen,
779 const RsScriptCall *sc,
780 MTLaunchStruct *mtls) {
781
782 memset(mtls, 0, sizeof(MTLaunchStruct));
783
Tim Murray3a25fdd2013-02-22 17:56:56 -0800784 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface
785 if (ain && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) {
Jason Samsddceab92013-08-07 13:02:32 -0700786 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null in allocations");
Tim Murray3a25fdd2013-02-22 17:56:56 -0800787 return;
788 }
789 if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) {
Jason Samsddceab92013-08-07 13:02:32 -0700790 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null out allocations");
Tim Murray3a25fdd2013-02-22 17:56:56 -0800791 return;
792 }
793
Jason Sams709a0972012-11-15 18:18:04 -0800794 if (ain) {
795 mtls->fep.dimX = ain->getType()->getDimX();
796 mtls->fep.dimY = ain->getType()->getDimY();
797 mtls->fep.dimZ = ain->getType()->getDimZ();
798 //mtls->dimArray = ain->getType()->getDimArray();
799 } else if (aout) {
800 mtls->fep.dimX = aout->getType()->getDimX();
801 mtls->fep.dimY = aout->getType()->getDimY();
802 mtls->fep.dimZ = aout->getType()->getDimZ();
803 //mtls->dimArray = aout->getType()->getDimArray();
804 } else {
805 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
806 return;
807 }
808
809 if (!sc || (sc->xEnd == 0)) {
810 mtls->xEnd = mtls->fep.dimX;
811 } else {
812 rsAssert(sc->xStart < mtls->fep.dimX);
813 rsAssert(sc->xEnd <= mtls->fep.dimX);
814 rsAssert(sc->xStart < sc->xEnd);
815 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
816 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
817 if (mtls->xStart >= mtls->xEnd) return;
818 }
819
820 if (!sc || (sc->yEnd == 0)) {
821 mtls->yEnd = mtls->fep.dimY;
822 } else {
823 rsAssert(sc->yStart < mtls->fep.dimY);
824 rsAssert(sc->yEnd <= mtls->fep.dimY);
825 rsAssert(sc->yStart < sc->yEnd);
826 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
827 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
828 if (mtls->yStart >= mtls->yEnd) return;
829 }
830
Tim Murrayd4ecb172013-02-07 12:17:03 -0800831 if (!sc || (sc->zEnd == 0)) {
832 mtls->zEnd = mtls->fep.dimZ;
833 } else {
834 rsAssert(sc->zStart < mtls->fep.dimZ);
835 rsAssert(sc->zEnd <= mtls->fep.dimZ);
836 rsAssert(sc->zStart < sc->zEnd);
837 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart);
838 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd);
839 if (mtls->zStart >= mtls->zEnd) return;
840 }
841
Jason Sams709a0972012-11-15 18:18:04 -0800842 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
843 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
844 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
845 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
846
847 rsAssert(!ain || (ain->getType()->getDimZ() == 0));
848
849 mtls->rsc = mCtx;
850 mtls->ain = ain;
851 mtls->aout = aout;
852 mtls->fep.usr = usr;
853 mtls->fep.usrLen = usrLen;
854 mtls->mSliceSize = 1;
855 mtls->mSliceNum = 0;
856
857 mtls->fep.ptrIn = NULL;
858 mtls->fep.eStrideIn = 0;
859 mtls->isThreadable = mIsThreadable;
860
861 if (ain) {
862 mtls->fep.ptrIn = (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr;
863 mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes();
864 mtls->fep.yStrideIn = ain->mHal.drvState.lod[0].stride;
865 }
866
867 mtls->fep.ptrOut = NULL;
868 mtls->fep.eStrideOut = 0;
869 if (aout) {
870 mtls->fep.ptrOut = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
871 mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes();
872 mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride;
873 }
874}
875
876
877void RsdCpuScriptImpl::invokeForEach(uint32_t slot,
878 const Allocation * ain,
879 Allocation * aout,
880 const void * usr,
881 uint32_t usrLen,
882 const RsScriptCall *sc) {
883
884 MTLaunchStruct mtls;
885 forEachMtlsSetup(ain, aout, usr, usrLen, sc, &mtls);
886 forEachKernelSetup(slot, &mtls);
887
888 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
889 mCtx->launchThreads(ain, aout, sc, &mtls);
890 mCtx->setTLS(oldTLS);
891}
892
893void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) {
Jason Sams709a0972012-11-15 18:18:04 -0800894 mtls->script = this;
895 mtls->fep.slot = slot;
Tim Murraye195a3f2014-03-13 15:04:58 -0700896#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -0700897#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800898 rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size());
899 mtls->kernel = reinterpret_cast<ForEachFunc_t>(
900 mExecutable->getExportForeachFuncAddrs()[slot]);
901 rsAssert(mtls->kernel != NULL);
902 mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second;
Jason Sams110f1812013-03-14 16:02:18 -0700903#else
904 mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]);
905 rsAssert(mtls->kernel != NULL);
906 mtls->sig = mForEachSignatures[slot];
907#endif
Tim Murraye195a3f2014-03-13 15:04:58 -0700908#endif
Jason Sams709a0972012-11-15 18:18:04 -0800909}
910
911int RsdCpuScriptImpl::invokeRoot() {
912 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
Tim Murraye195a3f2014-03-13 15:04:58 -0700913#ifndef FAKE_ARM64_BUILD
Jason Sams709a0972012-11-15 18:18:04 -0800914 int ret = mRoot();
Tim Murraye195a3f2014-03-13 15:04:58 -0700915#else
916 int ret = 0;
917#endif
Jason Sams709a0972012-11-15 18:18:04 -0800918 mCtx->setTLS(oldTLS);
919 return ret;
920}
921
922void RsdCpuScriptImpl::invokeInit() {
Tim Murraye195a3f2014-03-13 15:04:58 -0700923#ifndef FAKE_ARM64_BUILD
Jason Sams709a0972012-11-15 18:18:04 -0800924 if (mInit) {
925 mInit();
926 }
Tim Murraye195a3f2014-03-13 15:04:58 -0700927#endif
Jason Sams709a0972012-11-15 18:18:04 -0800928}
929
930void RsdCpuScriptImpl::invokeFreeChildren() {
Tim Murraye195a3f2014-03-13 15:04:58 -0700931#ifndef FAKE_ARM64_BUILD
Jason Sams709a0972012-11-15 18:18:04 -0800932 if (mFreeChildren) {
933 mFreeChildren();
934 }
Tim Murraye195a3f2014-03-13 15:04:58 -0700935#endif
Jason Sams709a0972012-11-15 18:18:04 -0800936}
937
938void RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params,
939 size_t paramLength) {
940 //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
941
942 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
Tim Murraye195a3f2014-03-13 15:04:58 -0700943#ifndef FAKE_ARM64_BUILD
Jason Sams709a0972012-11-15 18:18:04 -0800944 reinterpret_cast<void (*)(const void *, uint32_t)>(
Jason Sams110f1812013-03-14 16:02:18 -0700945#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800946 mExecutable->getExportFuncAddrs()[slot])(params, paramLength);
Jason Sams110f1812013-03-14 16:02:18 -0700947#else
948 mInvokeFunctions[slot])(params, paramLength);
949#endif
Tim Murraye195a3f2014-03-13 15:04:58 -0700950#endif
Jason Sams709a0972012-11-15 18:18:04 -0800951 mCtx->setTLS(oldTLS);
952}
953
954void RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) {
955 //rsAssert(!script->mFieldIsObject[slot]);
956 //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
957
958 //if (mIntrinsicID) {
959 //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
960 //return;
961 //}
962
Tim Murraye195a3f2014-03-13 15:04:58 -0700963#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -0700964#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800965 int32_t *destPtr = reinterpret_cast<int32_t *>(
966 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -0700967#else
968 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
969#endif
Tim Murraye195a3f2014-03-13 15:04:58 -0700970#else
971 int32_t *destPtr = NULL;
972#endif
Jason Sams709a0972012-11-15 18:18:04 -0800973 if (!destPtr) {
974 //ALOGV("Calling setVar on slot = %i which is null", slot);
975 return;
976 }
977
978 memcpy(destPtr, data, dataLength);
979}
980
Tim Murray9c642392013-04-11 13:29:59 -0700981void RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) {
982 //rsAssert(!script->mFieldIsObject[slot]);
983 //ALOGE("getGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
984
Tim Murraye195a3f2014-03-13 15:04:58 -0700985#ifndef FAKE_ARM64_BUILD
Tim Murray9c642392013-04-11 13:29:59 -0700986#ifndef RS_COMPATIBILITY_LIB
987 int32_t *srcPtr = reinterpret_cast<int32_t *>(
988 mExecutable->getExportVarAddrs()[slot]);
989#else
990 int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
991#endif
Tim Murraye195a3f2014-03-13 15:04:58 -0700992#else
993 int32_t *srcPtr = NULL;
994#endif
Tim Murray9c642392013-04-11 13:29:59 -0700995 if (!srcPtr) {
996 //ALOGV("Calling setVar on slot = %i which is null", slot);
997 return;
998 }
999 memcpy(data, srcPtr, dataLength);
1000}
1001
1002
Jason Sams709a0972012-11-15 18:18:04 -08001003void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength,
1004 const Element *elem,
1005 const size_t *dims, size_t dimLength) {
1006
Tim Murraye195a3f2014-03-13 15:04:58 -07001007#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -07001008#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001009 int32_t *destPtr = reinterpret_cast<int32_t *>(
1010 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001011#else
1012 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1013#endif
Tim Murraye195a3f2014-03-13 15:04:58 -07001014#else
1015 int32_t *destPtr = NULL;
1016#endif
Jason Sams709a0972012-11-15 18:18:04 -08001017 if (!destPtr) {
1018 //ALOGV("Calling setVar on slot = %i which is null", slot);
1019 return;
1020 }
1021
1022 // We want to look at dimension in terms of integer components,
1023 // but dimLength is given in terms of bytes.
1024 dimLength /= sizeof(int);
1025
1026 // Only a single dimension is currently supported.
1027 rsAssert(dimLength == 1);
1028 if (dimLength == 1) {
1029 // First do the increment loop.
1030 size_t stride = elem->getSizeBytes();
1031 const char *cVal = reinterpret_cast<const char *>(data);
1032 for (size_t i = 0; i < dims[0]; i++) {
1033 elem->incRefs(cVal);
1034 cVal += stride;
1035 }
1036
1037 // Decrement loop comes after (to prevent race conditions).
1038 char *oldVal = reinterpret_cast<char *>(destPtr);
1039 for (size_t i = 0; i < dims[0]; i++) {
1040 elem->decRefs(oldVal);
1041 oldVal += stride;
1042 }
1043 }
1044
1045 memcpy(destPtr, data, dataLength);
1046}
1047
1048void RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) {
1049
1050 //rsAssert(!script->mFieldIsObject[slot]);
1051 //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
1052
Tim Murraye195a3f2014-03-13 15:04:58 -07001053#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -07001054#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001055 int32_t *destPtr = reinterpret_cast<int32_t *>(
1056 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001057#else
1058 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1059#endif
Tim Murraye195a3f2014-03-13 15:04:58 -07001060#else
1061 int32_t *destPtr = NULL;
1062#endif
Jason Sams709a0972012-11-15 18:18:04 -08001063 if (!destPtr) {
1064 //ALOGV("Calling setVar on slot = %i which is null", slot);
1065 return;
1066 }
1067
1068 void *ptr = NULL;
1069 mBoundAllocs[slot] = data;
1070 if(data) {
1071 ptr = data->mHal.drvState.lod[0].mallocPtr;
1072 }
1073 memcpy(destPtr, &ptr, sizeof(void *));
1074}
1075
1076void RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) {
1077
1078 //rsAssert(script->mFieldIsObject[slot]);
1079 //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
1080
1081 //if (mIntrinsicID) {
1082 //mIntrinsicFuncs.setVarObj(dc, script, drv->mIntrinsicData, slot, alloc);
1083 //return;
1084 //}
1085
Tim Murraye195a3f2014-03-13 15:04:58 -07001086#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -07001087#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001088 int32_t *destPtr = reinterpret_cast<int32_t *>(
1089 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001090#else
1091 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1092#endif
Tim Murraye195a3f2014-03-13 15:04:58 -07001093#else
1094 int32_t *destPtr = NULL;
1095#endif
1096
1097
Jason Sams709a0972012-11-15 18:18:04 -08001098 if (!destPtr) {
1099 //ALOGV("Calling setVar on slot = %i which is null", slot);
1100 return;
1101 }
1102
1103 rsrSetObject(mCtx->getContext(), (ObjectBase **)destPtr, data);
1104}
1105
1106RsdCpuScriptImpl::~RsdCpuScriptImpl() {
Tim Murraye195a3f2014-03-13 15:04:58 -07001107#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -07001108#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001109 if (mExecutable) {
1110 Vector<void *>::const_iterator var_addr_iter =
1111 mExecutable->getExportVarAddrs().begin();
1112 Vector<void *>::const_iterator var_addr_end =
1113 mExecutable->getExportVarAddrs().end();
1114
1115 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter =
1116 mExecutable->getInfo().getObjectSlots().begin();
1117 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end =
1118 mExecutable->getInfo().getObjectSlots().end();
1119
1120 while ((var_addr_iter != var_addr_end) &&
1121 (is_object_iter != is_object_end)) {
1122 // The field address can be NULL if the script-side has optimized
1123 // the corresponding global variable away.
1124 ObjectBase **obj_addr =
1125 reinterpret_cast<ObjectBase **>(*var_addr_iter);
1126 if (*is_object_iter) {
1127 if (*var_addr_iter != NULL) {
1128 rsrClearObject(mCtx->getContext(), obj_addr);
1129 }
1130 }
1131 var_addr_iter++;
1132 is_object_iter++;
1133 }
1134 }
1135
1136 if (mCompilerContext) {
1137 delete mCompilerContext;
1138 }
1139 if (mCompilerDriver) {
1140 delete mCompilerDriver;
1141 }
1142 if (mExecutable) {
1143 delete mExecutable;
1144 }
1145 if (mBoundAllocs) {
1146 delete[] mBoundAllocs;
1147 }
Jason Sams110f1812013-03-14 16:02:18 -07001148#else
1149 if (mFieldIsObject) {
1150 for (size_t i = 0; i < mExportedVariableCount; ++i) {
1151 if (mFieldIsObject[i]) {
1152 if (mFieldAddress[i] != NULL) {
1153 ObjectBase **obj_addr =
1154 reinterpret_cast<ObjectBase **>(mFieldAddress[i]);
1155 rsrClearObject(mCtx->getContext(), obj_addr);
1156 }
1157 }
1158 }
1159 }
1160
1161 if (mInvokeFunctions) delete[] mInvokeFunctions;
1162 if (mForEachFunctions) delete[] mForEachFunctions;
1163 if (mFieldAddress) delete[] mFieldAddress;
1164 if (mFieldIsObject) delete[] mFieldIsObject;
1165 if (mForEachSignatures) delete[] mForEachSignatures;
1166 if (mBoundAllocs) delete[] mBoundAllocs;
1167 if (mScriptSO) {
1168 dlclose(mScriptSO);
1169 }
1170#endif
Tim Murraye195a3f2014-03-13 15:04:58 -07001171#endif
Jason Sams709a0972012-11-15 18:18:04 -08001172}
1173
1174Allocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const {
1175 if (!ptr) {
1176 return NULL;
1177 }
1178
1179 for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) {
1180 Allocation *a = mBoundAllocs[ct];
1181 if (!a) continue;
1182 if (a->mHal.drvState.lod[0].mallocPtr == ptr) {
1183 return a;
1184 }
1185 }
1186 ALOGE("rsGetAllocation, failed to find %p", ptr);
1187 return NULL;
1188}
1189
Jason Sams17e3cdc2013-09-09 17:32:16 -07001190void RsdCpuScriptImpl::preLaunch(uint32_t slot, const Allocation * ain,
1191 Allocation * aout, const void * usr,
1192 uint32_t usrLen, const RsScriptCall *sc)
1193{
1194}
1195
1196void RsdCpuScriptImpl::postLaunch(uint32_t slot, const Allocation * ain,
1197 Allocation * aout, const void * usr,
1198 uint32_t usrLen, const RsScriptCall *sc)
1199{
1200}
1201
Jason Sams709a0972012-11-15 18:18:04 -08001202
1203}
1204}