blob: fc673a2d517bf7750556c0d62b83464289392b5f [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 Samsbe36bf32010-05-11 14:03:58 -070097 mBccScript = NULL;
Jason Samsefb8de12009-06-08 15:20:31 -070098 memset(&mProgram, 0, sizeof(mProgram));
Jason Sams326e0dd2009-05-22 14:03:28 -070099}
100
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800101ScriptC::~ScriptC() {
Jason Samsbe36bf32010-05-11 14:03:58 -0700102 if (mBccScript) {
Jason Sams2e8665d2011-01-27 00:14:13 -0800103 if (mProgram.mObjectSlotList) {
104 for (size_t ct=0; ct < mProgram.mObjectSlotCount; ct++) {
105 setVarObj(mProgram.mObjectSlotList[ct], NULL);
106 }
107 delete [] mProgram.mObjectSlotList;
108 mProgram.mObjectSlotList = NULL;
109 mProgram.mObjectSlotCount = 0;
110 }
111
112
113 LOGD(">>>> ~ScriptC bccDisposeScript(%p)", mBccScript);
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800114 bccDisposeScript(mBccScript);
Jack Palevich1ef8b802009-05-28 15:53:04 -0700115 }
Jason Samse402ed32009-11-03 11:25:42 -0800116 free(mEnviroment.mScriptText);
117 mEnviroment.mScriptText = NULL;
Jason Sams326e0dd2009-05-22 14:03:28 -0700118}
119
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800120void ScriptC::setupScript(Context *rsc) {
Jason Samsc61346b2010-05-28 18:23:22 -0700121 mEnviroment.mStartTimeMillis
122 = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
123
Jason Samsbe36bf32010-05-11 14:03:58 -0700124 for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
Jason Sams900f1612010-09-16 18:18:29 -0700125 if (mSlots[ct].get() && !mTypes[ct].get()) {
126 mTypes[ct].set(mSlots[ct]->getType());
127 }
128
129 if (!mTypes[ct].get())
Jason Samsbe36bf32010-05-11 14:03:58 -0700130 continue;
Jason Sams900f1612010-09-16 18:18:29 -0700131 void *ptr = NULL;
132 if (mSlots[ct].get()) {
133 ptr = mSlots[ct]->getPtr();
134 }
Jason Samsbe36bf32010-05-11 14:03:58 -0700135 void **dest = ((void ***)mEnviroment.mFieldAddress)[ct];
Jason Samsbe36bf32010-05-11 14:03:58 -0700136
Jason Samsb9077f42010-09-22 15:57:41 -0700137 if (rsc->props.mLogScripts) {
Jason Sams2fad7e42010-11-16 12:19:26 -0800138 if (mSlots[ct].get() != NULL) {
139 LOGV("%p ScriptC::setupScript slot=%i dst=%p src=%p type=%p", rsc, ct, dest, ptr, mSlots[ct]->getType());
140 } else {
141 LOGV("%p ScriptC::setupScript slot=%i dst=%p src=%p type=null", rsc, ct, dest, ptr);
142 }
Jason Samsb9077f42010-09-22 15:57:41 -0700143 }
Jason Samsbe36bf32010-05-11 14:03:58 -0700144
145 if (dest) {
146 *dest = ptr;
Jason Samsada7f272009-09-24 14:55:38 -0700147 }
148 }
149}
150
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800151const Allocation *ScriptC::ptrToAllocation(const void *ptr) const {
Jason Samsce92d4b2010-05-17 14:55:34 -0700152 if (!ptr) {
153 return NULL;
154 }
155 for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
156 if (!mSlots[ct].get())
157 continue;
158 if (mSlots[ct]->getPtr() == ptr) {
159 return mSlots[ct].get();
160 }
161 }
162 LOGE("ScriptC::ptrToAllocation, failed to find %p", ptr);
163 return NULL;
164}
165
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800166Script * ScriptC::setTLS(Script *sc) {
Jason Sams22fa3712010-05-19 17:22:57 -0700167 Context::ScriptTLSStruct * tls = (Context::ScriptTLSStruct *)
168 pthread_getspecific(Context::gThreadTLSKey);
169 rsAssert(tls);
Jason Samsc61346b2010-05-28 18:23:22 -0700170 Script *old = tls->mScript;
171 tls->mScript = sc;
172 return old;
Jason Sams22fa3712010-05-19 17:22:57 -0700173}
174
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800175void ScriptC::setupGLState(Context *rsc) {
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700176 if (mEnviroment.mFragmentStore.get()) {
Jason Sams60709252010-11-17 15:29:32 -0800177 rsc->setProgramStore(mEnviroment.mFragmentStore.get());
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700178 }
179 if (mEnviroment.mFragment.get()) {
Jason Sams60709252010-11-17 15:29:32 -0800180 rsc->setProgramFragment(mEnviroment.mFragment.get());
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700181 }
Jason Sams8ce125b2009-06-17 16:52:59 -0700182 if (mEnviroment.mVertex.get()) {
Jason Sams60709252010-11-17 15:29:32 -0800183 rsc->setProgramVertex(mEnviroment.mVertex.get());
Jason Sams8ce125b2009-06-17 16:52:59 -0700184 }
Jason Samsb681c8a2009-09-28 18:12:56 -0700185 if (mEnviroment.mRaster.get()) {
Jason Sams60709252010-11-17 15:29:32 -0800186 rsc->setProgramRaster(mEnviroment.mRaster.get());
Jason Samsb681c8a2009-09-28 18:12:56 -0700187 }
Jason Samsc61346b2010-05-28 18:23:22 -0700188}
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700189
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800190uint32_t ScriptC::run(Context *rsc) {
Jason Samsc61346b2010-05-28 18:23:22 -0700191 if (mProgram.mRoot == NULL) {
192 rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
193 return 0;
Joe Onorato9c4e4ca2009-08-09 11:39:02 -0700194 }
Jason Samsc61346b2010-05-28 18:23:22 -0700195
Jason Sams1f24db42010-12-11 17:42:30 -0800196 setupGLState(rsc);
Jason Samsc61346b2010-05-28 18:23:22 -0700197 setupScript(rsc);
Jason Sams1d54f102009-09-03 15:43:13 -0700198
Jason Sams2dca84d2009-12-09 11:05:45 -0800199 uint32_t ret = 0;
Jason Samsc61346b2010-05-28 18:23:22 -0700200 Script * oldTLS = setTLS(this);
Jason Samsb9077f42010-09-22 15:57:41 -0700201
202 if (rsc->props.mLogScripts) {
203 LOGV("%p ScriptC::run invoking root, ptr %p", rsc, mProgram.mRoot);
204 }
205
Jason Samsbe36bf32010-05-11 14:03:58 -0700206 ret = mProgram.mRoot();
Jason Samsb9077f42010-09-22 15:57:41 -0700207
208 if (rsc->props.mLogScripts) {
209 LOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret);
210 }
211
Jason Samsc61346b2010-05-28 18:23:22 -0700212 setTLS(oldTLS);
Jason Samse45ac6e2009-07-20 14:31:06 -0700213 return ret;
Jason Sams326e0dd2009-05-22 14:03:28 -0700214}
215
Jason Sams7bf29dd2010-07-19 15:38:19 -0700216typedef struct {
217 Context *rsc;
218 ScriptC *script;
219 const Allocation * ain;
220 Allocation * aout;
221 const void * usr;
222
223 uint32_t mSliceSize;
224 volatile int mSliceNum;
225
226 const uint8_t *ptrIn;
227 uint32_t eStrideIn;
228 uint8_t *ptrOut;
229 uint32_t eStrideOut;
230
231 uint32_t xStart;
232 uint32_t xEnd;
233 uint32_t yStart;
234 uint32_t yEnd;
235 uint32_t zStart;
236 uint32_t zEnd;
237 uint32_t arrayStart;
238 uint32_t arrayEnd;
239
240 uint32_t dimX;
241 uint32_t dimY;
242 uint32_t dimZ;
243 uint32_t dimArray;
244} MTLaunchStruct;
245typedef int (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
246
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800247static void wc_xy(void *usr, uint32_t idx) {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700248 MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
Jason Sams7bf29dd2010-07-19 15:38:19 -0700249
250 while (1) {
251 uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
252 uint32_t yStart = mtls->yStart + slice * mtls->mSliceSize;
253 uint32_t yEnd = yStart + mtls->mSliceSize;
254 yEnd = rsMin(yEnd, mtls->yEnd);
255 if (yEnd <= yStart) {
256 return;
257 }
258
259 //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
Jason Sams8d957fa2010-09-28 14:41:22 -0700260 //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut);
Jason Sams7bf29dd2010-07-19 15:38:19 -0700261 for (uint32_t y = yStart; y < yEnd; y++) {
262 uint32_t offset = mtls->dimX * y;
263 uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * offset);
264 const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * offset);
265
266 for (uint32_t x = mtls->xStart; x < mtls->xEnd; x++) {
267 ((rs_t)mtls->script->mProgram.mRoot) (xPtrIn, xPtrOut, mtls->usr, x, y, 0, 0);
268 xPtrIn += mtls->eStrideIn;
269 xPtrOut += mtls->eStrideOut;
270 }
271 }
272 }
Jason Sams7bf29dd2010-07-19 15:38:19 -0700273}
274
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800275static void wc_x(void *usr, uint32_t idx) {
Jason Sams177f8442010-10-29 10:19:21 -0700276 MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
277
278 while (1) {
279 uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
280 uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize;
281 uint32_t xEnd = xStart + mtls->mSliceSize;
282 xEnd = rsMin(xEnd, mtls->xEnd);
283 if (xEnd <= xStart) {
284 return;
285 }
286
287 //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
288 //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut);
289 uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * xStart);
290 const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * xStart);
291 for (uint32_t x = xStart; x < xEnd; x++) {
292 ((rs_t)mtls->script->mProgram.mRoot) (xPtrIn, xPtrOut, mtls->usr, x, 0, 0, 0);
293 xPtrIn += mtls->eStrideIn;
294 xPtrOut += mtls->eStrideOut;
295 }
296 }
Jason Sams177f8442010-10-29 10:19:21 -0700297}
298
Jason Samsace3e012010-07-15 17:11:13 -0700299void ScriptC::runForEach(Context *rsc,
300 const Allocation * ain,
301 Allocation * aout,
302 const void * usr,
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800303 const RsScriptCall *sc) {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700304 MTLaunchStruct mtls;
305 memset(&mtls, 0, sizeof(mtls));
Jason Sams60709252010-11-17 15:29:32 -0800306 Context::PushState ps(rsc);
Jason Samsc61346b2010-05-28 18:23:22 -0700307
Jason Sams7bf29dd2010-07-19 15:38:19 -0700308 if (ain) {
309 mtls.dimX = ain->getType()->getDimX();
310 mtls.dimY = ain->getType()->getDimY();
311 mtls.dimZ = ain->getType()->getDimZ();
312 //mtls.dimArray = ain->getType()->getDimArray();
313 } else if (aout) {
314 mtls.dimX = aout->getType()->getDimX();
315 mtls.dimY = aout->getType()->getDimY();
316 mtls.dimZ = aout->getType()->getDimZ();
317 //mtls.dimArray = aout->getType()->getDimArray();
318 } else {
319 rsc->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
320 return;
321 }
Jason Samsace3e012010-07-15 17:11:13 -0700322
323 if (!sc || (sc->xEnd == 0)) {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700324 mtls.xEnd = mtls.dimX;
Jason Samsace3e012010-07-15 17:11:13 -0700325 } else {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700326 rsAssert(sc->xStart < mtls.dimX);
327 rsAssert(sc->xEnd <= mtls.dimX);
Jason Samsace3e012010-07-15 17:11:13 -0700328 rsAssert(sc->xStart < sc->xEnd);
Jason Sams7bf29dd2010-07-19 15:38:19 -0700329 mtls.xStart = rsMin(mtls.dimX, sc->xStart);
330 mtls.xEnd = rsMin(mtls.dimX, sc->xEnd);
331 if (mtls.xStart >= mtls.xEnd) return;
Jason Samsace3e012010-07-15 17:11:13 -0700332 }
333
334 if (!sc || (sc->yEnd == 0)) {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700335 mtls.yEnd = mtls.dimY;
Jason Samsace3e012010-07-15 17:11:13 -0700336 } else {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700337 rsAssert(sc->yStart < mtls.dimY);
338 rsAssert(sc->yEnd <= mtls.dimY);
Jason Samsace3e012010-07-15 17:11:13 -0700339 rsAssert(sc->yStart < sc->yEnd);
Jason Sams7bf29dd2010-07-19 15:38:19 -0700340 mtls.yStart = rsMin(mtls.dimY, sc->yStart);
341 mtls.yEnd = rsMin(mtls.dimY, sc->yEnd);
342 if (mtls.yStart >= mtls.yEnd) return;
Jason Samsace3e012010-07-15 17:11:13 -0700343 }
344
Jason Sams7bf29dd2010-07-19 15:38:19 -0700345 mtls.xEnd = rsMax((uint32_t)1, mtls.xEnd);
346 mtls.yEnd = rsMax((uint32_t)1, mtls.yEnd);
347 mtls.zEnd = rsMax((uint32_t)1, mtls.zEnd);
348 mtls.arrayEnd = rsMax((uint32_t)1, mtls.arrayEnd);
Jason Samsace3e012010-07-15 17:11:13 -0700349
350 rsAssert(ain->getType()->getDimZ() == 0);
Jason Samsc61346b2010-05-28 18:23:22 -0700351
Jason Sams1f24db42010-12-11 17:42:30 -0800352 setupGLState(rsc);
Jason Samsc61346b2010-05-28 18:23:22 -0700353 setupScript(rsc);
354 Script * oldTLS = setTLS(this);
355
Jason Sams7bf29dd2010-07-19 15:38:19 -0700356 mtls.rsc = rsc;
357 mtls.ain = ain;
358 mtls.aout = aout;
359 mtls.script = this;
360 mtls.usr = usr;
361 mtls.mSliceSize = 10;
362 mtls.mSliceNum = 0;
Jason Samsc61346b2010-05-28 18:23:22 -0700363
Jason Sams7bf29dd2010-07-19 15:38:19 -0700364 mtls.ptrIn = NULL;
365 mtls.eStrideIn = 0;
366 if (ain) {
367 mtls.ptrIn = (const uint8_t *)ain->getPtr();
368 mtls.eStrideIn = ain->getType()->getElementSizeBytes();
Jason Samsc61346b2010-05-28 18:23:22 -0700369 }
370
Jason Sams7bf29dd2010-07-19 15:38:19 -0700371 mtls.ptrOut = NULL;
372 mtls.eStrideOut = 0;
373 if (aout) {
374 mtls.ptrOut = (uint8_t *)aout->getPtr();
375 mtls.eStrideOut = aout->getType()->getElementSizeBytes();
376 }
377
Jason Sams177f8442010-10-29 10:19:21 -0700378 if ((rsc->getWorkerPoolSize() > 1) && mEnviroment.mIsThreadable) {
379 if (mtls.dimY > 1) {
380 rsc->launchThreads(wc_xy, &mtls);
381 } else {
382 rsc->launchThreads(wc_x, &mtls);
383 }
Jason Sams18133402010-07-20 15:09:00 -0700384
385 //LOGE("launch 1");
Jason Sams18133402010-07-20 15:09:00 -0700386 } else {
Jason Sams8d957fa2010-09-28 14:41:22 -0700387 //LOGE("launch 3");
Jason Sams18133402010-07-20 15:09:00 -0700388 for (uint32_t ar = mtls.arrayStart; ar < mtls.arrayEnd; ar++) {
389 for (uint32_t z = mtls.zStart; z < mtls.zEnd; z++) {
390 for (uint32_t y = mtls.yStart; y < mtls.yEnd; y++) {
391 uint32_t offset = mtls.dimX * mtls.dimY * mtls.dimZ * ar +
392 mtls.dimX * mtls.dimY * z +
393 mtls.dimX * y;
394 uint8_t *xPtrOut = mtls.ptrOut + (mtls.eStrideOut * offset);
395 const uint8_t *xPtrIn = mtls.ptrIn + (mtls.eStrideIn * offset);
Jason Sams7bf29dd2010-07-19 15:38:19 -0700396
Jason Sams18133402010-07-20 15:09:00 -0700397 for (uint32_t x = mtls.xStart; x < mtls.xEnd; x++) {
398 ((rs_t)mProgram.mRoot) (xPtrIn, xPtrOut, usr, x, y, z, ar);
399 xPtrIn += mtls.eStrideIn;
400 xPtrOut += mtls.eStrideOut;
401 }
Jason Samsace3e012010-07-15 17:11:13 -0700402 }
403 }
404 }
Jason Samsc61346b2010-05-28 18:23:22 -0700405 }
Jason Sams18133402010-07-20 15:09:00 -0700406
Jason Samsc61346b2010-05-28 18:23:22 -0700407 setTLS(oldTLS);
408}
409
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800410void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len) {
Jason Sams22fa3712010-05-19 17:22:57 -0700411 if ((slot >= mEnviroment.mInvokeFunctionCount) ||
412 (mEnviroment.mInvokeFunctions[slot] == NULL)) {
413 rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script");
414 return;
415 }
Jason Samsc61346b2010-05-28 18:23:22 -0700416 setupScript(rsc);
417 Script * oldTLS = setTLS(this);
Jason Sams22fa3712010-05-19 17:22:57 -0700418
Jason Samsb9077f42010-09-22 15:57:41 -0700419 if (rsc->props.mLogScripts) {
420 LOGV("%p ScriptC::Invoke invoking slot %i, ptr %p", rsc, slot, mEnviroment.mInvokeFunctions[slot]);
421 }
Jason Sams2a63bf62010-06-08 15:40:48 -0700422 ((void (*)(const void *, uint32_t))
423 mEnviroment.mInvokeFunctions[slot])(data, len);
Jason Samsb9077f42010-09-22 15:57:41 -0700424 if (rsc->props.mLogScripts) {
425 LOGV("%p ScriptC::Invoke complete", rsc);
426 }
Jason Sams2a63bf62010-06-08 15:40:48 -0700427
Jason Samsc61346b2010-05-28 18:23:22 -0700428 setTLS(oldTLS);
Jason Sams22fa3712010-05-19 17:22:57 -0700429}
430
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800431ScriptCState::ScriptCState() {
Jason Sams326e0dd2009-05-22 14:03:28 -0700432}
433
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800434ScriptCState::~ScriptCState() {
Jason Sams1f526332009-06-05 17:35:09 -0700435}
436
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800437static void* symbolLookup(void* pContext, char const* name) {
Jason Samsaeb094b2010-05-18 13:35:45 -0700438 const ScriptCState::SymbolTable_t *sym;
Jason Samsdd663fa2010-08-11 13:26:28 -0700439 ScriptC *s = (ScriptC *)pContext;
Shih-wei Liaof17b13b2010-12-07 13:44:10 -0800440 if (!strcmp(name, "__isThreadable")) {
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800441 return (void*) s->mEnviroment.mIsThreadable;
Shih-wei Liaof17b13b2010-12-07 13:44:10 -0800442 } else if (!strcmp(name, "__clearThreadable")) {
443 s->mEnviroment.mIsThreadable = false;
444 return NULL;
445 }
Jason Samsaeb094b2010-05-18 13:35:45 -0700446 sym = ScriptCState::lookupSymbol(name);
Jason Sams6bfc1b92010-11-01 14:26:30 -0700447 if (!sym) {
448 sym = ScriptCState::lookupSymbolCL(name);
Jason Samsaeb094b2010-05-18 13:35:45 -0700449 }
Jason Sams6bfc1b92010-11-01 14:26:30 -0700450 if (!sym) {
451 sym = ScriptCState::lookupSymbolGL(name);
Jason Samsaeb094b2010-05-18 13:35:45 -0700452 }
Jason Sams29df66f2009-07-16 15:08:06 -0700453 if (sym) {
Jason Sams6bfc1b92010-11-01 14:26:30 -0700454 s->mEnviroment.mIsThreadable &= sym->threadable;
Jason Sams29df66f2009-07-16 15:08:06 -0700455 return sym->mPtr;
456 }
Jason Sams29df66f2009-07-16 15:08:06 -0700457 LOGE("ScriptC sym lookup failed for %s", name);
Jason Sams29df66f2009-07-16 15:08:06 -0700458 return NULL;
459}
Jason Samsa4a54e42009-06-10 18:39:40 -0700460
Shih-wei Liao80761ec2011-01-16 02:23:04 -0800461#if 0
Shih-wei Liao1f9ba732010-10-23 02:15:57 -0700462extern const char rs_runtime_lib_bc[];
463extern unsigned rs_runtime_lib_bc_size;
Shih-wei Liao80761ec2011-01-16 02:23:04 -0800464#endif
Shih-wei Liao1f9ba732010-10-23 02:15:57 -0700465
Jason Sams26b2c9f2011-01-19 16:14:21 -0800466bool ScriptCState::runCompiler(Context *rsc,
Shih-wei Liaoce8a0792010-12-20 20:45:56 +0800467 ScriptC *s,
Shih-wei Liaoce8a0792010-12-20 20:45:56 +0800468 const char *resName,
469 const char *cacheDir) {
Stephen Hines7b337b12011-01-17 17:31:58 -0800470 s->mBccScript = bccCreateScript();
Shih-wei Liao37150de2011-01-07 18:17:07 -0800471
Stephen Hines7b337b12011-01-17 17:31:58 -0800472 s->mEnviroment.mIsThreadable = true;
Shih-wei Liao37150de2011-01-07 18:17:07 -0800473
Shih-wei Liaofa6113e2011-01-20 12:35:44 -0800474 if (bccRegisterSymbolCallback(s->mBccScript, symbolLookup, s) != 0) {
475 LOGE("bcc: FAILS to register symbol callback");
476 return false;
477 }
Shih-wei Liao37150de2011-01-07 18:17:07 -0800478
Stephen Hines7b337b12011-01-17 17:31:58 -0800479 if (bccReadBC(s->mBccScript,
480 resName,
481 s->mEnviroment.mScriptText,
482 s->mEnviroment.mScriptTextLength, 0) != 0) {
483 LOGE("bcc: FAILS to read bitcode");
Jason Sams26b2c9f2011-01-19 16:14:21 -0800484 return false;
Stephen Hines7b337b12011-01-17 17:31:58 -0800485 }
Shih-wei Liao37150de2011-01-07 18:17:07 -0800486
Shih-wei Liao54391842011-01-19 02:18:45 -0800487#if 1
Stephen Hines7b337b12011-01-17 17:31:58 -0800488 if (bccLinkBC(s->mBccScript,
489 resName,
490 NULL /*rs_runtime_lib_bc*/,
491 1 /*rs_runtime_lib_bc_size*/
492 /*"1" means skip buffer here, and let libbcc decide*/,
493 0) != 0) {
494 LOGE("bcc: FAILS to link bitcode");
Jason Sams26b2c9f2011-01-19 16:14:21 -0800495 return false;
Alex Sakhartchoukb26fb042010-09-24 15:18:12 -0700496 }
Stephen Hines7b337b12011-01-17 17:31:58 -0800497#endif
498 char *cachePath = genCacheFileName(cacheDir, resName, ".oBCC");
499
500 if (bccPrepareExecutable(s->mBccScript, cachePath, 0) != 0) {
501 LOGE("bcc: FAILS to prepare executable");
Jason Sams26b2c9f2011-01-19 16:14:21 -0800502 return false;
Stephen Hines7b337b12011-01-17 17:31:58 -0800503 }
504
505 free(cachePath);
506
507 s->mProgram.mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(s->mBccScript, "root"));
508 s->mProgram.mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(s->mBccScript, "init"));
Jason Samsf1685042009-07-16 17:47:40 -0700509
Jason Sams8c6bc692009-09-16 15:04:38 -0700510 if (s->mProgram.mInit) {
511 s->mProgram.mInit();
Jason Sams1d54f102009-09-03 15:43:13 -0700512 }
513
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800514 s->mEnviroment.mInvokeFunctionCount = bccGetExportFuncCount(s->mBccScript);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800515 if (s->mEnviroment.mInvokeFunctionCount <= 0)
Jason Sams8c880902010-06-15 12:15:57 -0700516 s->mEnviroment.mInvokeFunctions = NULL;
517 else {
518 s->mEnviroment.mInvokeFunctions = (Script::InvokeFunc_t*) calloc(s->mEnviroment.mInvokeFunctionCount, sizeof(Script::InvokeFunc_t));
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800519 bccGetExportFuncList(s->mBccScript, s->mEnviroment.mInvokeFunctionCount, (void **) s->mEnviroment.mInvokeFunctions);
Jason Sams1d54f102009-09-03 15:43:13 -0700520 }
521
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800522 s->mEnviroment.mFieldCount = bccGetExportVarCount(s->mBccScript);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800523 if (s->mEnviroment.mFieldCount <= 0)
Shih-wei Liaoa226b162010-07-20 16:43:25 -0700524 s->mEnviroment.mFieldAddress = NULL;
525 else {
526 s->mEnviroment.mFieldAddress = (void **) calloc(s->mEnviroment.mFieldCount, sizeof(void *));
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800527 bccGetExportVarList(s->mBccScript, s->mEnviroment.mFieldCount, (void **) s->mEnviroment.mFieldAddress);
Alex Sakhartchouk700ba382010-10-08 15:00:05 -0700528 s->initSlots();
Shih-wei Liaoa226b162010-07-20 16:43:25 -0700529 }
Jason Samsa4a54e42009-06-10 18:39:40 -0700530
Jason Sams8c6bc692009-09-16 15:04:38 -0700531 s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
532 s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
Jason Samsccc010b2010-05-13 18:30:11 -0700533 s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
Jason Samsb681c8a2009-09-28 18:12:56 -0700534 s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
Jason Sams8c6bc692009-09-16 15:04:38 -0700535
Stephen Hines7b337b12011-01-17 17:31:58 -0800536 const static int pragmaMax = 16;
537 size_t pragmaCount = bccGetPragmaCount(s->mBccScript);
538 char const *keys[pragmaMax];
539 char const *values[pragmaMax];
540 bccGetPragmaList(s->mBccScript, pragmaMax, keys, values);
Jason Sams10308932009-06-09 12:15:30 -0700541
Stephen Hines7b337b12011-01-17 17:31:58 -0800542 for (size_t i=0; i < pragmaCount; ++i) {
543 //LOGE("pragma %s %s", keys[i], values[i]);
544 if (!strcmp(keys[i], "version")) {
Stephen Hinesb5dc6af2011-01-18 14:10:44 -0800545 if (!strcmp(values[i], "1")) {
546 continue;
547 }
548 LOGE("Invalid version pragma value: %s\n", values[i]);
Jason Sams26b2c9f2011-01-19 16:14:21 -0800549 return false;
Stephen Hines7b337b12011-01-17 17:31:58 -0800550 }
551
552 if (!strcmp(keys[i], "stateVertex")) {
553 if (!strcmp(values[i], "default")) {
Jason Sams10308932009-06-09 12:15:30 -0700554 continue;
Jason Sams10308932009-06-09 12:15:30 -0700555 }
Stephen Hines7b337b12011-01-17 17:31:58 -0800556 if (!strcmp(values[i], "parent")) {
557 s->mEnviroment.mVertex.clear();
558 continue;
Jason Sams10308932009-06-09 12:15:30 -0700559 }
Stephen Hinesb5dc6af2011-01-18 14:10:44 -0800560 LOGE("Unrecognized value %s passed to stateVertex", values[i]);
Jason Sams26b2c9f2011-01-19 16:14:21 -0800561 return false;
Jason Sams10308932009-06-09 12:15:30 -0700562 }
Stephen Hines7b337b12011-01-17 17:31:58 -0800563
564 if (!strcmp(keys[i], "stateRaster")) {
565 if (!strcmp(values[i], "default")) {
566 continue;
567 }
568 if (!strcmp(values[i], "parent")) {
569 s->mEnviroment.mRaster.clear();
570 continue;
571 }
Stephen Hinesb5dc6af2011-01-18 14:10:44 -0800572 LOGE("Unrecognized value %s passed to stateRaster", values[i]);
Jason Sams26b2c9f2011-01-19 16:14:21 -0800573 return false;
Stephen Hines7b337b12011-01-17 17:31:58 -0800574 }
575
576 if (!strcmp(keys[i], "stateFragment")) {
577 if (!strcmp(values[i], "default")) {
578 continue;
579 }
580 if (!strcmp(values[i], "parent")) {
581 s->mEnviroment.mFragment.clear();
582 continue;
583 }
Stephen Hinesb5dc6af2011-01-18 14:10:44 -0800584 LOGE("Unrecognized value %s passed to stateFragment", values[i]);
Jason Sams26b2c9f2011-01-19 16:14:21 -0800585 return false;
Stephen Hines7b337b12011-01-17 17:31:58 -0800586 }
587
588 if (!strcmp(keys[i], "stateStore")) {
589 if (!strcmp(values[i], "default")) {
590 continue;
591 }
592 if (!strcmp(values[i], "parent")) {
593 s->mEnviroment.mFragmentStore.clear();
594 continue;
595 }
Stephen Hinesb5dc6af2011-01-18 14:10:44 -0800596 LOGE("Unrecognized value %s passed to stateStore", values[i]);
Jason Sams26b2c9f2011-01-19 16:14:21 -0800597 return false;
Stephen Hines7b337b12011-01-17 17:31:58 -0800598 }
Jason Sams10308932009-06-09 12:15:30 -0700599 }
Jason Sams2e8665d2011-01-27 00:14:13 -0800600
601 size_t objectSlotCount = bccGetObjectSlotCount(s->mBccScript);
602 uint32_t *objectSlots = NULL;
603 if (objectSlotCount) {
604 objectSlots = new uint32_t[objectSlotCount];
605 bccGetObjectSlotList(s->mBccScript, objectSlotCount, objectSlots);
606 s->mProgram.mObjectSlotList = objectSlots;
607 s->mProgram.mObjectSlotCount = objectSlotCount;
608 }
609
Jason Sams26b2c9f2011-01-19 16:14:21 -0800610 return true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700611}
612
613namespace android {
614namespace renderscript {
615
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800616void rsi_ScriptCBegin(Context * rsc) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700617}
618
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800619void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len) {
Jason Sams1f526332009-06-05 17:35:09 -0700620 ScriptCState *ss = &rsc->mScriptC;
Jason Samse402ed32009-11-03 11:25:42 -0800621
622 char *t = (char *)malloc(len + 1);
623 memcpy(t, text, len);
624 t[len] = 0;
Jason Sams249d4532011-01-23 17:48:45 -0800625 ss->mScriptText = t;
626 ss->mScriptLen = len;
Jason Sams1f526332009-06-05 17:35:09 -0700627}
628
Shih-wei Liaoce8a0792010-12-20 20:45:56 +0800629
630RsScript rsi_ScriptCCreate(Context *rsc,
Shih-wei Liao37150de2011-01-07 18:17:07 -0800631 const char *packageName /* deprecated */,
Shih-wei Liaoce8a0792010-12-20 20:45:56 +0800632 const char *resName,
633 const char *cacheDir)
Shih-wei Liao9503b662010-11-08 01:33:59 -0800634{
Jason Sams326e0dd2009-05-22 14:03:28 -0700635 ScriptCState *ss = &rsc->mScriptC;
636
Jason Sams249d4532011-01-23 17:48:45 -0800637 ScriptC *s = new ScriptC(rsc);
638 s->mEnviroment.mScriptText = ss->mScriptText;
639 s->mEnviroment.mScriptTextLength = ss->mScriptLen;
640 ss->mScriptText = NULL;
641 ss->mScriptLen = 0;
Jason Sams225afd32010-10-21 14:06:55 -0700642 s->incUserRef();
Jason Sams1f526332009-06-05 17:35:09 -0700643
Jason Sams249d4532011-01-23 17:48:45 -0800644 if (!ss->runCompiler(rsc, s, resName, cacheDir)) {
Jason Sams26b2c9f2011-01-19 16:14:21 -0800645 // Error during compile, destroy s and return null.
Jason Sams249d4532011-01-23 17:48:45 -0800646 delete s;
Jason Sams26b2c9f2011-01-19 16:14:21 -0800647 return NULL;
648 }
Jason Sams249d4532011-01-23 17:48:45 -0800649 return s;
Jason Sams326e0dd2009-05-22 14:03:28 -0700650}
651
Jason Sams326e0dd2009-05-22 14:03:28 -0700652}
653}