blob: 01a3e5a1ca491ce9520f5509c55544a76894e135 [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
Stephen Hines25e3af52014-05-21 21:23:08 -0700421 // Configure symbol resolvers (via compiler-rt and the RS runtime).
422 mRSRuntime.setLookupFunction(lookupRuntimeStub);
423 mRSRuntime.setContext(this);
424 mResolver.chainResolver(mCompilerRuntime);
425 mResolver.chainResolver(mRSRuntime);
Jason Sams709a0972012-11-15 18:18:04 -0800426
Stephen Hinesb7d9c802013-04-29 19:13:09 -0700427 // Run any compiler setup functions we have been provided with.
428 RSSetupCompilerCallback setupCompilerCallback =
429 mCtx->getSetupCompilerCallback();
430 if (setupCompilerCallback != NULL) {
431 setupCompilerCallback(mCompilerDriver);
432 }
433
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700434 const char *core_lib = bcc::RSInfo::LibCLCorePath;
435
436 bcinfo::MetadataExtractor ME((const char *) bitcode, bitcodeSize);
437 if (!ME.extract()) {
438 ALOGE("Could not extract metadata from bitcode");
439 return false;
440 }
441
442 enum bcinfo::RSFloatPrecision prec = ME.getRSFloatPrecision();
443 switch (prec) {
444 case bcinfo::RS_FP_Imprecise:
445 case bcinfo::RS_FP_Relaxed:
446#if defined(ARCH_ARM_HAVE_NEON)
447 // NEON-capable devices can use an accelerated math library for all
448 // reduced precision scripts.
449 core_lib = bcc::RSInfo::LibCLCoreNEONPath;
450#endif
451 break;
452 case bcinfo::RS_FP_Full:
453 break;
454 default:
455 ALOGE("Unknown precision for bitcode");
456 return false;
457 }
458
Stephen Hines4da42502013-10-03 14:57:51 -0700459#if defined(__i386__)
460 // x86 devices will use an optimized library.
Tim Murraye195a3f2014-03-13 15:04:58 -0700461 core_lib = bcc::RSInfo::LibCLCoreX86Path;
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700462#endif
463
Stephen Hines1d476622013-03-29 22:08:49 -0700464 RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback();
465 if (selectRTCallback != NULL) {
466 core_lib = selectRTCallback((const char *)bitcode, bitcodeSize);
467 }
Stephen Hinescca3d6c2013-04-15 01:06:39 -0700468
469 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
470 // Use the libclcore_debug.bc instead of the default library.
471 core_lib = bcc::RSInfo::LibCLCoreDebugPath;
Stephen Hinesf47e8b42013-04-18 01:06:29 -0700472 mCompilerDriver->setDebugContext(true);
Stephen Hines00511322014-01-31 11:20:23 -0800473 useRSDebugContext = true;
Stephen Hinesba17ae42013-06-05 17:18:04 -0700474 // Skip the cache lookup
475 } else if (!is_force_recompile()) {
476 // Attempt to just load the script from cache first if we can.
Stephen Hines25e3af52014-05-21 21:23:08 -0700477 exec = bcc::RSCompilerDriver::loadScript(cacheDir, resName,
478 (const char *)bitcode, bitcodeSize, mResolver);
Stephen Hinescca3d6c2013-04-15 01:06:39 -0700479 }
Stephen Hinesba17ae42013-06-05 17:18:04 -0700480
Stephen Hinesba17ae42013-06-05 17:18:04 -0700481 if (exec == NULL) {
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700482 bool built = compileBitcode(cacheDir, resName, (const char *)bitcode,
Stephen Hines00511322014-01-31 11:20:23 -0800483 bitcodeSize, core_lib, useRSDebugContext,
484 bccPluginName);
Stephen Hinesba17ae42013-06-05 17:18:04 -0700485 if (built) {
Stephen Hines25e3af52014-05-21 21:23:08 -0700486 exec = bcc::RSCompilerDriver::loadScript(cacheDir, resName,
487 (const char *)bitcode, bitcodeSize, mResolver);
Stephen Hinesba17ae42013-06-05 17:18:04 -0700488 }
489 }
Jason Sams709a0972012-11-15 18:18:04 -0800490
491 if (exec == NULL) {
492 ALOGE("bcc: FAILS to prepare executable for '%s'", resName);
493 mCtx->unlockMutex();
494 return false;
495 }
496
497 mExecutable = exec;
498
499 exec->setThreadable(mIsThreadable);
500 if (!exec->syncInfo()) {
501 ALOGW("bcc: FAILS to synchronize the RS info file to the disk");
502 }
503
504 mRoot = reinterpret_cast<int (*)()>(exec->getSymbolAddress("root"));
505 mRootExpand =
506 reinterpret_cast<int (*)()>(exec->getSymbolAddress("root.expand"));
507 mInit = reinterpret_cast<void (*)()>(exec->getSymbolAddress("init"));
508 mFreeChildren =
509 reinterpret_cast<void (*)()>(exec->getSymbolAddress(".rs.dtor"));
510
511
Stephen Hines1d476622013-03-29 22:08:49 -0700512 const bcc::RSInfo *info = &mExecutable->getInfo();
Jason Sams709a0972012-11-15 18:18:04 -0800513 if (info->getExportVarNames().size()) {
514 mBoundAllocs = new Allocation *[info->getExportVarNames().size()];
515 memset(mBoundAllocs, 0, sizeof(void *) * info->getExportVarNames().size());
516 }
517
Jason Sams110f1812013-03-14 16:02:18 -0700518#else
519
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700520 mScriptSO = loadSharedLibrary(cacheDir, resName);
Jason Sams110f1812013-03-14 16:02:18 -0700521
522 if (mScriptSO) {
523 char line[MAXLINE];
524 mRoot = (RootFunc_t) dlsym(mScriptSO, "root");
525 if (mRoot) {
526 //ALOGE("Found root(): %p", mRoot);
527 }
528 mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand");
529 if (mRootExpand) {
530 //ALOGE("Found root.expand(): %p", mRootExpand);
531 }
532 mInit = (InvokeFunc_t) dlsym(mScriptSO, "init");
533 if (mInit) {
534 //ALOGE("Found init(): %p", mInit);
535 }
536 mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor");
537 if (mFreeChildren) {
538 //ALOGE("Found .rs.dtor(): %p", mFreeChildren);
539 }
540
541 const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info");
542 if (rsInfo) {
543 //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo);
544 }
545
546 size_t varCount = 0;
547 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
548 goto error;
549 }
550 if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
551 ALOGE("Invalid export var count!: %s", line);
552 goto error;
553 }
554
555 mExportedVariableCount = varCount;
556 //ALOGE("varCount: %zu", varCount);
557 if (varCount > 0) {
558 // Start by creating/zeroing this member, since we don't want to
559 // accidentally clean up invalid pointers later (if we error out).
560 mFieldIsObject = new bool[varCount];
561 if (mFieldIsObject == NULL) {
562 goto error;
563 }
564 memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject));
565 mFieldAddress = new void*[varCount];
566 if (mFieldAddress == NULL) {
567 goto error;
568 }
569 for (size_t i = 0; i < varCount; ++i) {
570 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
571 goto error;
572 }
573 char *c = strrchr(line, '\n');
574 if (c) {
575 *c = '\0';
576 }
577 mFieldAddress[i] = dlsym(mScriptSO, line);
578 if (mFieldAddress[i] == NULL) {
579 ALOGE("Failed to find variable address for %s: %s",
580 line, dlerror());
581 // Not a critical error if we don't find a global variable.
582 }
583 else {
584 //ALOGE("Found variable %s at %p", line,
585 //mFieldAddress[i]);
586 }
587 }
588 }
589
590 size_t funcCount = 0;
591 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
592 goto error;
593 }
594 if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
595 ALOGE("Invalid export func count!: %s", line);
596 goto error;
597 }
598
599 mExportedFunctionCount = funcCount;
600 //ALOGE("funcCount: %zu", funcCount);
601
602 if (funcCount > 0) {
603 mInvokeFunctions = new InvokeFunc_t[funcCount];
604 if (mInvokeFunctions == NULL) {
605 goto error;
606 }
607 for (size_t i = 0; i < funcCount; ++i) {
608 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
609 goto error;
610 }
611 char *c = strrchr(line, '\n');
612 if (c) {
613 *c = '\0';
614 }
615
616 mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line);
617 if (mInvokeFunctions[i] == NULL) {
618 ALOGE("Failed to get function address for %s(): %s",
619 line, dlerror());
620 goto error;
621 }
622 else {
623 //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]);
624 }
625 }
626 }
627
628 size_t forEachCount = 0;
629 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
630 goto error;
631 }
632 if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
633 ALOGE("Invalid export forEach count!: %s", line);
634 goto error;
635 }
636
637 if (forEachCount > 0) {
638
639 mForEachSignatures = new uint32_t[forEachCount];
640 if (mForEachSignatures == NULL) {
641 goto error;
642 }
643 mForEachFunctions = new ForEachFunc_t[forEachCount];
644 if (mForEachFunctions == NULL) {
645 goto error;
646 }
647 for (size_t i = 0; i < forEachCount; ++i) {
648 unsigned int tmpSig = 0;
649 char tmpName[MAXLINE];
650
651 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
652 goto error;
653 }
654 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
655 &tmpSig, tmpName) != 2) {
656 ALOGE("Invalid export forEach!: %s", line);
657 goto error;
658 }
659
660 // Lookup the expanded ForEach kernel.
661 strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
662 mForEachSignatures[i] = tmpSig;
663 mForEachFunctions[i] =
664 (ForEachFunc_t) dlsym(mScriptSO, tmpName);
Stephen Hinesef7481e2013-04-09 19:05:27 -0700665 if (i != 0 && mForEachFunctions[i] == NULL) {
Jason Sams110f1812013-03-14 16:02:18 -0700666 // Ignore missing root.expand functions.
667 // root() is always specified at location 0.
Stephen Hinesef7481e2013-04-09 19:05:27 -0700668 ALOGE("Failed to find forEach function address for %s: %s",
669 tmpName, dlerror());
670 goto error;
Jason Sams110f1812013-03-14 16:02:18 -0700671 }
672 else {
673 //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]);
674 }
675 }
676 }
677
678 size_t objectSlotCount = 0;
679 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
680 goto error;
681 }
682 if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
683 ALOGE("Invalid object slot count!: %s", line);
684 goto error;
685 }
686
687 if (objectSlotCount > 0) {
688 rsAssert(varCount > 0);
689 for (size_t i = 0; i < objectSlotCount; ++i) {
690 uint32_t varNum = 0;
691 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
692 goto error;
693 }
694 if (sscanf(line, "%u", &varNum) != 1) {
695 ALOGE("Invalid object slot!: %s", line);
696 goto error;
697 }
698
699 if (varNum < varCount) {
700 mFieldIsObject[varNum] = true;
701 }
702 }
703 }
704
705 if (varCount > 0) {
706 mBoundAllocs = new Allocation *[varCount];
707 memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs));
708 }
709
710 if (mScriptSO == (void*)1) {
711 //rsdLookupRuntimeStub(script, "acos");
712 }
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700713 } else {
714 goto error;
Jason Sams110f1812013-03-14 16:02:18 -0700715 }
716#endif
Tim Murraye195a3f2014-03-13 15:04:58 -0700717#endif // FAKE_ARM64_BUILD
Jason Sams709a0972012-11-15 18:18:04 -0800718 mCtx->unlockMutex();
719 return true;
Jason Sams110f1812013-03-14 16:02:18 -0700720
721#ifdef RS_COMPATIBILITY_LIB
722error:
723
724 mCtx->unlockMutex();
725 delete[] mInvokeFunctions;
726 delete[] mForEachFunctions;
727 delete[] mFieldAddress;
728 delete[] mFieldIsObject;
729 delete[] mForEachSignatures;
730 delete[] mBoundAllocs;
731 if (mScriptSO) {
732 dlclose(mScriptSO);
733 }
734 return false;
735#endif
Jason Sams709a0972012-11-15 18:18:04 -0800736}
737
738void RsdCpuScriptImpl::populateScript(Script *script) {
Tim Murraye195a3f2014-03-13 15:04:58 -0700739#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -0700740#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800741 const bcc::RSInfo *info = &mExecutable->getInfo();
742
743 // Copy info over to runtime
744 script->mHal.info.exportedFunctionCount = info->getExportFuncNames().size();
745 script->mHal.info.exportedVariableCount = info->getExportVarNames().size();
Tobias Grosser47935ac2013-06-17 11:47:26 -0700746 script->mHal.info.exportedForeachFuncList = info->getExportForeachFuncs().array();
Jason Sams709a0972012-11-15 18:18:04 -0800747 script->mHal.info.exportedPragmaCount = info->getPragmas().size();
748 script->mHal.info.exportedPragmaKeyList =
749 const_cast<const char**>(mExecutable->getPragmaKeys().array());
750 script->mHal.info.exportedPragmaValueList =
751 const_cast<const char**>(mExecutable->getPragmaValues().array());
752
753 if (mRootExpand) {
754 script->mHal.info.root = mRootExpand;
755 } else {
756 script->mHal.info.root = mRoot;
757 }
Jason Sams110f1812013-03-14 16:02:18 -0700758#else
759 // Copy info over to runtime
760 script->mHal.info.exportedFunctionCount = mExportedFunctionCount;
761 script->mHal.info.exportedVariableCount = mExportedVariableCount;
762 script->mHal.info.exportedPragmaCount = 0;
763 script->mHal.info.exportedPragmaKeyList = 0;
764 script->mHal.info.exportedPragmaValueList = 0;
765
766 // Bug, need to stash in metadata
767 if (mRootExpand) {
768 script->mHal.info.root = mRootExpand;
769 } else {
770 script->mHal.info.root = mRoot;
771 }
772#endif
Tim Murraye195a3f2014-03-13 15:04:58 -0700773#endif
Jason Sams709a0972012-11-15 18:18:04 -0800774}
775
Jason Sams709a0972012-11-15 18:18:04 -0800776
777typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
778
779void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation * ain, Allocation * aout,
780 const void * usr, uint32_t usrLen,
781 const RsScriptCall *sc,
782 MTLaunchStruct *mtls) {
783
784 memset(mtls, 0, sizeof(MTLaunchStruct));
785
Tim Murray3a25fdd2013-02-22 17:56:56 -0800786 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface
787 if (ain && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) {
Jason Samsddceab92013-08-07 13:02:32 -0700788 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null in allocations");
Tim Murray3a25fdd2013-02-22 17:56:56 -0800789 return;
790 }
791 if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) {
Jason Samsddceab92013-08-07 13:02:32 -0700792 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null out allocations");
Tim Murray3a25fdd2013-02-22 17:56:56 -0800793 return;
794 }
795
Jason Sams709a0972012-11-15 18:18:04 -0800796 if (ain) {
797 mtls->fep.dimX = ain->getType()->getDimX();
798 mtls->fep.dimY = ain->getType()->getDimY();
799 mtls->fep.dimZ = ain->getType()->getDimZ();
800 //mtls->dimArray = ain->getType()->getDimArray();
801 } else if (aout) {
802 mtls->fep.dimX = aout->getType()->getDimX();
803 mtls->fep.dimY = aout->getType()->getDimY();
804 mtls->fep.dimZ = aout->getType()->getDimZ();
805 //mtls->dimArray = aout->getType()->getDimArray();
806 } else {
807 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
808 return;
809 }
810
811 if (!sc || (sc->xEnd == 0)) {
812 mtls->xEnd = mtls->fep.dimX;
813 } else {
814 rsAssert(sc->xStart < mtls->fep.dimX);
815 rsAssert(sc->xEnd <= mtls->fep.dimX);
816 rsAssert(sc->xStart < sc->xEnd);
817 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
818 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
819 if (mtls->xStart >= mtls->xEnd) return;
820 }
821
822 if (!sc || (sc->yEnd == 0)) {
823 mtls->yEnd = mtls->fep.dimY;
824 } else {
825 rsAssert(sc->yStart < mtls->fep.dimY);
826 rsAssert(sc->yEnd <= mtls->fep.dimY);
827 rsAssert(sc->yStart < sc->yEnd);
828 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
829 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
830 if (mtls->yStart >= mtls->yEnd) return;
831 }
832
Tim Murrayd4ecb172013-02-07 12:17:03 -0800833 if (!sc || (sc->zEnd == 0)) {
834 mtls->zEnd = mtls->fep.dimZ;
835 } else {
836 rsAssert(sc->zStart < mtls->fep.dimZ);
837 rsAssert(sc->zEnd <= mtls->fep.dimZ);
838 rsAssert(sc->zStart < sc->zEnd);
839 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart);
840 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd);
841 if (mtls->zStart >= mtls->zEnd) return;
842 }
843
Jason Sams709a0972012-11-15 18:18:04 -0800844 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
845 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
846 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
847 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
848
849 rsAssert(!ain || (ain->getType()->getDimZ() == 0));
850
851 mtls->rsc = mCtx;
852 mtls->ain = ain;
853 mtls->aout = aout;
854 mtls->fep.usr = usr;
855 mtls->fep.usrLen = usrLen;
856 mtls->mSliceSize = 1;
857 mtls->mSliceNum = 0;
858
859 mtls->fep.ptrIn = NULL;
860 mtls->fep.eStrideIn = 0;
861 mtls->isThreadable = mIsThreadable;
862
863 if (ain) {
864 mtls->fep.ptrIn = (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr;
865 mtls->fep.eStrideIn = ain->getType()->getElementSizeBytes();
866 mtls->fep.yStrideIn = ain->mHal.drvState.lod[0].stride;
867 }
868
869 mtls->fep.ptrOut = NULL;
870 mtls->fep.eStrideOut = 0;
871 if (aout) {
872 mtls->fep.ptrOut = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
873 mtls->fep.eStrideOut = aout->getType()->getElementSizeBytes();
874 mtls->fep.yStrideOut = aout->mHal.drvState.lod[0].stride;
875 }
876}
877
878
879void RsdCpuScriptImpl::invokeForEach(uint32_t slot,
880 const Allocation * ain,
881 Allocation * aout,
882 const void * usr,
883 uint32_t usrLen,
884 const RsScriptCall *sc) {
885
886 MTLaunchStruct mtls;
887 forEachMtlsSetup(ain, aout, usr, usrLen, sc, &mtls);
888 forEachKernelSetup(slot, &mtls);
889
890 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
891 mCtx->launchThreads(ain, aout, sc, &mtls);
892 mCtx->setTLS(oldTLS);
893}
894
895void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) {
Jason Sams709a0972012-11-15 18:18:04 -0800896 mtls->script = this;
897 mtls->fep.slot = slot;
Tim Murraye195a3f2014-03-13 15:04:58 -0700898#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -0700899#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800900 rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size());
901 mtls->kernel = reinterpret_cast<ForEachFunc_t>(
902 mExecutable->getExportForeachFuncAddrs()[slot]);
903 rsAssert(mtls->kernel != NULL);
904 mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second;
Jason Sams110f1812013-03-14 16:02:18 -0700905#else
906 mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]);
907 rsAssert(mtls->kernel != NULL);
908 mtls->sig = mForEachSignatures[slot];
909#endif
Tim Murraye195a3f2014-03-13 15:04:58 -0700910#endif
Jason Sams709a0972012-11-15 18:18:04 -0800911}
912
913int RsdCpuScriptImpl::invokeRoot() {
914 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
Tim Murraye195a3f2014-03-13 15:04:58 -0700915#ifndef FAKE_ARM64_BUILD
Jason Sams709a0972012-11-15 18:18:04 -0800916 int ret = mRoot();
Tim Murraye195a3f2014-03-13 15:04:58 -0700917#else
918 int ret = 0;
919#endif
Jason Sams709a0972012-11-15 18:18:04 -0800920 mCtx->setTLS(oldTLS);
921 return ret;
922}
923
924void RsdCpuScriptImpl::invokeInit() {
Tim Murraye195a3f2014-03-13 15:04:58 -0700925#ifndef FAKE_ARM64_BUILD
Jason Sams709a0972012-11-15 18:18:04 -0800926 if (mInit) {
927 mInit();
928 }
Tim Murraye195a3f2014-03-13 15:04:58 -0700929#endif
Jason Sams709a0972012-11-15 18:18:04 -0800930}
931
932void RsdCpuScriptImpl::invokeFreeChildren() {
Tim Murraye195a3f2014-03-13 15:04:58 -0700933#ifndef FAKE_ARM64_BUILD
Jason Sams709a0972012-11-15 18:18:04 -0800934 if (mFreeChildren) {
935 mFreeChildren();
936 }
Tim Murraye195a3f2014-03-13 15:04:58 -0700937#endif
Jason Sams709a0972012-11-15 18:18:04 -0800938}
939
940void RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params,
941 size_t paramLength) {
942 //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
943
944 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
Tim Murraye195a3f2014-03-13 15:04:58 -0700945#ifndef FAKE_ARM64_BUILD
Jason Sams709a0972012-11-15 18:18:04 -0800946 reinterpret_cast<void (*)(const void *, uint32_t)>(
Jason Sams110f1812013-03-14 16:02:18 -0700947#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800948 mExecutable->getExportFuncAddrs()[slot])(params, paramLength);
Jason Sams110f1812013-03-14 16:02:18 -0700949#else
950 mInvokeFunctions[slot])(params, paramLength);
951#endif
Tim Murraye195a3f2014-03-13 15:04:58 -0700952#endif
Jason Sams709a0972012-11-15 18:18:04 -0800953 mCtx->setTLS(oldTLS);
954}
955
956void RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) {
957 //rsAssert(!script->mFieldIsObject[slot]);
958 //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
959
960 //if (mIntrinsicID) {
961 //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
962 //return;
963 //}
964
Tim Murraye195a3f2014-03-13 15:04:58 -0700965#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -0700966#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800967 int32_t *destPtr = reinterpret_cast<int32_t *>(
968 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -0700969#else
970 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
971#endif
Tim Murraye195a3f2014-03-13 15:04:58 -0700972#else
973 int32_t *destPtr = NULL;
974#endif
Jason Sams709a0972012-11-15 18:18:04 -0800975 if (!destPtr) {
976 //ALOGV("Calling setVar on slot = %i which is null", slot);
977 return;
978 }
979
980 memcpy(destPtr, data, dataLength);
981}
982
Tim Murray9c642392013-04-11 13:29:59 -0700983void RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) {
984 //rsAssert(!script->mFieldIsObject[slot]);
985 //ALOGE("getGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
986
Tim Murraye195a3f2014-03-13 15:04:58 -0700987#ifndef FAKE_ARM64_BUILD
Tim Murray9c642392013-04-11 13:29:59 -0700988#ifndef RS_COMPATIBILITY_LIB
989 int32_t *srcPtr = reinterpret_cast<int32_t *>(
990 mExecutable->getExportVarAddrs()[slot]);
991#else
992 int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
993#endif
Tim Murraye195a3f2014-03-13 15:04:58 -0700994#else
995 int32_t *srcPtr = NULL;
996#endif
Tim Murray9c642392013-04-11 13:29:59 -0700997 if (!srcPtr) {
998 //ALOGV("Calling setVar on slot = %i which is null", slot);
999 return;
1000 }
1001 memcpy(data, srcPtr, dataLength);
1002}
1003
1004
Jason Sams709a0972012-11-15 18:18:04 -08001005void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength,
1006 const Element *elem,
1007 const size_t *dims, size_t dimLength) {
1008
Tim Murraye195a3f2014-03-13 15:04:58 -07001009#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -07001010#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001011 int32_t *destPtr = reinterpret_cast<int32_t *>(
1012 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001013#else
1014 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1015#endif
Tim Murraye195a3f2014-03-13 15:04:58 -07001016#else
1017 int32_t *destPtr = NULL;
1018#endif
Jason Sams709a0972012-11-15 18:18:04 -08001019 if (!destPtr) {
1020 //ALOGV("Calling setVar on slot = %i which is null", slot);
1021 return;
1022 }
1023
1024 // We want to look at dimension in terms of integer components,
1025 // but dimLength is given in terms of bytes.
1026 dimLength /= sizeof(int);
1027
1028 // Only a single dimension is currently supported.
1029 rsAssert(dimLength == 1);
1030 if (dimLength == 1) {
1031 // First do the increment loop.
1032 size_t stride = elem->getSizeBytes();
1033 const char *cVal = reinterpret_cast<const char *>(data);
1034 for (size_t i = 0; i < dims[0]; i++) {
1035 elem->incRefs(cVal);
1036 cVal += stride;
1037 }
1038
1039 // Decrement loop comes after (to prevent race conditions).
1040 char *oldVal = reinterpret_cast<char *>(destPtr);
1041 for (size_t i = 0; i < dims[0]; i++) {
1042 elem->decRefs(oldVal);
1043 oldVal += stride;
1044 }
1045 }
1046
1047 memcpy(destPtr, data, dataLength);
1048}
1049
1050void RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) {
1051
1052 //rsAssert(!script->mFieldIsObject[slot]);
1053 //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
1054
Tim Murraye195a3f2014-03-13 15:04:58 -07001055#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -07001056#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001057 int32_t *destPtr = reinterpret_cast<int32_t *>(
1058 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001059#else
1060 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1061#endif
Tim Murraye195a3f2014-03-13 15:04:58 -07001062#else
1063 int32_t *destPtr = NULL;
1064#endif
Jason Sams709a0972012-11-15 18:18:04 -08001065 if (!destPtr) {
1066 //ALOGV("Calling setVar on slot = %i which is null", slot);
1067 return;
1068 }
1069
1070 void *ptr = NULL;
1071 mBoundAllocs[slot] = data;
1072 if(data) {
1073 ptr = data->mHal.drvState.lod[0].mallocPtr;
1074 }
1075 memcpy(destPtr, &ptr, sizeof(void *));
1076}
1077
1078void RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) {
1079
1080 //rsAssert(script->mFieldIsObject[slot]);
1081 //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
1082
1083 //if (mIntrinsicID) {
1084 //mIntrinsicFuncs.setVarObj(dc, script, drv->mIntrinsicData, slot, alloc);
1085 //return;
1086 //}
1087
Tim Murraye195a3f2014-03-13 15:04:58 -07001088#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -07001089#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001090 int32_t *destPtr = reinterpret_cast<int32_t *>(
1091 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001092#else
1093 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1094#endif
Tim Murraye195a3f2014-03-13 15:04:58 -07001095#else
1096 int32_t *destPtr = NULL;
1097#endif
1098
1099
Jason Sams709a0972012-11-15 18:18:04 -08001100 if (!destPtr) {
1101 //ALOGV("Calling setVar on slot = %i which is null", slot);
1102 return;
1103 }
1104
1105 rsrSetObject(mCtx->getContext(), (ObjectBase **)destPtr, data);
1106}
1107
1108RsdCpuScriptImpl::~RsdCpuScriptImpl() {
Tim Murraye195a3f2014-03-13 15:04:58 -07001109#ifndef FAKE_ARM64_BUILD
Jason Sams110f1812013-03-14 16:02:18 -07001110#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001111 if (mExecutable) {
1112 Vector<void *>::const_iterator var_addr_iter =
1113 mExecutable->getExportVarAddrs().begin();
1114 Vector<void *>::const_iterator var_addr_end =
1115 mExecutable->getExportVarAddrs().end();
1116
1117 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter =
1118 mExecutable->getInfo().getObjectSlots().begin();
1119 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end =
1120 mExecutable->getInfo().getObjectSlots().end();
1121
1122 while ((var_addr_iter != var_addr_end) &&
1123 (is_object_iter != is_object_end)) {
1124 // The field address can be NULL if the script-side has optimized
1125 // the corresponding global variable away.
1126 ObjectBase **obj_addr =
1127 reinterpret_cast<ObjectBase **>(*var_addr_iter);
1128 if (*is_object_iter) {
1129 if (*var_addr_iter != NULL) {
1130 rsrClearObject(mCtx->getContext(), obj_addr);
1131 }
1132 }
1133 var_addr_iter++;
1134 is_object_iter++;
1135 }
1136 }
1137
1138 if (mCompilerContext) {
1139 delete mCompilerContext;
1140 }
1141 if (mCompilerDriver) {
1142 delete mCompilerDriver;
1143 }
1144 if (mExecutable) {
1145 delete mExecutable;
1146 }
1147 if (mBoundAllocs) {
1148 delete[] mBoundAllocs;
1149 }
Jason Sams110f1812013-03-14 16:02:18 -07001150#else
1151 if (mFieldIsObject) {
1152 for (size_t i = 0; i < mExportedVariableCount; ++i) {
1153 if (mFieldIsObject[i]) {
1154 if (mFieldAddress[i] != NULL) {
1155 ObjectBase **obj_addr =
1156 reinterpret_cast<ObjectBase **>(mFieldAddress[i]);
1157 rsrClearObject(mCtx->getContext(), obj_addr);
1158 }
1159 }
1160 }
1161 }
1162
1163 if (mInvokeFunctions) delete[] mInvokeFunctions;
1164 if (mForEachFunctions) delete[] mForEachFunctions;
1165 if (mFieldAddress) delete[] mFieldAddress;
1166 if (mFieldIsObject) delete[] mFieldIsObject;
1167 if (mForEachSignatures) delete[] mForEachSignatures;
1168 if (mBoundAllocs) delete[] mBoundAllocs;
1169 if (mScriptSO) {
1170 dlclose(mScriptSO);
1171 }
1172#endif
Tim Murraye195a3f2014-03-13 15:04:58 -07001173#endif
Jason Sams709a0972012-11-15 18:18:04 -08001174}
1175
1176Allocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const {
1177 if (!ptr) {
1178 return NULL;
1179 }
1180
1181 for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) {
1182 Allocation *a = mBoundAllocs[ct];
1183 if (!a) continue;
1184 if (a->mHal.drvState.lod[0].mallocPtr == ptr) {
1185 return a;
1186 }
1187 }
1188 ALOGE("rsGetAllocation, failed to find %p", ptr);
1189 return NULL;
1190}
1191
Jason Sams17e3cdc2013-09-09 17:32:16 -07001192void RsdCpuScriptImpl::preLaunch(uint32_t slot, const Allocation * ain,
1193 Allocation * aout, const void * usr,
1194 uint32_t usrLen, const RsScriptCall *sc)
1195{
1196}
1197
1198void RsdCpuScriptImpl::postLaunch(uint32_t slot, const Allocation * ain,
1199 Allocation * aout, const void * usr,
1200 uint32_t usrLen, const RsScriptCall *sc)
1201{
1202}
1203
Jason Sams709a0972012-11-15 18:18:04 -08001204
1205}
1206}