blob: e0b4004257bae6197b64c2c64d351a1dfc034693 [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
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -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
Jason Sams110f1812013-03-14 16:02:18 -070020#ifdef RS_COMPATIBILITY_LIB
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070021 #include <set>
22 #include <string>
Jason Sams110f1812013-03-14 16:02:18 -070023 #include <dlfcn.h>
24 #include <stdio.h>
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070025 #include <stdlib.h>
Jason Sams110f1812013-03-14 16:02:18 -070026 #include <string.h>
Stephen Hinesee48c0b2013-10-30 17:48:30 -070027 #include <sys/stat.h>
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070028 #include <unistd.h>
Jason Sams110f1812013-03-14 16:02:18 -070029#else
30 #include <bcc/BCCContext.h>
Stephen Hines82e0a672014-05-05 15:40:56 -070031 #include <bcc/Config/Config.h>
Jason Sams110f1812013-03-14 16:02:18 -070032 #include <bcc/Renderscript/RSCompilerDriver.h>
33 #include <bcc/Renderscript/RSExecutable.h>
34 #include <bcc/Renderscript/RSInfo.h>
Stephen Hinesb58d9ad2013-06-19 19:26:19 -070035 #include <bcinfo/MetadataExtractor.h>
Stephen Hinesba17ae42013-06-05 17:18:04 -070036 #include <cutils/properties.h>
Stephen Hinesb58d9ad2013-06-19 19:26:19 -070037
38 #include <sys/types.h>
39 #include <sys/wait.h>
40 #include <unistd.h>
Stephen Hines00511322014-01-31 11:20:23 -080041
42 #include <string>
43 #include <vector>
Jason Sams110f1812013-03-14 16:02:18 -070044#endif
Jason Sams709a0972012-11-15 18:18:04 -080045
Stephen Hinesba17ae42013-06-05 17:18:04 -070046namespace {
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070047#ifdef RS_COMPATIBILITY_LIB
48
49// Create a len length string containing random characters from [A-Za-z0-9].
50static 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
Stephen Hinesee48c0b2013-10-30 17:48:30 -070070// Check if a path exists and attempt to create it if it doesn't.
71static 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
Stephen Hinesc2c11cc2013-07-19 01:07:42 -070082// 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.
85static 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
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700111 std::string newName(cacheDir);
Stephen Hinesee48c0b2013-10-30 17:48:30 -0700112 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.");
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700121 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.
148static 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.
Chris Wailes93d6bc82014-07-28 16:54:38 -0700179 std::string scriptSONameSystem("/system/lib/librs.");
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700180 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
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -0700193#else // RS_COMPATIBILITY_LIB is not defined
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700194
Stephen Hinesba17ae42013-06-05 17:18:04 -0700195static 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}
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700216
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700217const static char *BCC_EXE_PATH = "/system/bin/bcc";
218
Chris Wailes6847e732014-08-11 17:30:51 -0700219static void setCompileArguments(std::vector<const char*>* args,
220 const std::string& bcFileName,
221 const char* cacheDir, const char* resName,
222 const char* core_lib, bool useRSDebugContext,
223 const char* bccPluginName) {
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700224 rsAssert(cacheDir && resName && core_lib);
225 args->push_back(BCC_EXE_PATH);
226 args->push_back("-o");
227 args->push_back(resName);
228 args->push_back("-output_path");
229 args->push_back(cacheDir);
230 args->push_back("-bclib");
231 args->push_back(core_lib);
232 args->push_back("-mtriple");
233 args->push_back(DEFAULT_TARGET_TRIPLE_STRING);
234
235 // Execute the bcc compiler.
236 if (useRSDebugContext) {
237 args->push_back("-rs-debug-ctx");
238 } else {
239 // Only load additional libraries for compiles that don't use
240 // the debug context.
241 if (bccPluginName && strlen(bccPluginName) > 0) {
242 args->push_back("-load");
243 args->push_back(bccPluginName);
244 }
245 }
246
Chris Wailes6847e732014-08-11 17:30:51 -0700247 args->push_back(bcFileName.c_str());
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700248 args->push_back(NULL);
249}
250
Chris Wailes6847e732014-08-11 17:30:51 -0700251static bool compileBitcode(const std::string &bcFileName,
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700252 const char *bitcode,
253 size_t bitcodeSize,
Chris Wailes6847e732014-08-11 17:30:51 -0700254 const char **compileArguments,
255 const std::string &compileCommandLine) {
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700256 rsAssert(bitcode && bitcodeSize);
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700257
Chris Wailes6847e732014-08-11 17:30:51 -0700258 FILE *bcfile = fopen(bcFileName.c_str(), "w");
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700259 if (!bcfile) {
Chris Wailes6847e732014-08-11 17:30:51 -0700260 ALOGE("Could not write to %s", bcFileName.c_str());
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700261 return false;
262 }
263 size_t nwritten = fwrite(bitcode, 1, bitcodeSize, bcfile);
264 fclose(bcfile);
265 if (nwritten != bitcodeSize) {
266 ALOGE("Could not write %zu bytes to %s", bitcodeSize,
Chris Wailes6847e732014-08-11 17:30:51 -0700267 bcFileName.c_str());
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700268 return false;
269 }
270
271 pid_t pid = fork();
Stephen Hines00511322014-01-31 11:20:23 -0800272
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700273 switch (pid) {
274 case -1: { // Error occurred (we attempt no recovery)
275 ALOGE("Couldn't fork for bcc compiler execution");
276 return false;
277 }
278 case 0: { // Child process
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700279 ALOGV("Invoking BCC with: %s", compileCommandLine.c_str());
280 execv(BCC_EXE_PATH, (char* const*)compileArguments);
Stephen Hines00511322014-01-31 11:20:23 -0800281
Stephen Hines00511322014-01-31 11:20:23 -0800282 ALOGE("execv() failed: %s", strerror(errno));
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700283 abort();
284 return false;
285 }
286 default: { // Parent process (actual driver)
287 // Wait on child process to finish compiling the source.
288 int status = 0;
289 pid_t w = waitpid(pid, &status, 0);
290 if (w == -1) {
291 ALOGE("Could not wait for bcc compiler");
292 return false;
293 }
294
295 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
296 return true;
297 }
298
299 ALOGE("bcc compiler terminated unexpectedly");
300 return false;
301 }
302 }
303}
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700304
Stephen Hinesba17ae42013-06-05 17:18:04 -0700305#endif // !defined(RS_COMPATIBILITY_LIB)
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700306} // namespace
Stephen Hinesba17ae42013-06-05 17:18:04 -0700307
Jason Sams709a0972012-11-15 18:18:04 -0800308namespace android {
309namespace renderscript {
310
Jason Sams110f1812013-03-14 16:02:18 -0700311#ifdef RS_COMPATIBILITY_LIB
312#define MAXLINE 500
313#define MAKE_STR_HELPER(S) #S
314#define MAKE_STR(S) MAKE_STR_HELPER(S)
315#define EXPORT_VAR_STR "exportVarCount: "
Jason Sams110f1812013-03-14 16:02:18 -0700316#define EXPORT_FUNC_STR "exportFuncCount: "
Jason Sams110f1812013-03-14 16:02:18 -0700317#define EXPORT_FOREACH_STR "exportForEachCount: "
Jason Sams110f1812013-03-14 16:02:18 -0700318#define OBJECT_SLOT_STR "objectSlotCount: "
Jason Sams110f1812013-03-14 16:02:18 -0700319
320// Copy up to a newline or size chars from str -> s, updating str
321// Returns s when successful and NULL when '\0' is finally reached.
322static char* strgets(char *s, int size, const char **ppstr) {
323 if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
324 return NULL;
325 }
326
327 int i;
328 for (i = 0; i < (size - 1); i++) {
329 s[i] = **ppstr;
330 (*ppstr)++;
331 if (s[i] == '\0') {
332 return s;
333 } else if (s[i] == '\n') {
334 s[i+1] = '\0';
335 return s;
336 }
337 }
338
339 // size has been exceeded.
340 s[i] = '\0';
341
342 return s;
343}
344#endif
Jason Sams709a0972012-11-15 18:18:04 -0800345
346RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) {
347 mCtx = ctx;
348 mScript = s;
349
Jason Sams110f1812013-03-14 16:02:18 -0700350#ifdef RS_COMPATIBILITY_LIB
351 mScriptSO = NULL;
352 mInvokeFunctions = NULL;
353 mForEachFunctions = NULL;
354 mFieldAddress = NULL;
355 mFieldIsObject = NULL;
356 mForEachSignatures = NULL;
357#else
358 mCompilerContext = NULL;
359 mCompilerDriver = NULL;
360 mExecutable = NULL;
361#endif
362
Tim Murraye195a3f2014-03-13 15:04:58 -0700363
Jason Sams709a0972012-11-15 18:18:04 -0800364 mRoot = NULL;
365 mRootExpand = NULL;
366 mInit = NULL;
367 mFreeChildren = NULL;
368
Jason Sams709a0972012-11-15 18:18:04 -0800369
370 mBoundAllocs = NULL;
371 mIntrinsicData = NULL;
372 mIsThreadable = true;
373}
374
375
376bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
377 uint8_t const *bitcode, size_t bitcodeSize,
Stephen Hines00511322014-01-31 11:20:23 -0800378 uint32_t flags, char const *bccPluginName) {
Jason Sams709a0972012-11-15 18:18:04 -0800379 //ALOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc);
380 //ALOGE("rsdScriptInit %p %p", rsc, script);
381
382 mCtx->lockMutex();
Jason Sams110f1812013-03-14 16:02:18 -0700383#ifndef RS_COMPATIBILITY_LIB
Stephen Hines00511322014-01-31 11:20:23 -0800384 bool useRSDebugContext = false;
Jason Sams709a0972012-11-15 18:18:04 -0800385
386 mCompilerContext = NULL;
387 mCompilerDriver = NULL;
388 mExecutable = NULL;
389
390 mCompilerContext = new bcc::BCCContext();
391 if (mCompilerContext == NULL) {
392 ALOGE("bcc: FAILS to create compiler context (out of memory)");
393 mCtx->unlockMutex();
394 return false;
395 }
396
397 mCompilerDriver = new bcc::RSCompilerDriver();
398 if (mCompilerDriver == NULL) {
399 ALOGE("bcc: FAILS to create compiler driver (out of memory)");
400 mCtx->unlockMutex();
401 return false;
402 }
403
Stephen Hines25e3af52014-05-21 21:23:08 -0700404 // Configure symbol resolvers (via compiler-rt and the RS runtime).
405 mRSRuntime.setLookupFunction(lookupRuntimeStub);
406 mRSRuntime.setContext(this);
407 mResolver.chainResolver(mCompilerRuntime);
408 mResolver.chainResolver(mRSRuntime);
Jason Sams709a0972012-11-15 18:18:04 -0800409
Stephen Hinesb7d9c802013-04-29 19:13:09 -0700410 // Run any compiler setup functions we have been provided with.
411 RSSetupCompilerCallback setupCompilerCallback =
412 mCtx->getSetupCompilerCallback();
413 if (setupCompilerCallback != NULL) {
414 setupCompilerCallback(mCompilerDriver);
415 }
416
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700417 bcinfo::MetadataExtractor bitcodeMetadata((const char *) bitcode, bitcodeSize);
418 if (!bitcodeMetadata.extract()) {
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700419 ALOGE("Could not extract metadata from bitcode");
Stephen Hinesf94e8db2014-06-26 11:55:29 -0700420 mCtx->unlockMutex();
Stephen Hinesb58d9ad2013-06-19 19:26:19 -0700421 return false;
422 }
423
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700424 const char* core_lib = findCoreLib(bitcodeMetadata, (const char*)bitcode, bitcodeSize);
Stephen Hinescca3d6c2013-04-15 01:06:39 -0700425
426 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
Stephen Hinesf47e8b42013-04-18 01:06:29 -0700427 mCompilerDriver->setDebugContext(true);
Stephen Hines00511322014-01-31 11:20:23 -0800428 useRSDebugContext = true;
Stephen Hinescca3d6c2013-04-15 01:06:39 -0700429 }
Stephen Hinesba17ae42013-06-05 17:18:04 -0700430
Chris Wailes6847e732014-08-11 17:30:51 -0700431 std::string bcFileName(cacheDir);
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700432 bcFileName.append("/");
433 bcFileName.append(resName);
434 bcFileName.append(".bc");
435
436 std::vector<const char*> compileArguments;
437 setCompileArguments(&compileArguments, bcFileName, cacheDir, resName, core_lib,
438 useRSDebugContext, bccPluginName);
439 // The last argument of compileArguments ia a NULL, so remove 1 from the size.
440 std::string compileCommandLine =
441 bcc::getCommandLine(compileArguments.size() - 1, compileArguments.data());
442
443 if (!is_force_recompile()) {
444 // Load the compiled script that's in the cache, if any.
445 mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode,
446 bitcodeSize, compileCommandLine.c_str(),
447 mResolver);
448 }
449
450 // If we can't, it's either not there or out of date. We compile the bit code and try loading
451 // again.
452 if (mExecutable == NULL) {
453 if (!compileBitcode(bcFileName, (const char*)bitcode, bitcodeSize, compileArguments.data(),
454 compileCommandLine)) {
455 ALOGE("bcc: FAILS to compile '%s'", resName);
456 mCtx->unlockMutex();
457 return false;
458 }
459 mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode,
460 bitcodeSize, compileCommandLine.c_str(),
461 mResolver);
462 if (mExecutable == NULL) {
463 ALOGE("bcc: FAILS to load freshly compiled executable for '%s'", resName);
464 mCtx->unlockMutex();
465 return false;
Stephen Hinesba17ae42013-06-05 17:18:04 -0700466 }
467 }
Jason Sams709a0972012-11-15 18:18:04 -0800468
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700469 mExecutable->setThreadable(mIsThreadable);
470 if (!mExecutable->syncInfo()) {
Jason Sams709a0972012-11-15 18:18:04 -0800471 ALOGW("bcc: FAILS to synchronize the RS info file to the disk");
472 }
473
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700474 mRoot = reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root"));
Jason Sams709a0972012-11-15 18:18:04 -0800475 mRootExpand =
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700476 reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root.expand"));
477 mInit = reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress("init"));
Jason Sams709a0972012-11-15 18:18:04 -0800478 mFreeChildren =
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700479 reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress(".rs.dtor"));
Jason Sams709a0972012-11-15 18:18:04 -0800480
481
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700482 if (bitcodeMetadata.getExportVarCount()) {
483 mBoundAllocs = new Allocation *[bitcodeMetadata.getExportVarCount()];
484 memset(mBoundAllocs, 0, sizeof(void *) * bitcodeMetadata.getExportVarCount());
Tim Murray29809d12014-05-28 12:04:19 -0700485 }
486
Jean-Luc Brouillet40e35cd2014-06-25 18:21:45 -0700487 for (size_t i = 0; i < bitcodeMetadata.getExportForEachSignatureCount(); i++) {
488 char* name = new char[strlen(bitcodeMetadata.getExportForEachNameList()[i]) + 1];
489 mExportedForEachFuncList.push_back(
490 std::make_pair(name, bitcodeMetadata.getExportForEachSignatureList()[i]));
Jason Sams709a0972012-11-15 18:18:04 -0800491 }
492
Jean-Luc Brouilletf4d216e2014-06-09 18:04:16 -0700493#else // RS_COMPATIBILITY_LIB is defined
Jason Sams110f1812013-03-14 16:02:18 -0700494
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700495 mScriptSO = loadSharedLibrary(cacheDir, resName);
Jason Sams110f1812013-03-14 16:02:18 -0700496
497 if (mScriptSO) {
498 char line[MAXLINE];
499 mRoot = (RootFunc_t) dlsym(mScriptSO, "root");
500 if (mRoot) {
501 //ALOGE("Found root(): %p", mRoot);
502 }
503 mRootExpand = (RootFunc_t) dlsym(mScriptSO, "root.expand");
504 if (mRootExpand) {
505 //ALOGE("Found root.expand(): %p", mRootExpand);
506 }
507 mInit = (InvokeFunc_t) dlsym(mScriptSO, "init");
508 if (mInit) {
509 //ALOGE("Found init(): %p", mInit);
510 }
511 mFreeChildren = (InvokeFunc_t) dlsym(mScriptSO, ".rs.dtor");
512 if (mFreeChildren) {
513 //ALOGE("Found .rs.dtor(): %p", mFreeChildren);
514 }
515
516 const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info");
517 if (rsInfo) {
518 //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo);
519 }
520
521 size_t varCount = 0;
522 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
523 goto error;
524 }
525 if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
526 ALOGE("Invalid export var count!: %s", line);
527 goto error;
528 }
529
530 mExportedVariableCount = varCount;
531 //ALOGE("varCount: %zu", varCount);
532 if (varCount > 0) {
533 // Start by creating/zeroing this member, since we don't want to
534 // accidentally clean up invalid pointers later (if we error out).
535 mFieldIsObject = new bool[varCount];
536 if (mFieldIsObject == NULL) {
537 goto error;
538 }
539 memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject));
540 mFieldAddress = new void*[varCount];
541 if (mFieldAddress == NULL) {
542 goto error;
543 }
544 for (size_t i = 0; i < varCount; ++i) {
545 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
546 goto error;
547 }
548 char *c = strrchr(line, '\n');
549 if (c) {
550 *c = '\0';
551 }
552 mFieldAddress[i] = dlsym(mScriptSO, line);
553 if (mFieldAddress[i] == NULL) {
554 ALOGE("Failed to find variable address for %s: %s",
555 line, dlerror());
556 // Not a critical error if we don't find a global variable.
557 }
558 else {
559 //ALOGE("Found variable %s at %p", line,
560 //mFieldAddress[i]);
561 }
562 }
563 }
564
565 size_t funcCount = 0;
566 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
567 goto error;
568 }
569 if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
570 ALOGE("Invalid export func count!: %s", line);
571 goto error;
572 }
573
574 mExportedFunctionCount = funcCount;
575 //ALOGE("funcCount: %zu", funcCount);
576
577 if (funcCount > 0) {
578 mInvokeFunctions = new InvokeFunc_t[funcCount];
579 if (mInvokeFunctions == NULL) {
580 goto error;
581 }
582 for (size_t i = 0; i < funcCount; ++i) {
583 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
584 goto error;
585 }
586 char *c = strrchr(line, '\n');
587 if (c) {
588 *c = '\0';
589 }
590
591 mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line);
592 if (mInvokeFunctions[i] == NULL) {
593 ALOGE("Failed to get function address for %s(): %s",
594 line, dlerror());
595 goto error;
596 }
597 else {
598 //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]);
599 }
600 }
601 }
602
603 size_t forEachCount = 0;
604 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
605 goto error;
606 }
607 if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
608 ALOGE("Invalid export forEach count!: %s", line);
609 goto error;
610 }
611
612 if (forEachCount > 0) {
613
614 mForEachSignatures = new uint32_t[forEachCount];
615 if (mForEachSignatures == NULL) {
616 goto error;
617 }
618 mForEachFunctions = new ForEachFunc_t[forEachCount];
619 if (mForEachFunctions == NULL) {
620 goto error;
621 }
622 for (size_t i = 0; i < forEachCount; ++i) {
623 unsigned int tmpSig = 0;
624 char tmpName[MAXLINE];
625
626 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
627 goto error;
628 }
629 if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
630 &tmpSig, tmpName) != 2) {
631 ALOGE("Invalid export forEach!: %s", line);
632 goto error;
633 }
634
635 // Lookup the expanded ForEach kernel.
636 strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
637 mForEachSignatures[i] = tmpSig;
638 mForEachFunctions[i] =
639 (ForEachFunc_t) dlsym(mScriptSO, tmpName);
Stephen Hinesef7481e2013-04-09 19:05:27 -0700640 if (i != 0 && mForEachFunctions[i] == NULL) {
Jason Sams110f1812013-03-14 16:02:18 -0700641 // Ignore missing root.expand functions.
642 // root() is always specified at location 0.
Stephen Hinesef7481e2013-04-09 19:05:27 -0700643 ALOGE("Failed to find forEach function address for %s: %s",
644 tmpName, dlerror());
645 goto error;
Jason Sams110f1812013-03-14 16:02:18 -0700646 }
647 else {
648 //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]);
649 }
650 }
651 }
652
653 size_t objectSlotCount = 0;
654 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
655 goto error;
656 }
657 if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
658 ALOGE("Invalid object slot count!: %s", line);
659 goto error;
660 }
661
662 if (objectSlotCount > 0) {
663 rsAssert(varCount > 0);
664 for (size_t i = 0; i < objectSlotCount; ++i) {
665 uint32_t varNum = 0;
666 if (strgets(line, MAXLINE, &rsInfo) == NULL) {
667 goto error;
668 }
669 if (sscanf(line, "%u", &varNum) != 1) {
670 ALOGE("Invalid object slot!: %s", line);
671 goto error;
672 }
673
674 if (varNum < varCount) {
675 mFieldIsObject[varNum] = true;
676 }
677 }
678 }
679
680 if (varCount > 0) {
681 mBoundAllocs = new Allocation *[varCount];
682 memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs));
683 }
684
685 if (mScriptSO == (void*)1) {
686 //rsdLookupRuntimeStub(script, "acos");
687 }
Stephen Hinesc2c11cc2013-07-19 01:07:42 -0700688 } else {
689 goto error;
Jason Sams110f1812013-03-14 16:02:18 -0700690 }
691#endif
Jason Sams709a0972012-11-15 18:18:04 -0800692 mCtx->unlockMutex();
693 return true;
Jason Sams110f1812013-03-14 16:02:18 -0700694
695#ifdef RS_COMPATIBILITY_LIB
696error:
697
698 mCtx->unlockMutex();
699 delete[] mInvokeFunctions;
700 delete[] mForEachFunctions;
701 delete[] mFieldAddress;
702 delete[] mFieldIsObject;
703 delete[] mForEachSignatures;
704 delete[] mBoundAllocs;
705 if (mScriptSO) {
706 dlclose(mScriptSO);
707 }
708 return false;
709#endif
Jason Sams709a0972012-11-15 18:18:04 -0800710}
711
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -0700712#ifndef RS_COMPATIBILITY_LIB
713
714#ifdef __LP64__
715#define SYSLIBPATH "/system/lib64"
716#else
717#define SYSLIBPATH "/system/lib"
718#endif
719
720const char* RsdCpuScriptImpl::findCoreLib(const bcinfo::MetadataExtractor& ME, const char* bitcode,
721 size_t bitcodeSize) {
722 const char* defaultLib = SYSLIBPATH"/libclcore.bc";
723
724 // If we're debugging, use the debug library.
725 if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
726 return SYSLIBPATH"/libclcore_debug.bc";
727 }
728
729 // If a callback has been registered to specify a library, use that.
730 RSSelectRTCallback selectRTCallback = mCtx->getSelectRTCallback();
731 if (selectRTCallback != NULL) {
732 return selectRTCallback((const char*)bitcode, bitcodeSize);
733 }
734
735 // Check for a platform specific library
736#if defined(ARCH_ARM_HAVE_NEON) && !defined(DISABLE_CLCORE_NEON)
737 enum bcinfo::RSFloatPrecision prec = ME.getRSFloatPrecision();
Jean-Luc Brouilletf4d38362014-07-09 17:46:03 -0700738 if (prec == bcinfo::RS_FP_Relaxed) {
Jean-Luc Brouillet9ab50942014-06-18 18:10:32 -0700739 // NEON-capable ARMv7a devices can use an accelerated math library
740 // for all reduced precision scripts.
741 // ARMv8 does not use NEON, as ASIMD can be used with all precision
742 // levels.
743 return SYSLIBPATH"/libclcore_neon.bc";
744 } else {
745 return defaultLib;
746 }
747#elif defined(__i386__) || defined(__x86_64__)
748 // x86 devices will use an optimized library.
749 return SYSLIBPATH"/libclcore_x86.bc";
750#else
751 return defaultLib;
752#endif
753}
754
755#endif
756
Jason Sams709a0972012-11-15 18:18:04 -0800757void RsdCpuScriptImpl::populateScript(Script *script) {
Jason Sams110f1812013-03-14 16:02:18 -0700758#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800759 // Copy info over to runtime
Tim Murray29809d12014-05-28 12:04:19 -0700760 script->mHal.info.exportedFunctionCount = mExecutable->getExportFuncAddrs().size();
761 script->mHal.info.exportedVariableCount = mExecutable->getExportVarAddrs().size();
762 script->mHal.info.exportedForeachFuncList = &mExportedForEachFuncList[0];
763 script->mHal.info.exportedPragmaCount = mExecutable->getPragmaKeys().size();
Jason Sams709a0972012-11-15 18:18:04 -0800764 script->mHal.info.exportedPragmaKeyList =
Chris Wailes70d49712014-08-08 14:42:33 -0700765 const_cast<const char**>(&mExecutable->getPragmaKeys().front());
Jason Sams709a0972012-11-15 18:18:04 -0800766 script->mHal.info.exportedPragmaValueList =
Chris Wailes70d49712014-08-08 14:42:33 -0700767 const_cast<const char**>(&mExecutable->getPragmaValues().front());
Jason Sams709a0972012-11-15 18:18:04 -0800768
769 if (mRootExpand) {
770 script->mHal.info.root = mRootExpand;
771 } else {
772 script->mHal.info.root = mRoot;
773 }
Jason Sams110f1812013-03-14 16:02:18 -0700774#else
775 // Copy info over to runtime
776 script->mHal.info.exportedFunctionCount = mExportedFunctionCount;
777 script->mHal.info.exportedVariableCount = mExportedVariableCount;
778 script->mHal.info.exportedPragmaCount = 0;
779 script->mHal.info.exportedPragmaKeyList = 0;
780 script->mHal.info.exportedPragmaValueList = 0;
781
782 // Bug, need to stash in metadata
783 if (mRootExpand) {
784 script->mHal.info.root = mRootExpand;
785 } else {
786 script->mHal.info.root = mRoot;
787 }
788#endif
Jason Sams709a0972012-11-15 18:18:04 -0800789}
790
Jason Sams709a0972012-11-15 18:18:04 -0800791
792typedef void (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
793
Chris Wailesf3712132014-07-16 15:18:30 -0700794void RsdCpuScriptImpl::forEachMtlsSetup(const Allocation ** ains,
795 uint32_t inLen,
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700796 Allocation * aout,
797 const void * usr, uint32_t usrLen,
798 const RsScriptCall *sc,
799 MTLaunchStruct *mtls) {
800
801 memset(mtls, 0, sizeof(MTLaunchStruct));
802
Chris Wailesf3712132014-07-16 15:18:30 -0700803 for (int index = inLen; --index >= 0;) {
804 const Allocation* ain = ains[index];
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700805
Chris Wailesf3712132014-07-16 15:18:30 -0700806 // possible for this to occur if IO_OUTPUT/IO_INPUT with no bound surface
807 if (ain != NULL && (const uint8_t *)ain->mHal.drvState.lod[0].mallocPtr == NULL) {
808 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
809 "rsForEach called with null in allocations");
810 return;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700811 }
812 }
813
814 if (aout && (const uint8_t *)aout->mHal.drvState.lod[0].mallocPtr == NULL) {
Chris Wailesf3712132014-07-16 15:18:30 -0700815 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
816 "rsForEach called with null out allocations");
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700817 return;
818 }
819
Chris Wailesf3712132014-07-16 15:18:30 -0700820 if (inLen > 0) {
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700821 const Allocation *ain0 = ains[0];
822 const Type *inType = ain0->getType();
823
824 mtls->fep.dimX = inType->getDimX();
825 mtls->fep.dimY = inType->getDimY();
826 mtls->fep.dimZ = inType->getDimZ();
827
828 for (int Index = inLen; --Index >= 1;) {
829 if (!ain0->hasSameDims(ains[Index])) {
830 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
831 "Failed to launch kernel; dimensions of input and output allocations do not match.");
832
833 return;
834 }
835 }
836
837 } else if (aout != NULL) {
838 const Type *outType = aout->getType();
839
840 mtls->fep.dimX = outType->getDimX();
841 mtls->fep.dimY = outType->getDimY();
842 mtls->fep.dimZ = outType->getDimZ();
843
844 } else {
Chris Wailesf3712132014-07-16 15:18:30 -0700845 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
846 "rsForEach called with null allocations");
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700847 return;
848 }
849
Chris Wailesf3712132014-07-16 15:18:30 -0700850 if (inLen > 0 && aout != NULL) {
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700851 if (!ains[0]->hasSameDims(aout)) {
852 mCtx->getContext()->setError(RS_ERROR_BAD_SCRIPT,
853 "Failed to launch kernel; dimensions of input and output allocations do not match.");
854
855 return;
856 }
857 }
858
859 if (!sc || (sc->xEnd == 0)) {
860 mtls->xEnd = mtls->fep.dimX;
861 } else {
862 rsAssert(sc->xStart < mtls->fep.dimX);
863 rsAssert(sc->xEnd <= mtls->fep.dimX);
864 rsAssert(sc->xStart < sc->xEnd);
865 mtls->xStart = rsMin(mtls->fep.dimX, sc->xStart);
866 mtls->xEnd = rsMin(mtls->fep.dimX, sc->xEnd);
867 if (mtls->xStart >= mtls->xEnd) return;
868 }
869
870 if (!sc || (sc->yEnd == 0)) {
871 mtls->yEnd = mtls->fep.dimY;
872 } else {
873 rsAssert(sc->yStart < mtls->fep.dimY);
874 rsAssert(sc->yEnd <= mtls->fep.dimY);
875 rsAssert(sc->yStart < sc->yEnd);
876 mtls->yStart = rsMin(mtls->fep.dimY, sc->yStart);
877 mtls->yEnd = rsMin(mtls->fep.dimY, sc->yEnd);
878 if (mtls->yStart >= mtls->yEnd) return;
879 }
880
881 if (!sc || (sc->zEnd == 0)) {
882 mtls->zEnd = mtls->fep.dimZ;
883 } else {
884 rsAssert(sc->zStart < mtls->fep.dimZ);
885 rsAssert(sc->zEnd <= mtls->fep.dimZ);
886 rsAssert(sc->zStart < sc->zEnd);
887 mtls->zStart = rsMin(mtls->fep.dimZ, sc->zStart);
888 mtls->zEnd = rsMin(mtls->fep.dimZ, sc->zEnd);
889 if (mtls->zStart >= mtls->zEnd) return;
890 }
891
892 mtls->xEnd = rsMax((uint32_t)1, mtls->xEnd);
893 mtls->yEnd = rsMax((uint32_t)1, mtls->yEnd);
894 mtls->zEnd = rsMax((uint32_t)1, mtls->zEnd);
895 mtls->arrayEnd = rsMax((uint32_t)1, mtls->arrayEnd);
896
Chris Wailesf3712132014-07-16 15:18:30 -0700897 rsAssert(inLen == 0 || (ains[0]->getType()->getDimZ() == 0));
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700898
899 mtls->rsc = mCtx;
900 mtls->ains = ains;
901 mtls->aout = aout;
902 mtls->fep.usr = usr;
903 mtls->fep.usrLen = usrLen;
904 mtls->mSliceSize = 1;
905 mtls->mSliceNum = 0;
906
Chris Wailesf3712132014-07-16 15:18:30 -0700907 mtls->fep.inPtrs = NULL;
908 mtls->fep.inStrides = NULL;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700909 mtls->isThreadable = mIsThreadable;
910
Chris Wailesf3712132014-07-16 15:18:30 -0700911 if (inLen > 0) {
912
913 if (inLen <= RS_KERNEL_INPUT_THRESHOLD) {
914 mtls->fep.inPtrs = (const uint8_t**)mtls->inPtrsBuff;
915 mtls->fep.inStrides = mtls->inStridesBuff;
916 } else {
917 mtls->fep.heapAllocatedArrays = true;
918
919 mtls->fep.inPtrs = new const uint8_t*[inLen];
920 mtls->fep.inStrides = new StridePair[inLen];
921 }
922
923 mtls->fep.inLen = inLen;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700924
925 for (int index = inLen; --index >= 0;) {
926 const Allocation *ain = ains[index];
927
Chris Wailesf3712132014-07-16 15:18:30 -0700928 mtls->fep.inPtrs[index] =
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700929 (const uint8_t*)ain->mHal.drvState.lod[0].mallocPtr;
930
931 mtls->fep.inStrides[index].eStride =
932 ain->getType()->getElementSizeBytes();
933 mtls->fep.inStrides[index].yStride =
934 ain->mHal.drvState.lod[0].stride;
935 }
936 }
937
Chris Wailesf3712132014-07-16 15:18:30 -0700938 mtls->fep.outPtr = NULL;
939 mtls->fep.outStride.eStride = 0;
940 mtls->fep.outStride.yStride = 0;
941 if (aout != NULL) {
942 mtls->fep.outPtr = (uint8_t *)aout->mHal.drvState.lod[0].mallocPtr;
943
944 mtls->fep.outStride.eStride = aout->getType()->getElementSizeBytes();
945 mtls->fep.outStride.yStride = aout->mHal.drvState.lod[0].stride;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700946 }
947}
948
Jason Sams709a0972012-11-15 18:18:04 -0800949
950void RsdCpuScriptImpl::invokeForEach(uint32_t slot,
Chris Wailesf3712132014-07-16 15:18:30 -0700951 const Allocation ** ains,
952 uint32_t inLen,
Jason Sams709a0972012-11-15 18:18:04 -0800953 Allocation * aout,
954 const void * usr,
955 uint32_t usrLen,
956 const RsScriptCall *sc) {
957
958 MTLaunchStruct mtls;
Chris Wailes4b3c34e2014-06-11 12:00:29 -0700959
960 forEachMtlsSetup(ains, inLen, aout, usr, usrLen, sc, &mtls);
961 forEachKernelSetup(slot, &mtls);
962
963 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
964 mCtx->launchThreads(ains, inLen, aout, sc, &mtls);
965 mCtx->setTLS(oldTLS);
966}
967
Jason Sams709a0972012-11-15 18:18:04 -0800968void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) {
Jason Sams709a0972012-11-15 18:18:04 -0800969 mtls->script = this;
970 mtls->fep.slot = slot;
Jason Sams110f1812013-03-14 16:02:18 -0700971#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -0800972 rsAssert(slot < mExecutable->getExportForeachFuncAddrs().size());
973 mtls->kernel = reinterpret_cast<ForEachFunc_t>(
974 mExecutable->getExportForeachFuncAddrs()[slot]);
975 rsAssert(mtls->kernel != NULL);
976 mtls->sig = mExecutable->getInfo().getExportForeachFuncs()[slot].second;
Jason Sams110f1812013-03-14 16:02:18 -0700977#else
978 mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]);
979 rsAssert(mtls->kernel != NULL);
980 mtls->sig = mForEachSignatures[slot];
981#endif
Jason Sams709a0972012-11-15 18:18:04 -0800982}
983
984int RsdCpuScriptImpl::invokeRoot() {
985 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
986 int ret = mRoot();
987 mCtx->setTLS(oldTLS);
988 return ret;
989}
990
991void RsdCpuScriptImpl::invokeInit() {
992 if (mInit) {
993 mInit();
994 }
995}
996
997void RsdCpuScriptImpl::invokeFreeChildren() {
998 if (mFreeChildren) {
999 mFreeChildren();
1000 }
1001}
1002
1003void RsdCpuScriptImpl::invokeFunction(uint32_t slot, const void *params,
1004 size_t paramLength) {
1005 //ALOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength);
1006
1007 RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
1008 reinterpret_cast<void (*)(const void *, uint32_t)>(
Jason Sams110f1812013-03-14 16:02:18 -07001009#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001010 mExecutable->getExportFuncAddrs()[slot])(params, paramLength);
Jason Sams110f1812013-03-14 16:02:18 -07001011#else
1012 mInvokeFunctions[slot])(params, paramLength);
1013#endif
Jason Sams709a0972012-11-15 18:18:04 -08001014 mCtx->setTLS(oldTLS);
1015}
1016
1017void RsdCpuScriptImpl::setGlobalVar(uint32_t slot, const void *data, size_t dataLength) {
1018 //rsAssert(!script->mFieldIsObject[slot]);
1019 //ALOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
1020
1021 //if (mIntrinsicID) {
1022 //mIntrinsicFuncs.setVar(dc, script, drv->mIntrinsicData, slot, data, dataLength);
1023 //return;
1024 //}
1025
Jason Sams110f1812013-03-14 16:02:18 -07001026#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001027 int32_t *destPtr = reinterpret_cast<int32_t *>(
1028 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001029#else
1030 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1031#endif
Jason Sams709a0972012-11-15 18:18:04 -08001032 if (!destPtr) {
1033 //ALOGV("Calling setVar on slot = %i which is null", slot);
1034 return;
1035 }
1036
1037 memcpy(destPtr, data, dataLength);
1038}
1039
Tim Murray9c642392013-04-11 13:29:59 -07001040void RsdCpuScriptImpl::getGlobalVar(uint32_t slot, void *data, size_t dataLength) {
1041 //rsAssert(!script->mFieldIsObject[slot]);
1042 //ALOGE("getGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength);
1043
1044#ifndef RS_COMPATIBILITY_LIB
1045 int32_t *srcPtr = reinterpret_cast<int32_t *>(
1046 mExecutable->getExportVarAddrs()[slot]);
1047#else
1048 int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1049#endif
1050 if (!srcPtr) {
1051 //ALOGV("Calling setVar on slot = %i which is null", slot);
1052 return;
1053 }
1054 memcpy(data, srcPtr, dataLength);
1055}
1056
1057
Jason Sams709a0972012-11-15 18:18:04 -08001058void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength,
1059 const Element *elem,
Stephen Hinesac8d1462014-06-25 00:01:23 -07001060 const uint32_t *dims, size_t dimLength) {
Jason Sams709a0972012-11-15 18:18:04 -08001061
Jason Sams110f1812013-03-14 16:02:18 -07001062#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001063 int32_t *destPtr = reinterpret_cast<int32_t *>(
1064 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001065#else
1066 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1067#endif
Jason Sams709a0972012-11-15 18:18:04 -08001068 if (!destPtr) {
1069 //ALOGV("Calling setVar on slot = %i which is null", slot);
1070 return;
1071 }
1072
1073 // We want to look at dimension in terms of integer components,
1074 // but dimLength is given in terms of bytes.
1075 dimLength /= sizeof(int);
1076
1077 // Only a single dimension is currently supported.
1078 rsAssert(dimLength == 1);
1079 if (dimLength == 1) {
1080 // First do the increment loop.
1081 size_t stride = elem->getSizeBytes();
1082 const char *cVal = reinterpret_cast<const char *>(data);
Stephen Hinesac8d1462014-06-25 00:01:23 -07001083 for (uint32_t i = 0; i < dims[0]; i++) {
Jason Sams709a0972012-11-15 18:18:04 -08001084 elem->incRefs(cVal);
1085 cVal += stride;
1086 }
1087
1088 // Decrement loop comes after (to prevent race conditions).
1089 char *oldVal = reinterpret_cast<char *>(destPtr);
Stephen Hinesac8d1462014-06-25 00:01:23 -07001090 for (uint32_t i = 0; i < dims[0]; i++) {
Jason Sams709a0972012-11-15 18:18:04 -08001091 elem->decRefs(oldVal);
1092 oldVal += stride;
1093 }
1094 }
1095
1096 memcpy(destPtr, data, dataLength);
1097}
1098
1099void RsdCpuScriptImpl::setGlobalBind(uint32_t slot, Allocation *data) {
1100
1101 //rsAssert(!script->mFieldIsObject[slot]);
1102 //ALOGE("setGlobalBind %p %p %i %p", dc, script, slot, data);
1103
Jason Sams110f1812013-03-14 16:02:18 -07001104#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001105 int32_t *destPtr = reinterpret_cast<int32_t *>(
1106 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001107#else
1108 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1109#endif
Jason Sams709a0972012-11-15 18:18:04 -08001110 if (!destPtr) {
1111 //ALOGV("Calling setVar on slot = %i which is null", slot);
1112 return;
1113 }
1114
1115 void *ptr = NULL;
1116 mBoundAllocs[slot] = data;
1117 if(data) {
1118 ptr = data->mHal.drvState.lod[0].mallocPtr;
1119 }
1120 memcpy(destPtr, &ptr, sizeof(void *));
1121}
1122
1123void RsdCpuScriptImpl::setGlobalObj(uint32_t slot, ObjectBase *data) {
1124
1125 //rsAssert(script->mFieldIsObject[slot]);
1126 //ALOGE("setGlobalObj %p %p %i %p", dc, script, slot, data);
1127
Jason Sams110f1812013-03-14 16:02:18 -07001128#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001129 int32_t *destPtr = reinterpret_cast<int32_t *>(
1130 mExecutable->getExportVarAddrs()[slot]);
Jason Sams110f1812013-03-14 16:02:18 -07001131#else
1132 int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
1133#endif
Tim Murraye195a3f2014-03-13 15:04:58 -07001134
Jason Sams709a0972012-11-15 18:18:04 -08001135 if (!destPtr) {
1136 //ALOGV("Calling setVar on slot = %i which is null", slot);
1137 return;
1138 }
1139
Jason Sams05ef73f2014-08-05 14:59:22 -07001140 rsrSetObject(mCtx->getContext(), (rs_object_base *)destPtr, data);
Jason Sams709a0972012-11-15 18:18:04 -08001141}
1142
1143RsdCpuScriptImpl::~RsdCpuScriptImpl() {
Jason Sams110f1812013-03-14 16:02:18 -07001144#ifndef RS_COMPATIBILITY_LIB
Jason Sams709a0972012-11-15 18:18:04 -08001145 if (mExecutable) {
Chris Wailes70d49712014-08-08 14:42:33 -07001146 std::vector<void *>::const_iterator var_addr_iter =
Jason Sams709a0972012-11-15 18:18:04 -08001147 mExecutable->getExportVarAddrs().begin();
Chris Wailes70d49712014-08-08 14:42:33 -07001148 std::vector<void *>::const_iterator var_addr_end =
Jason Sams709a0972012-11-15 18:18:04 -08001149 mExecutable->getExportVarAddrs().end();
1150
1151 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_iter =
1152 mExecutable->getInfo().getObjectSlots().begin();
1153 bcc::RSInfo::ObjectSlotListTy::const_iterator is_object_end =
1154 mExecutable->getInfo().getObjectSlots().end();
1155
1156 while ((var_addr_iter != var_addr_end) &&
1157 (is_object_iter != is_object_end)) {
1158 // The field address can be NULL if the script-side has optimized
1159 // the corresponding global variable away.
Jason Sams05ef73f2014-08-05 14:59:22 -07001160 rs_object_base *obj_addr =
1161 reinterpret_cast<rs_object_base *>(*var_addr_iter);
Jason Sams709a0972012-11-15 18:18:04 -08001162 if (*is_object_iter) {
Jason Samsa36c50a2014-06-17 12:06:06 -07001163 if (*var_addr_iter != NULL && mCtx->getContext() != NULL) {
Jason Sams709a0972012-11-15 18:18:04 -08001164 rsrClearObject(mCtx->getContext(), obj_addr);
1165 }
1166 }
1167 var_addr_iter++;
1168 is_object_iter++;
1169 }
1170 }
1171
1172 if (mCompilerContext) {
1173 delete mCompilerContext;
1174 }
1175 if (mCompilerDriver) {
1176 delete mCompilerDriver;
1177 }
1178 if (mExecutable) {
1179 delete mExecutable;
1180 }
1181 if (mBoundAllocs) {
1182 delete[] mBoundAllocs;
1183 }
Tim Murraybee48d72014-06-13 12:44:47 -07001184
Tim Murray29809d12014-05-28 12:04:19 -07001185 for (size_t i = 0; i < mExportedForEachFuncList.size(); i++) {
1186 delete[] mExportedForEachFuncList[i].first;
1187 }
Jason Sams110f1812013-03-14 16:02:18 -07001188#else
1189 if (mFieldIsObject) {
1190 for (size_t i = 0; i < mExportedVariableCount; ++i) {
1191 if (mFieldIsObject[i]) {
1192 if (mFieldAddress[i] != NULL) {
Jason Sams05ef73f2014-08-05 14:59:22 -07001193 rs_object_base *obj_addr =
1194 reinterpret_cast<rs_object_base *>(mFieldAddress[i]);
Jason Sams110f1812013-03-14 16:02:18 -07001195 rsrClearObject(mCtx->getContext(), obj_addr);
1196 }
1197 }
1198 }
1199 }
1200
1201 if (mInvokeFunctions) delete[] mInvokeFunctions;
1202 if (mForEachFunctions) delete[] mForEachFunctions;
1203 if (mFieldAddress) delete[] mFieldAddress;
1204 if (mFieldIsObject) delete[] mFieldIsObject;
1205 if (mForEachSignatures) delete[] mForEachSignatures;
1206 if (mBoundAllocs) delete[] mBoundAllocs;
1207 if (mScriptSO) {
1208 dlclose(mScriptSO);
1209 }
1210#endif
Jason Sams709a0972012-11-15 18:18:04 -08001211}
1212
1213Allocation * RsdCpuScriptImpl::getAllocationForPointer(const void *ptr) const {
1214 if (!ptr) {
1215 return NULL;
1216 }
1217
1218 for (uint32_t ct=0; ct < mScript->mHal.info.exportedVariableCount; ct++) {
1219 Allocation *a = mBoundAllocs[ct];
1220 if (!a) continue;
1221 if (a->mHal.drvState.lod[0].mallocPtr == ptr) {
1222 return a;
1223 }
1224 }
1225 ALOGE("rsGetAllocation, failed to find %p", ptr);
1226 return NULL;
1227}
1228
Chris Wailesf3712132014-07-16 15:18:30 -07001229void RsdCpuScriptImpl::preLaunch(uint32_t slot, const Allocation ** ains,
1230 uint32_t inLen, Allocation * aout,
1231 const void * usr, uint32_t usrLen,
1232 const RsScriptCall *sc) {}
Jason Sams17e3cdc2013-09-09 17:32:16 -07001233
Chris Wailesf3712132014-07-16 15:18:30 -07001234void RsdCpuScriptImpl::postLaunch(uint32_t slot, const Allocation ** ains,
1235 uint32_t inLen, Allocation * aout,
1236 const void * usr, uint32_t usrLen,
1237 const RsScriptCall *sc) {}
Jason Sams17e3cdc2013-09-09 17:32:16 -07001238
Jason Sams709a0972012-11-15 18:18:04 -08001239
1240}
1241}