blob: 0ecb18a28d885c98e4fc953974e7b2378ea31f14 [file] [log] [blame]
Jason Sams326e0dd2009-05-22 14:03:28 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "rsContext.h"
18#include "rsScriptC.h"
19#include "rsMatrix.h"
Joe Onorato9c4e4ca2009-08-09 11:39:02 -070020#include "utils/Timers.h"
Alex Sakhartchoukb26fb042010-09-24 15:18:12 -070021#include "utils/StopWatch.h"
Shih-wei Liaoce8a0792010-12-20 20:45:56 +080022extern "C" {
23#include "libdex/ZipArchive.h"
24}
Jack Palevich1ef8b802009-05-28 15:53:04 -070025
Jason Sams1aa5a4e2009-06-22 17:15:15 -070026#include <GLES/gl.h>
27#include <GLES/glext.h>
28
Jason Sams326e0dd2009-05-22 14:03:28 -070029using namespace android;
30using namespace android::renderscript;
31
Jason Samse5769102009-06-19 16:03:18 -070032#define GET_TLS() Context::ScriptTLSStruct * tls = \
33 (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
34 Context * rsc = tls->mContext; \
35 ScriptC * sc = (ScriptC *) tls->mScript
36
Shih-wei Liao2b2e6212011-01-14 06:21:28 -080037// Input: cacheDir
38// Input: resName
39// Input: extName
40//
41// Note: cacheFile = resName + extName
42//
43// Output: Returns cachePath == cacheDir + cacheFile
44char *genCacheFileName(const char *cacheDir,
45 const char *resName,
46 const char *extName) {
47 char cachePath[512];
48 char cacheFile[sizeof(cachePath)];
49 const size_t kBufLen = sizeof(cachePath) - 1;
50
51 cacheFile[0] = '\0';
52 // Note: resName today is usually something like
53 // "/com.android.fountain:raw/fountain"
54 if (resName[0] != '/') {
55 // Get the absolute path of the raw/***.bc file.
56
57 // Generate the absolute path. This doesn't do everything it
58 // should, e.g. if resName is "./out/whatever" it doesn't crunch
59 // the leading "./" out because this if-block is not triggered,
60 // but it'll make do.
61 //
62 if (getcwd(cacheFile, kBufLen) == NULL) {
63 LOGE("Can't get CWD while opening raw/***.bc file\n");
64 return NULL;
65 }
66 // Append "/" at the end of cacheFile so far.
67 strncat(cacheFile, "/", kBufLen);
68 }
69
70 // cacheFile = resName + extName
71 //
72 strncat(cacheFile, resName, kBufLen);
73 if (extName != NULL) {
74 // TODO(srhines): strncat() is a bit dangerous
75 strncat(cacheFile, extName, kBufLen);
76 }
77
78 // Turn the path into a flat filename by replacing
79 // any slashes after the first one with '@' characters.
80 char *cp = cacheFile + 1;
81 while (*cp != '\0') {
82 if (*cp == '/') {
83 *cp = '@';
84 }
85 cp++;
86 }
87
88 // Tack on the file name for the actual cache file path.
89 strncpy(cachePath, cacheDir, kBufLen);
90 strncat(cachePath, cacheFile, kBufLen);
91
92 LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath);
93 return strdup(cachePath);
94}
Jason Sams326e0dd2009-05-22 14:03:28 -070095
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080096ScriptC::ScriptC(Context *rsc) : Script(rsc) {
Jason Sams741aac92010-12-24 14:38:39 -080097 LOGD(">>>> ScriptC ctor called, obj=%p", this);
Jason Samsbe36bf32010-05-11 14:03:58 -070098 mBccScript = NULL;
Jason Samsefb8de12009-06-08 15:20:31 -070099 memset(&mProgram, 0, sizeof(mProgram));
Jason Sams326e0dd2009-05-22 14:03:28 -0700100}
101
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800102ScriptC::~ScriptC() {
Jason Sams741aac92010-12-24 14:38:39 -0800103 LOGD(">>>> ~ScriptC() mBccScript = %p", mBccScript);
Jason Samsbe36bf32010-05-11 14:03:58 -0700104 if (mBccScript) {
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800105 bccDisposeScript(mBccScript);
Shih-wei Liaoa6ebec82010-12-23 23:04:21 +0800106 LOGD(">>>> ~ScriptC(mBCCScript)");
Jack Palevich1ef8b802009-05-28 15:53:04 -0700107 }
Jason Samse402ed32009-11-03 11:25:42 -0800108 free(mEnviroment.mScriptText);
109 mEnviroment.mScriptText = NULL;
Jason Sams326e0dd2009-05-22 14:03:28 -0700110}
111
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800112void ScriptC::setupScript(Context *rsc) {
Jason Samsc61346b2010-05-28 18:23:22 -0700113 mEnviroment.mStartTimeMillis
114 = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
115
Jason Samsbe36bf32010-05-11 14:03:58 -0700116 for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
Jason Sams900f1612010-09-16 18:18:29 -0700117 if (mSlots[ct].get() && !mTypes[ct].get()) {
118 mTypes[ct].set(mSlots[ct]->getType());
119 }
120
121 if (!mTypes[ct].get())
Jason Samsbe36bf32010-05-11 14:03:58 -0700122 continue;
Jason Sams900f1612010-09-16 18:18:29 -0700123 void *ptr = NULL;
124 if (mSlots[ct].get()) {
125 ptr = mSlots[ct]->getPtr();
126 }
Jason Samsbe36bf32010-05-11 14:03:58 -0700127 void **dest = ((void ***)mEnviroment.mFieldAddress)[ct];
Jason Samsbe36bf32010-05-11 14:03:58 -0700128
Jason Samsb9077f42010-09-22 15:57:41 -0700129 if (rsc->props.mLogScripts) {
Jason Sams2fad7e42010-11-16 12:19:26 -0800130 if (mSlots[ct].get() != NULL) {
131 LOGV("%p ScriptC::setupScript slot=%i dst=%p src=%p type=%p", rsc, ct, dest, ptr, mSlots[ct]->getType());
132 } else {
133 LOGV("%p ScriptC::setupScript slot=%i dst=%p src=%p type=null", rsc, ct, dest, ptr);
134 }
Jason Samsb9077f42010-09-22 15:57:41 -0700135 }
Jason Samsbe36bf32010-05-11 14:03:58 -0700136
137 if (dest) {
138 *dest = ptr;
Jason Samsada7f272009-09-24 14:55:38 -0700139 }
140 }
141}
142
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800143const Allocation *ScriptC::ptrToAllocation(const void *ptr) const {
Jason Samsce92d4b2010-05-17 14:55:34 -0700144 if (!ptr) {
145 return NULL;
146 }
147 for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
148 if (!mSlots[ct].get())
149 continue;
150 if (mSlots[ct]->getPtr() == ptr) {
151 return mSlots[ct].get();
152 }
153 }
154 LOGE("ScriptC::ptrToAllocation, failed to find %p", ptr);
155 return NULL;
156}
157
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800158Script * ScriptC::setTLS(Script *sc) {
Jason Sams22fa3712010-05-19 17:22:57 -0700159 Context::ScriptTLSStruct * tls = (Context::ScriptTLSStruct *)
160 pthread_getspecific(Context::gThreadTLSKey);
161 rsAssert(tls);
Jason Samsc61346b2010-05-28 18:23:22 -0700162 Script *old = tls->mScript;
163 tls->mScript = sc;
164 return old;
Jason Sams22fa3712010-05-19 17:22:57 -0700165}
166
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800167void ScriptC::setupGLState(Context *rsc) {
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700168 if (mEnviroment.mFragmentStore.get()) {
Jason Sams60709252010-11-17 15:29:32 -0800169 rsc->setProgramStore(mEnviroment.mFragmentStore.get());
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700170 }
171 if (mEnviroment.mFragment.get()) {
Jason Sams60709252010-11-17 15:29:32 -0800172 rsc->setProgramFragment(mEnviroment.mFragment.get());
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700173 }
Jason Sams8ce125b2009-06-17 16:52:59 -0700174 if (mEnviroment.mVertex.get()) {
Jason Sams60709252010-11-17 15:29:32 -0800175 rsc->setProgramVertex(mEnviroment.mVertex.get());
Jason Sams8ce125b2009-06-17 16:52:59 -0700176 }
Jason Samsb681c8a2009-09-28 18:12:56 -0700177 if (mEnviroment.mRaster.get()) {
Jason Sams60709252010-11-17 15:29:32 -0800178 rsc->setProgramRaster(mEnviroment.mRaster.get());
Jason Samsb681c8a2009-09-28 18:12:56 -0700179 }
Jason Samsc61346b2010-05-28 18:23:22 -0700180}
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700181
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800182uint32_t ScriptC::run(Context *rsc) {
Jason Samsc61346b2010-05-28 18:23:22 -0700183 if (mProgram.mRoot == NULL) {
184 rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
185 return 0;
Joe Onorato9c4e4ca2009-08-09 11:39:02 -0700186 }
Jason Samsc61346b2010-05-28 18:23:22 -0700187
Jason Sams1f24db42010-12-11 17:42:30 -0800188 setupGLState(rsc);
Jason Samsc61346b2010-05-28 18:23:22 -0700189 setupScript(rsc);
Jason Sams1d54f102009-09-03 15:43:13 -0700190
Jason Sams2dca84d2009-12-09 11:05:45 -0800191 uint32_t ret = 0;
Jason Samsc61346b2010-05-28 18:23:22 -0700192 Script * oldTLS = setTLS(this);
Jason Samsb9077f42010-09-22 15:57:41 -0700193
194 if (rsc->props.mLogScripts) {
195 LOGV("%p ScriptC::run invoking root, ptr %p", rsc, mProgram.mRoot);
196 }
197
Jason Samsbe36bf32010-05-11 14:03:58 -0700198 ret = mProgram.mRoot();
Jason Samsb9077f42010-09-22 15:57:41 -0700199
200 if (rsc->props.mLogScripts) {
201 LOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret);
202 }
203
Jason Samsc61346b2010-05-28 18:23:22 -0700204 setTLS(oldTLS);
Jason Samse45ac6e2009-07-20 14:31:06 -0700205 return ret;
Jason Sams326e0dd2009-05-22 14:03:28 -0700206}
207
Jason Sams7bf29dd2010-07-19 15:38:19 -0700208typedef struct {
209 Context *rsc;
210 ScriptC *script;
211 const Allocation * ain;
212 Allocation * aout;
213 const void * usr;
214
215 uint32_t mSliceSize;
216 volatile int mSliceNum;
217
218 const uint8_t *ptrIn;
219 uint32_t eStrideIn;
220 uint8_t *ptrOut;
221 uint32_t eStrideOut;
222
223 uint32_t xStart;
224 uint32_t xEnd;
225 uint32_t yStart;
226 uint32_t yEnd;
227 uint32_t zStart;
228 uint32_t zEnd;
229 uint32_t arrayStart;
230 uint32_t arrayEnd;
231
232 uint32_t dimX;
233 uint32_t dimY;
234 uint32_t dimZ;
235 uint32_t dimArray;
236} MTLaunchStruct;
237typedef int (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
238
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800239static void wc_xy(void *usr, uint32_t idx) {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700240 MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
Jason Sams7bf29dd2010-07-19 15:38:19 -0700241
242 while (1) {
243 uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
244 uint32_t yStart = mtls->yStart + slice * mtls->mSliceSize;
245 uint32_t yEnd = yStart + mtls->mSliceSize;
246 yEnd = rsMin(yEnd, mtls->yEnd);
247 if (yEnd <= yStart) {
248 return;
249 }
250
251 //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
Jason Sams8d957fa2010-09-28 14:41:22 -0700252 //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut);
Jason Sams7bf29dd2010-07-19 15:38:19 -0700253 for (uint32_t y = yStart; y < yEnd; y++) {
254 uint32_t offset = mtls->dimX * y;
255 uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * offset);
256 const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * offset);
257
258 for (uint32_t x = mtls->xStart; x < mtls->xEnd; x++) {
259 ((rs_t)mtls->script->mProgram.mRoot) (xPtrIn, xPtrOut, mtls->usr, x, y, 0, 0);
260 xPtrIn += mtls->eStrideIn;
261 xPtrOut += mtls->eStrideOut;
262 }
263 }
264 }
Jason Sams7bf29dd2010-07-19 15:38:19 -0700265}
266
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800267static void wc_x(void *usr, uint32_t idx) {
Jason Sams177f8442010-10-29 10:19:21 -0700268 MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
269
270 while (1) {
271 uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
272 uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize;
273 uint32_t xEnd = xStart + mtls->mSliceSize;
274 xEnd = rsMin(xEnd, mtls->xEnd);
275 if (xEnd <= xStart) {
276 return;
277 }
278
279 //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
280 //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut);
281 uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * xStart);
282 const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * xStart);
283 for (uint32_t x = xStart; x < xEnd; x++) {
284 ((rs_t)mtls->script->mProgram.mRoot) (xPtrIn, xPtrOut, mtls->usr, x, 0, 0, 0);
285 xPtrIn += mtls->eStrideIn;
286 xPtrOut += mtls->eStrideOut;
287 }
288 }
Jason Sams177f8442010-10-29 10:19:21 -0700289}
290
Jason Samsace3e012010-07-15 17:11:13 -0700291void ScriptC::runForEach(Context *rsc,
292 const Allocation * ain,
293 Allocation * aout,
294 const void * usr,
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800295 const RsScriptCall *sc) {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700296 MTLaunchStruct mtls;
297 memset(&mtls, 0, sizeof(mtls));
Jason Sams60709252010-11-17 15:29:32 -0800298 Context::PushState ps(rsc);
Jason Samsc61346b2010-05-28 18:23:22 -0700299
Jason Sams7bf29dd2010-07-19 15:38:19 -0700300 if (ain) {
301 mtls.dimX = ain->getType()->getDimX();
302 mtls.dimY = ain->getType()->getDimY();
303 mtls.dimZ = ain->getType()->getDimZ();
304 //mtls.dimArray = ain->getType()->getDimArray();
305 } else if (aout) {
306 mtls.dimX = aout->getType()->getDimX();
307 mtls.dimY = aout->getType()->getDimY();
308 mtls.dimZ = aout->getType()->getDimZ();
309 //mtls.dimArray = aout->getType()->getDimArray();
310 } else {
311 rsc->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
312 return;
313 }
Jason Samsace3e012010-07-15 17:11:13 -0700314
315 if (!sc || (sc->xEnd == 0)) {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700316 mtls.xEnd = mtls.dimX;
Jason Samsace3e012010-07-15 17:11:13 -0700317 } else {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700318 rsAssert(sc->xStart < mtls.dimX);
319 rsAssert(sc->xEnd <= mtls.dimX);
Jason Samsace3e012010-07-15 17:11:13 -0700320 rsAssert(sc->xStart < sc->xEnd);
Jason Sams7bf29dd2010-07-19 15:38:19 -0700321 mtls.xStart = rsMin(mtls.dimX, sc->xStart);
322 mtls.xEnd = rsMin(mtls.dimX, sc->xEnd);
323 if (mtls.xStart >= mtls.xEnd) return;
Jason Samsace3e012010-07-15 17:11:13 -0700324 }
325
326 if (!sc || (sc->yEnd == 0)) {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700327 mtls.yEnd = mtls.dimY;
Jason Samsace3e012010-07-15 17:11:13 -0700328 } else {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700329 rsAssert(sc->yStart < mtls.dimY);
330 rsAssert(sc->yEnd <= mtls.dimY);
Jason Samsace3e012010-07-15 17:11:13 -0700331 rsAssert(sc->yStart < sc->yEnd);
Jason Sams7bf29dd2010-07-19 15:38:19 -0700332 mtls.yStart = rsMin(mtls.dimY, sc->yStart);
333 mtls.yEnd = rsMin(mtls.dimY, sc->yEnd);
334 if (mtls.yStart >= mtls.yEnd) return;
Jason Samsace3e012010-07-15 17:11:13 -0700335 }
336
Jason Sams7bf29dd2010-07-19 15:38:19 -0700337 mtls.xEnd = rsMax((uint32_t)1, mtls.xEnd);
338 mtls.yEnd = rsMax((uint32_t)1, mtls.yEnd);
339 mtls.zEnd = rsMax((uint32_t)1, mtls.zEnd);
340 mtls.arrayEnd = rsMax((uint32_t)1, mtls.arrayEnd);
Jason Samsace3e012010-07-15 17:11:13 -0700341
342 rsAssert(ain->getType()->getDimZ() == 0);
Jason Samsc61346b2010-05-28 18:23:22 -0700343
Jason Sams1f24db42010-12-11 17:42:30 -0800344 setupGLState(rsc);
Jason Samsc61346b2010-05-28 18:23:22 -0700345 setupScript(rsc);
346 Script * oldTLS = setTLS(this);
347
Jason Sams7bf29dd2010-07-19 15:38:19 -0700348 mtls.rsc = rsc;
349 mtls.ain = ain;
350 mtls.aout = aout;
351 mtls.script = this;
352 mtls.usr = usr;
353 mtls.mSliceSize = 10;
354 mtls.mSliceNum = 0;
Jason Samsc61346b2010-05-28 18:23:22 -0700355
Jason Sams7bf29dd2010-07-19 15:38:19 -0700356 mtls.ptrIn = NULL;
357 mtls.eStrideIn = 0;
358 if (ain) {
359 mtls.ptrIn = (const uint8_t *)ain->getPtr();
360 mtls.eStrideIn = ain->getType()->getElementSizeBytes();
Jason Samsc61346b2010-05-28 18:23:22 -0700361 }
362
Jason Sams7bf29dd2010-07-19 15:38:19 -0700363 mtls.ptrOut = NULL;
364 mtls.eStrideOut = 0;
365 if (aout) {
366 mtls.ptrOut = (uint8_t *)aout->getPtr();
367 mtls.eStrideOut = aout->getType()->getElementSizeBytes();
368 }
369
Jason Sams177f8442010-10-29 10:19:21 -0700370 if ((rsc->getWorkerPoolSize() > 1) && mEnviroment.mIsThreadable) {
371 if (mtls.dimY > 1) {
372 rsc->launchThreads(wc_xy, &mtls);
373 } else {
374 rsc->launchThreads(wc_x, &mtls);
375 }
Jason Sams18133402010-07-20 15:09:00 -0700376
377 //LOGE("launch 1");
Jason Sams18133402010-07-20 15:09:00 -0700378 } else {
Jason Sams8d957fa2010-09-28 14:41:22 -0700379 //LOGE("launch 3");
Jason Sams18133402010-07-20 15:09:00 -0700380 for (uint32_t ar = mtls.arrayStart; ar < mtls.arrayEnd; ar++) {
381 for (uint32_t z = mtls.zStart; z < mtls.zEnd; z++) {
382 for (uint32_t y = mtls.yStart; y < mtls.yEnd; y++) {
383 uint32_t offset = mtls.dimX * mtls.dimY * mtls.dimZ * ar +
384 mtls.dimX * mtls.dimY * z +
385 mtls.dimX * y;
386 uint8_t *xPtrOut = mtls.ptrOut + (mtls.eStrideOut * offset);
387 const uint8_t *xPtrIn = mtls.ptrIn + (mtls.eStrideIn * offset);
Jason Sams7bf29dd2010-07-19 15:38:19 -0700388
Jason Sams18133402010-07-20 15:09:00 -0700389 for (uint32_t x = mtls.xStart; x < mtls.xEnd; x++) {
390 ((rs_t)mProgram.mRoot) (xPtrIn, xPtrOut, usr, x, y, z, ar);
391 xPtrIn += mtls.eStrideIn;
392 xPtrOut += mtls.eStrideOut;
393 }
Jason Samsace3e012010-07-15 17:11:13 -0700394 }
395 }
396 }
Jason Samsc61346b2010-05-28 18:23:22 -0700397 }
Jason Sams18133402010-07-20 15:09:00 -0700398
Jason Samsc61346b2010-05-28 18:23:22 -0700399 setTLS(oldTLS);
400}
401
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800402void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len) {
Jason Sams22fa3712010-05-19 17:22:57 -0700403 if ((slot >= mEnviroment.mInvokeFunctionCount) ||
404 (mEnviroment.mInvokeFunctions[slot] == NULL)) {
405 rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script");
406 return;
407 }
Jason Samsc61346b2010-05-28 18:23:22 -0700408 setupScript(rsc);
409 Script * oldTLS = setTLS(this);
Jason Sams22fa3712010-05-19 17:22:57 -0700410
Jason Samsb9077f42010-09-22 15:57:41 -0700411 if (rsc->props.mLogScripts) {
412 LOGV("%p ScriptC::Invoke invoking slot %i, ptr %p", rsc, slot, mEnviroment.mInvokeFunctions[slot]);
413 }
Jason Sams2a63bf62010-06-08 15:40:48 -0700414 ((void (*)(const void *, uint32_t))
415 mEnviroment.mInvokeFunctions[slot])(data, len);
Jason Samsb9077f42010-09-22 15:57:41 -0700416 if (rsc->props.mLogScripts) {
417 LOGV("%p ScriptC::Invoke complete", rsc);
418 }
Jason Sams2a63bf62010-06-08 15:40:48 -0700419
Jason Samsc61346b2010-05-28 18:23:22 -0700420 setTLS(oldTLS);
Jason Sams22fa3712010-05-19 17:22:57 -0700421}
422
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800423ScriptCState::ScriptCState() {
Stephen Hines01b7d292010-09-28 15:45:45 -0700424 mScript.clear();
Jason Sams326e0dd2009-05-22 14:03:28 -0700425}
426
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800427ScriptCState::~ScriptCState() {
Stephen Hines01b7d292010-09-28 15:45:45 -0700428 mScript.clear();
Jason Sams326e0dd2009-05-22 14:03:28 -0700429}
430
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800431void ScriptCState::init(Context *rsc) {
Stephen Hines01b7d292010-09-28 15:45:45 -0700432 clear(rsc);
433}
434
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800435void ScriptCState::clear(Context *rsc) {
Stephen Hines01b7d292010-09-28 15:45:45 -0700436 rsAssert(rsc);
Stephen Hines01b7d292010-09-28 15:45:45 -0700437 mScript.clear();
438 mScript.set(new ScriptC(rsc));
Jason Sams1f526332009-06-05 17:35:09 -0700439}
440
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800441static void* symbolLookup(void* pContext, char const* name) {
Jason Samsaeb094b2010-05-18 13:35:45 -0700442 const ScriptCState::SymbolTable_t *sym;
Jason Samsdd663fa2010-08-11 13:26:28 -0700443 ScriptC *s = (ScriptC *)pContext;
Shih-wei Liaof17b13b2010-12-07 13:44:10 -0800444 if (!strcmp(name, "__isThreadable")) {
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800445 return (void*) s->mEnviroment.mIsThreadable;
Shih-wei Liaof17b13b2010-12-07 13:44:10 -0800446 } else if (!strcmp(name, "__clearThreadable")) {
447 s->mEnviroment.mIsThreadable = false;
448 return NULL;
449 }
Jason Samsaeb094b2010-05-18 13:35:45 -0700450 sym = ScriptCState::lookupSymbol(name);
Jason Sams6bfc1b92010-11-01 14:26:30 -0700451 if (!sym) {
452 sym = ScriptCState::lookupSymbolCL(name);
Jason Samsaeb094b2010-05-18 13:35:45 -0700453 }
Jason Sams6bfc1b92010-11-01 14:26:30 -0700454 if (!sym) {
455 sym = ScriptCState::lookupSymbolGL(name);
Jason Samsaeb094b2010-05-18 13:35:45 -0700456 }
Jason Sams29df66f2009-07-16 15:08:06 -0700457 if (sym) {
Jason Sams6bfc1b92010-11-01 14:26:30 -0700458 s->mEnviroment.mIsThreadable &= sym->threadable;
Jason Sams29df66f2009-07-16 15:08:06 -0700459 return sym->mPtr;
460 }
Jason Sams29df66f2009-07-16 15:08:06 -0700461 LOGE("ScriptC sym lookup failed for %s", name);
Jason Sams29df66f2009-07-16 15:08:06 -0700462 return NULL;
463}
Jason Samsa4a54e42009-06-10 18:39:40 -0700464
Shih-wei Liao80761ec2011-01-16 02:23:04 -0800465#if 0
Shih-wei Liao1f9ba732010-10-23 02:15:57 -0700466extern const char rs_runtime_lib_bc[];
467extern unsigned rs_runtime_lib_bc_size;
Shih-wei Liao80761ec2011-01-16 02:23:04 -0800468#endif
Shih-wei Liao1f9ba732010-10-23 02:15:57 -0700469
Shih-wei Liaoce8a0792010-12-20 20:45:56 +0800470void ScriptCState::runCompiler(Context *rsc,
471 ScriptC *s,
Shih-wei Liaoce8a0792010-12-20 20:45:56 +0800472 const char *resName,
473 const char *cacheDir) {
Alex Sakhartchoukb26fb042010-09-24 15:18:12 -0700474 {
Alex Sakhartchoukb26fb042010-09-24 15:18:12 -0700475 s->mBccScript = bccCreateScript();
Shih-wei Liao37150de2011-01-07 18:17:07 -0800476
Alex Sakhartchoukb26fb042010-09-24 15:18:12 -0700477 s->mEnviroment.mIsThreadable = true;
Shih-wei Liao37150de2011-01-07 18:17:07 -0800478
Alex Sakhartchoukb26fb042010-09-24 15:18:12 -0700479 bccRegisterSymbolCallback(s->mBccScript, symbolLookup, s);
Shih-wei Liao37150de2011-01-07 18:17:07 -0800480
Shih-wei Liao9503b662010-11-08 01:33:59 -0800481 if (bccReadBC(s->mBccScript,
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800482 resName,
Shih-wei Liao9503b662010-11-08 01:33:59 -0800483 s->mEnviroment.mScriptText,
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800484 s->mEnviroment.mScriptTextLength, 0) != 0) {
Shih-wei Liao37150de2011-01-07 18:17:07 -0800485 LOGE("bcc: FAILS to read bitcode");
486 // Handle Fatal Error
Shih-wei Liao9503b662010-11-08 01:33:59 -0800487 }
Shih-wei Liao37150de2011-01-07 18:17:07 -0800488
Shih-wei Liao80761ec2011-01-16 02:23:04 -0800489#if 1
Shih-wei Liao37150de2011-01-07 18:17:07 -0800490 if (bccLinkBC(s->mBccScript,
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800491 resName,
Shih-wei Liao80761ec2011-01-16 02:23:04 -0800492 NULL /*rs_runtime_lib_bc*/,
493 0 /*rs_runtime_lib_bc_size*/,
494 0) != 0) {
Shih-wei Liao37150de2011-01-07 18:17:07 -0800495 LOGE("bcc: FAILS to link bitcode");
496 // Handle Fatal Error
497 }
498#endif
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800499 char *cachePath = genCacheFileName(cacheDir, resName, ".oBCC");
Shih-wei Liao37150de2011-01-07 18:17:07 -0800500
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800501 if (bccPrepareExecutable(s->mBccScript, cachePath, 0) != 0) {
Shih-wei Liao37150de2011-01-07 18:17:07 -0800502 LOGE("bcc: FAILS to prepare executable");
503 // Handle Fatal Error
504 }
505
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800506 free(cachePath);
507
508 s->mProgram.mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(s->mBccScript, "root"));
509 s->mProgram.mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(s->mBccScript, "init"));
Alex Sakhartchoukb26fb042010-09-24 15:18:12 -0700510 }
Jason Samsb9077f42010-09-22 15:57:41 -0700511 LOGV("%p ScriptCState::runCompiler root %p, init %p", rsc, s->mProgram.mRoot, s->mProgram.mInit);
Jason Samsf1685042009-07-16 17:47:40 -0700512
Jason Sams8c6bc692009-09-16 15:04:38 -0700513 if (s->mProgram.mInit) {
514 s->mProgram.mInit();
Jason Sams1d54f102009-09-03 15:43:13 -0700515 }
516
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800517 s->mEnviroment.mInvokeFunctionCount = bccGetExportFuncCount(s->mBccScript);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800518 if (s->mEnviroment.mInvokeFunctionCount <= 0)
Jason Sams8c880902010-06-15 12:15:57 -0700519 s->mEnviroment.mInvokeFunctions = NULL;
520 else {
521 s->mEnviroment.mInvokeFunctions = (Script::InvokeFunc_t*) calloc(s->mEnviroment.mInvokeFunctionCount, sizeof(Script::InvokeFunc_t));
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800522 bccGetExportFuncList(s->mBccScript, s->mEnviroment.mInvokeFunctionCount, (void **) s->mEnviroment.mInvokeFunctions);
Jason Sams1d54f102009-09-03 15:43:13 -0700523 }
524
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800525 s->mEnviroment.mFieldCount = bccGetExportVarCount(s->mBccScript);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800526 if (s->mEnviroment.mFieldCount <= 0)
Shih-wei Liaoa226b162010-07-20 16:43:25 -0700527 s->mEnviroment.mFieldAddress = NULL;
528 else {
529 s->mEnviroment.mFieldAddress = (void **) calloc(s->mEnviroment.mFieldCount, sizeof(void *));
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800530 bccGetExportVarList(s->mBccScript, s->mEnviroment.mFieldCount, (void **) s->mEnviroment.mFieldAddress);
Alex Sakhartchouk700ba382010-10-08 15:00:05 -0700531 s->initSlots();
Shih-wei Liaoa226b162010-07-20 16:43:25 -0700532 }
Jason Samsa4a54e42009-06-10 18:39:40 -0700533
Jason Sams8c6bc692009-09-16 15:04:38 -0700534 s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
535 s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
Jason Samsccc010b2010-05-13 18:30:11 -0700536 s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
Jason Samsb681c8a2009-09-28 18:12:56 -0700537 s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
Jason Sams8c6bc692009-09-16 15:04:38 -0700538
Jason Samsbe36bf32010-05-11 14:03:58 -0700539 if (s->mProgram.mRoot) {
Jason Sams10308932009-06-09 12:15:30 -0700540 const static int pragmaMax = 16;
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800541 size_t pragmaCount = bccGetPragmaCount(s->mBccScript);
542 char const *keys[pragmaMax];
543 char const *values[pragmaMax];
544 bccGetPragmaList(s->mBccScript, pragmaMax, keys, values);
Jason Sams10308932009-06-09 12:15:30 -0700545
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800546 for (size_t i=0; i < pragmaCount; ++i) {
547 //LOGE("pragma %s %s", keys[i], values[i]);
548 if (!strcmp(keys[i], "version")) {
Jason Sams10308932009-06-09 12:15:30 -0700549 continue;
Jason Sams10308932009-06-09 12:15:30 -0700550 }
551
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800552 if (!strcmp(keys[i], "stateVertex")) {
553 if (!strcmp(values[i], "default")) {
Jason Sams8ce125b2009-06-17 16:52:59 -0700554 continue;
555 }
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800556 if (!strcmp(values[i], "parent")) {
Jason Sams8c6bc692009-09-16 15:04:38 -0700557 s->mEnviroment.mVertex.clear();
Jason Sams8ce125b2009-06-17 16:52:59 -0700558 continue;
559 }
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800560 LOGE("Unreconized value %s passed to stateVertex", values[i]);
Jason Sams10308932009-06-09 12:15:30 -0700561 }
562
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800563 if (!strcmp(keys[i], "stateRaster")) {
564 if (!strcmp(values[i], "default")) {
Jason Samsb681c8a2009-09-28 18:12:56 -0700565 continue;
566 }
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800567 if (!strcmp(values[i], "parent")) {
Jason Samsb681c8a2009-09-28 18:12:56 -0700568 s->mEnviroment.mRaster.clear();
569 continue;
570 }
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800571 LOGE("Unreconized value %s passed to stateRaster", values[i]);
Jason Sams10308932009-06-09 12:15:30 -0700572 }
573
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800574 if (!strcmp(keys[i], "stateFragment")) {
575 if (!strcmp(values[i], "default")) {
Jason Sams8ce125b2009-06-17 16:52:59 -0700576 continue;
577 }
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800578 if (!strcmp(values[i], "parent")) {
Jason Sams8c6bc692009-09-16 15:04:38 -0700579 s->mEnviroment.mFragment.clear();
Jason Sams8ce125b2009-06-17 16:52:59 -0700580 continue;
581 }
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800582 LOGE("Unreconized value %s passed to stateFragment", values[i]);
Jason Sams10308932009-06-09 12:15:30 -0700583 }
584
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800585 if (!strcmp(keys[i], "stateStore")) {
586 if (!strcmp(values[i], "default")) {
Jason Sams8ce125b2009-06-17 16:52:59 -0700587 continue;
588 }
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800589 if (!strcmp(values[i], "parent")) {
Jason Sams8c6bc692009-09-16 15:04:38 -0700590 s->mEnviroment.mFragmentStore.clear();
Jason Sams8ce125b2009-06-17 16:52:59 -0700591 continue;
592 }
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800593 LOGE("Unreconized value %s passed to stateStore", values[i]);
Jason Sams10308932009-06-09 12:15:30 -0700594 }
Jason Sams10308932009-06-09 12:15:30 -0700595 }
Jason Sams10308932009-06-09 12:15:30 -0700596 } else {
Shih-wei Liao37150de2011-01-07 18:17:07 -0800597 LOGE("bcc: FAILS to prepare executable");
598 // Handle Fatal Error
Jason Sams10308932009-06-09 12:15:30 -0700599 }
Jason Sams326e0dd2009-05-22 14:03:28 -0700600}
601
602namespace android {
603namespace renderscript {
604
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800605void rsi_ScriptCBegin(Context * rsc) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700606 ScriptCState *ss = &rsc->mScriptC;
Stephen Hines01b7d292010-09-28 15:45:45 -0700607 ss->clear(rsc);
Jason Sams326e0dd2009-05-22 14:03:28 -0700608}
609
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800610void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len) {
Jason Sams1f526332009-06-05 17:35:09 -0700611 ScriptCState *ss = &rsc->mScriptC;
Jason Samse402ed32009-11-03 11:25:42 -0800612
613 char *t = (char *)malloc(len + 1);
614 memcpy(t, text, len);
615 t[len] = 0;
616 ss->mScript->mEnviroment.mScriptText = t;
Jason Sams8c6bc692009-09-16 15:04:38 -0700617 ss->mScript->mEnviroment.mScriptTextLength = len;
Jason Sams1f526332009-06-05 17:35:09 -0700618}
619
Shih-wei Liaoce8a0792010-12-20 20:45:56 +0800620
621RsScript rsi_ScriptCCreate(Context *rsc,
Shih-wei Liao37150de2011-01-07 18:17:07 -0800622 const char *packageName /* deprecated */,
Shih-wei Liaoce8a0792010-12-20 20:45:56 +0800623 const char *resName,
624 const char *cacheDir)
Shih-wei Liao9503b662010-11-08 01:33:59 -0800625{
Jason Sams326e0dd2009-05-22 14:03:28 -0700626 ScriptCState *ss = &rsc->mScriptC;
627
Jason Sams225afd32010-10-21 14:06:55 -0700628 ObjectBaseRef<ScriptC> s(ss->mScript);
Stephen Hines01b7d292010-09-28 15:45:45 -0700629 ss->mScript.clear();
Jason Sams225afd32010-10-21 14:06:55 -0700630 s->incUserRef();
Jason Sams1f526332009-06-05 17:35:09 -0700631
Shih-wei Liao37150de2011-01-07 18:17:07 -0800632 ss->runCompiler(rsc, s.get(), resName, cacheDir);
Stephen Hines01b7d292010-09-28 15:45:45 -0700633 ss->clear(rsc);
634 return s.get();
Jason Sams326e0dd2009-05-22 14:03:28 -0700635}
636
Jason Sams326e0dd2009-05-22 14:03:28 -0700637}
638}