blob: e12926b0a641829a2157a39f179fef35b23e155e [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
Alex Sakhartchouk02000b32011-02-25 09:34:33 -080029#include <bcc/bcc.h>
30
Jason Sams326e0dd2009-05-22 14:03:28 -070031using namespace android;
32using namespace android::renderscript;
33
Jason Samse5769102009-06-19 16:03:18 -070034#define GET_TLS() Context::ScriptTLSStruct * tls = \
35 (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
36 Context * rsc = tls->mContext; \
37 ScriptC * sc = (ScriptC *) tls->mScript
38
Shih-wei Liao2b2e6212011-01-14 06:21:28 -080039// Input: cacheDir
40// Input: resName
41// Input: extName
42//
43// Note: cacheFile = resName + extName
44//
45// Output: Returns cachePath == cacheDir + cacheFile
46char *genCacheFileName(const char *cacheDir,
47 const char *resName,
48 const char *extName) {
49 char cachePath[512];
50 char cacheFile[sizeof(cachePath)];
51 const size_t kBufLen = sizeof(cachePath) - 1;
52
53 cacheFile[0] = '\0';
54 // Note: resName today is usually something like
55 // "/com.android.fountain:raw/fountain"
56 if (resName[0] != '/') {
57 // Get the absolute path of the raw/***.bc file.
58
59 // Generate the absolute path. This doesn't do everything it
60 // should, e.g. if resName is "./out/whatever" it doesn't crunch
61 // the leading "./" out because this if-block is not triggered,
62 // but it'll make do.
63 //
64 if (getcwd(cacheFile, kBufLen) == NULL) {
65 LOGE("Can't get CWD while opening raw/***.bc file\n");
66 return NULL;
67 }
68 // Append "/" at the end of cacheFile so far.
69 strncat(cacheFile, "/", kBufLen);
70 }
71
72 // cacheFile = resName + extName
73 //
74 strncat(cacheFile, resName, kBufLen);
75 if (extName != NULL) {
76 // TODO(srhines): strncat() is a bit dangerous
77 strncat(cacheFile, extName, kBufLen);
78 }
79
80 // Turn the path into a flat filename by replacing
81 // any slashes after the first one with '@' characters.
82 char *cp = cacheFile + 1;
83 while (*cp != '\0') {
84 if (*cp == '/') {
85 *cp = '@';
86 }
87 cp++;
88 }
89
90 // Tack on the file name for the actual cache file path.
91 strncpy(cachePath, cacheDir, kBufLen);
92 strncat(cachePath, cacheFile, kBufLen);
93
94 LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath);
95 return strdup(cachePath);
96}
Jason Sams326e0dd2009-05-22 14:03:28 -070097
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -080098ScriptC::ScriptC(Context *rsc) : Script(rsc) {
Jason Samsbe36bf32010-05-11 14:03:58 -070099 mBccScript = NULL;
Jason Samsefb8de12009-06-08 15:20:31 -0700100 memset(&mProgram, 0, sizeof(mProgram));
Jason Sams326e0dd2009-05-22 14:03:28 -0700101}
102
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800103ScriptC::~ScriptC() {
Jason Samsbe36bf32010-05-11 14:03:58 -0700104 if (mBccScript) {
Jason Sams2e8665d2011-01-27 00:14:13 -0800105 if (mProgram.mObjectSlotList) {
106 for (size_t ct=0; ct < mProgram.mObjectSlotCount; ct++) {
107 setVarObj(mProgram.mObjectSlotList[ct], NULL);
108 }
109 delete [] mProgram.mObjectSlotList;
110 mProgram.mObjectSlotList = NULL;
111 mProgram.mObjectSlotCount = 0;
112 }
113
114
115 LOGD(">>>> ~ScriptC bccDisposeScript(%p)", mBccScript);
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800116 bccDisposeScript(mBccScript);
Jack Palevich1ef8b802009-05-28 15:53:04 -0700117 }
Jason Samse402ed32009-11-03 11:25:42 -0800118 free(mEnviroment.mScriptText);
119 mEnviroment.mScriptText = NULL;
Jason Sams326e0dd2009-05-22 14:03:28 -0700120}
121
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800122void ScriptC::setupScript(Context *rsc) {
Jason Samsc61346b2010-05-28 18:23:22 -0700123 mEnviroment.mStartTimeMillis
124 = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
125
Jason Samsbe36bf32010-05-11 14:03:58 -0700126 for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
Jason Sams900f1612010-09-16 18:18:29 -0700127 if (mSlots[ct].get() && !mTypes[ct].get()) {
128 mTypes[ct].set(mSlots[ct]->getType());
129 }
130
131 if (!mTypes[ct].get())
Jason Samsbe36bf32010-05-11 14:03:58 -0700132 continue;
Jason Sams900f1612010-09-16 18:18:29 -0700133 void *ptr = NULL;
134 if (mSlots[ct].get()) {
135 ptr = mSlots[ct]->getPtr();
136 }
Jason Samsbe36bf32010-05-11 14:03:58 -0700137 void **dest = ((void ***)mEnviroment.mFieldAddress)[ct];
Jason Samsbe36bf32010-05-11 14:03:58 -0700138
Jason Samsb9077f42010-09-22 15:57:41 -0700139 if (rsc->props.mLogScripts) {
Jason Sams2fad7e42010-11-16 12:19:26 -0800140 if (mSlots[ct].get() != NULL) {
141 LOGV("%p ScriptC::setupScript slot=%i dst=%p src=%p type=%p", rsc, ct, dest, ptr, mSlots[ct]->getType());
142 } else {
143 LOGV("%p ScriptC::setupScript slot=%i dst=%p src=%p type=null", rsc, ct, dest, ptr);
144 }
Jason Samsb9077f42010-09-22 15:57:41 -0700145 }
Jason Samsbe36bf32010-05-11 14:03:58 -0700146
147 if (dest) {
148 *dest = ptr;
Jason Samsada7f272009-09-24 14:55:38 -0700149 }
150 }
151}
152
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800153const Allocation *ScriptC::ptrToAllocation(const void *ptr) const {
Jason Samsce92d4b2010-05-17 14:55:34 -0700154 if (!ptr) {
155 return NULL;
156 }
157 for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
158 if (!mSlots[ct].get())
159 continue;
160 if (mSlots[ct]->getPtr() == ptr) {
161 return mSlots[ct].get();
162 }
163 }
164 LOGE("ScriptC::ptrToAllocation, failed to find %p", ptr);
165 return NULL;
166}
167
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800168Script * ScriptC::setTLS(Script *sc) {
Jason Sams22fa3712010-05-19 17:22:57 -0700169 Context::ScriptTLSStruct * tls = (Context::ScriptTLSStruct *)
170 pthread_getspecific(Context::gThreadTLSKey);
171 rsAssert(tls);
Jason Samsc61346b2010-05-28 18:23:22 -0700172 Script *old = tls->mScript;
173 tls->mScript = sc;
174 return old;
Jason Sams22fa3712010-05-19 17:22:57 -0700175}
176
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800177void ScriptC::setupGLState(Context *rsc) {
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700178 if (mEnviroment.mFragmentStore.get()) {
Jason Sams60709252010-11-17 15:29:32 -0800179 rsc->setProgramStore(mEnviroment.mFragmentStore.get());
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700180 }
181 if (mEnviroment.mFragment.get()) {
Jason Sams60709252010-11-17 15:29:32 -0800182 rsc->setProgramFragment(mEnviroment.mFragment.get());
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700183 }
Jason Sams8ce125b2009-06-17 16:52:59 -0700184 if (mEnviroment.mVertex.get()) {
Jason Sams60709252010-11-17 15:29:32 -0800185 rsc->setProgramVertex(mEnviroment.mVertex.get());
Jason Sams8ce125b2009-06-17 16:52:59 -0700186 }
Jason Samsb681c8a2009-09-28 18:12:56 -0700187 if (mEnviroment.mRaster.get()) {
Jason Sams60709252010-11-17 15:29:32 -0800188 rsc->setProgramRaster(mEnviroment.mRaster.get());
Jason Samsb681c8a2009-09-28 18:12:56 -0700189 }
Jason Samsc61346b2010-05-28 18:23:22 -0700190}
Jason Samsa0a1b6f2009-06-10 15:04:38 -0700191
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800192uint32_t ScriptC::run(Context *rsc) {
Jason Samsc61346b2010-05-28 18:23:22 -0700193 if (mProgram.mRoot == NULL) {
194 rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
195 return 0;
Joe Onorato9c4e4ca2009-08-09 11:39:02 -0700196 }
Jason Samsc61346b2010-05-28 18:23:22 -0700197
Jason Sams1f24db42010-12-11 17:42:30 -0800198 setupGLState(rsc);
Jason Samsc61346b2010-05-28 18:23:22 -0700199 setupScript(rsc);
Jason Sams1d54f102009-09-03 15:43:13 -0700200
Jason Sams2dca84d2009-12-09 11:05:45 -0800201 uint32_t ret = 0;
Jason Samsc61346b2010-05-28 18:23:22 -0700202 Script * oldTLS = setTLS(this);
Jason Samsb9077f42010-09-22 15:57:41 -0700203
204 if (rsc->props.mLogScripts) {
205 LOGV("%p ScriptC::run invoking root, ptr %p", rsc, mProgram.mRoot);
206 }
207
Jason Samsbe36bf32010-05-11 14:03:58 -0700208 ret = mProgram.mRoot();
Jason Samsb9077f42010-09-22 15:57:41 -0700209
210 if (rsc->props.mLogScripts) {
211 LOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret);
212 }
213
Jason Samsc61346b2010-05-28 18:23:22 -0700214 setTLS(oldTLS);
Jason Samse45ac6e2009-07-20 14:31:06 -0700215 return ret;
Jason Sams326e0dd2009-05-22 14:03:28 -0700216}
217
Jason Sams7bf29dd2010-07-19 15:38:19 -0700218typedef struct {
219 Context *rsc;
220 ScriptC *script;
221 const Allocation * ain;
222 Allocation * aout;
223 const void * usr;
224
225 uint32_t mSliceSize;
226 volatile int mSliceNum;
227
228 const uint8_t *ptrIn;
229 uint32_t eStrideIn;
230 uint8_t *ptrOut;
231 uint32_t eStrideOut;
232
233 uint32_t xStart;
234 uint32_t xEnd;
235 uint32_t yStart;
236 uint32_t yEnd;
237 uint32_t zStart;
238 uint32_t zEnd;
239 uint32_t arrayStart;
240 uint32_t arrayEnd;
241
242 uint32_t dimX;
243 uint32_t dimY;
244 uint32_t dimZ;
245 uint32_t dimArray;
246} MTLaunchStruct;
247typedef int (*rs_t)(const void *, void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t);
248
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800249static void wc_xy(void *usr, uint32_t idx) {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700250 MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
Jason Sams7bf29dd2010-07-19 15:38:19 -0700251
252 while (1) {
253 uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
254 uint32_t yStart = mtls->yStart + slice * mtls->mSliceSize;
255 uint32_t yEnd = yStart + mtls->mSliceSize;
256 yEnd = rsMin(yEnd, mtls->yEnd);
257 if (yEnd <= yStart) {
258 return;
259 }
260
261 //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
Jason Sams8d957fa2010-09-28 14:41:22 -0700262 //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut);
Jason Sams7bf29dd2010-07-19 15:38:19 -0700263 for (uint32_t y = yStart; y < yEnd; y++) {
264 uint32_t offset = mtls->dimX * y;
265 uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * offset);
266 const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * offset);
267
268 for (uint32_t x = mtls->xStart; x < mtls->xEnd; x++) {
269 ((rs_t)mtls->script->mProgram.mRoot) (xPtrIn, xPtrOut, mtls->usr, x, y, 0, 0);
270 xPtrIn += mtls->eStrideIn;
271 xPtrOut += mtls->eStrideOut;
272 }
273 }
274 }
Jason Sams7bf29dd2010-07-19 15:38:19 -0700275}
276
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800277static void wc_x(void *usr, uint32_t idx) {
Jason Sams177f8442010-10-29 10:19:21 -0700278 MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
279
280 while (1) {
281 uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
282 uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize;
283 uint32_t xEnd = xStart + mtls->mSliceSize;
284 xEnd = rsMin(xEnd, mtls->xEnd);
285 if (xEnd <= xStart) {
286 return;
287 }
288
289 //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
290 //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut);
291 uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * xStart);
292 const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * xStart);
293 for (uint32_t x = xStart; x < xEnd; x++) {
294 ((rs_t)mtls->script->mProgram.mRoot) (xPtrIn, xPtrOut, mtls->usr, x, 0, 0, 0);
295 xPtrIn += mtls->eStrideIn;
296 xPtrOut += mtls->eStrideOut;
297 }
298 }
Jason Sams177f8442010-10-29 10:19:21 -0700299}
300
Jason Samsace3e012010-07-15 17:11:13 -0700301void ScriptC::runForEach(Context *rsc,
302 const Allocation * ain,
303 Allocation * aout,
304 const void * usr,
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800305 const RsScriptCall *sc) {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700306 MTLaunchStruct mtls;
307 memset(&mtls, 0, sizeof(mtls));
Jason Sams60709252010-11-17 15:29:32 -0800308 Context::PushState ps(rsc);
Jason Samsc61346b2010-05-28 18:23:22 -0700309
Jason Sams7bf29dd2010-07-19 15:38:19 -0700310 if (ain) {
311 mtls.dimX = ain->getType()->getDimX();
312 mtls.dimY = ain->getType()->getDimY();
313 mtls.dimZ = ain->getType()->getDimZ();
314 //mtls.dimArray = ain->getType()->getDimArray();
315 } else if (aout) {
316 mtls.dimX = aout->getType()->getDimX();
317 mtls.dimY = aout->getType()->getDimY();
318 mtls.dimZ = aout->getType()->getDimZ();
319 //mtls.dimArray = aout->getType()->getDimArray();
320 } else {
321 rsc->setError(RS_ERROR_BAD_SCRIPT, "rsForEach called with null allocations");
322 return;
323 }
Jason Samsace3e012010-07-15 17:11:13 -0700324
325 if (!sc || (sc->xEnd == 0)) {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700326 mtls.xEnd = mtls.dimX;
Jason Samsace3e012010-07-15 17:11:13 -0700327 } else {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700328 rsAssert(sc->xStart < mtls.dimX);
329 rsAssert(sc->xEnd <= mtls.dimX);
Jason Samsace3e012010-07-15 17:11:13 -0700330 rsAssert(sc->xStart < sc->xEnd);
Jason Sams7bf29dd2010-07-19 15:38:19 -0700331 mtls.xStart = rsMin(mtls.dimX, sc->xStart);
332 mtls.xEnd = rsMin(mtls.dimX, sc->xEnd);
333 if (mtls.xStart >= mtls.xEnd) return;
Jason Samsace3e012010-07-15 17:11:13 -0700334 }
335
336 if (!sc || (sc->yEnd == 0)) {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700337 mtls.yEnd = mtls.dimY;
Jason Samsace3e012010-07-15 17:11:13 -0700338 } else {
Jason Sams7bf29dd2010-07-19 15:38:19 -0700339 rsAssert(sc->yStart < mtls.dimY);
340 rsAssert(sc->yEnd <= mtls.dimY);
Jason Samsace3e012010-07-15 17:11:13 -0700341 rsAssert(sc->yStart < sc->yEnd);
Jason Sams7bf29dd2010-07-19 15:38:19 -0700342 mtls.yStart = rsMin(mtls.dimY, sc->yStart);
343 mtls.yEnd = rsMin(mtls.dimY, sc->yEnd);
344 if (mtls.yStart >= mtls.yEnd) return;
Jason Samsace3e012010-07-15 17:11:13 -0700345 }
346
Jason Sams7bf29dd2010-07-19 15:38:19 -0700347 mtls.xEnd = rsMax((uint32_t)1, mtls.xEnd);
348 mtls.yEnd = rsMax((uint32_t)1, mtls.yEnd);
349 mtls.zEnd = rsMax((uint32_t)1, mtls.zEnd);
350 mtls.arrayEnd = rsMax((uint32_t)1, mtls.arrayEnd);
Jason Samsace3e012010-07-15 17:11:13 -0700351
352 rsAssert(ain->getType()->getDimZ() == 0);
Jason Samsc61346b2010-05-28 18:23:22 -0700353
Jason Sams1f24db42010-12-11 17:42:30 -0800354 setupGLState(rsc);
Jason Samsc61346b2010-05-28 18:23:22 -0700355 setupScript(rsc);
356 Script * oldTLS = setTLS(this);
357
Jason Sams7bf29dd2010-07-19 15:38:19 -0700358 mtls.rsc = rsc;
359 mtls.ain = ain;
360 mtls.aout = aout;
361 mtls.script = this;
362 mtls.usr = usr;
363 mtls.mSliceSize = 10;
364 mtls.mSliceNum = 0;
Jason Samsc61346b2010-05-28 18:23:22 -0700365
Jason Sams7bf29dd2010-07-19 15:38:19 -0700366 mtls.ptrIn = NULL;
367 mtls.eStrideIn = 0;
368 if (ain) {
369 mtls.ptrIn = (const uint8_t *)ain->getPtr();
370 mtls.eStrideIn = ain->getType()->getElementSizeBytes();
Jason Samsc61346b2010-05-28 18:23:22 -0700371 }
372
Jason Sams7bf29dd2010-07-19 15:38:19 -0700373 mtls.ptrOut = NULL;
374 mtls.eStrideOut = 0;
375 if (aout) {
376 mtls.ptrOut = (uint8_t *)aout->getPtr();
377 mtls.eStrideOut = aout->getType()->getElementSizeBytes();
378 }
379
Jason Sams177f8442010-10-29 10:19:21 -0700380 if ((rsc->getWorkerPoolSize() > 1) && mEnviroment.mIsThreadable) {
381 if (mtls.dimY > 1) {
382 rsc->launchThreads(wc_xy, &mtls);
383 } else {
384 rsc->launchThreads(wc_x, &mtls);
385 }
Jason Sams18133402010-07-20 15:09:00 -0700386
387 //LOGE("launch 1");
Jason Sams18133402010-07-20 15:09:00 -0700388 } else {
Jason Sams8d957fa2010-09-28 14:41:22 -0700389 //LOGE("launch 3");
Jason Sams18133402010-07-20 15:09:00 -0700390 for (uint32_t ar = mtls.arrayStart; ar < mtls.arrayEnd; ar++) {
391 for (uint32_t z = mtls.zStart; z < mtls.zEnd; z++) {
392 for (uint32_t y = mtls.yStart; y < mtls.yEnd; y++) {
393 uint32_t offset = mtls.dimX * mtls.dimY * mtls.dimZ * ar +
394 mtls.dimX * mtls.dimY * z +
395 mtls.dimX * y;
396 uint8_t *xPtrOut = mtls.ptrOut + (mtls.eStrideOut * offset);
397 const uint8_t *xPtrIn = mtls.ptrIn + (mtls.eStrideIn * offset);
Jason Sams7bf29dd2010-07-19 15:38:19 -0700398
Jason Sams18133402010-07-20 15:09:00 -0700399 for (uint32_t x = mtls.xStart; x < mtls.xEnd; x++) {
400 ((rs_t)mProgram.mRoot) (xPtrIn, xPtrOut, usr, x, y, z, ar);
401 xPtrIn += mtls.eStrideIn;
402 xPtrOut += mtls.eStrideOut;
403 }
Jason Samsace3e012010-07-15 17:11:13 -0700404 }
405 }
406 }
Jason Samsc61346b2010-05-28 18:23:22 -0700407 }
Jason Sams18133402010-07-20 15:09:00 -0700408
Jason Samsc61346b2010-05-28 18:23:22 -0700409 setTLS(oldTLS);
410}
411
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800412void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len) {
Jason Sams22fa3712010-05-19 17:22:57 -0700413 if ((slot >= mEnviroment.mInvokeFunctionCount) ||
414 (mEnviroment.mInvokeFunctions[slot] == NULL)) {
415 rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script");
416 return;
417 }
Jason Samsc61346b2010-05-28 18:23:22 -0700418 setupScript(rsc);
419 Script * oldTLS = setTLS(this);
Jason Sams22fa3712010-05-19 17:22:57 -0700420
Jason Samsb9077f42010-09-22 15:57:41 -0700421 if (rsc->props.mLogScripts) {
422 LOGV("%p ScriptC::Invoke invoking slot %i, ptr %p", rsc, slot, mEnviroment.mInvokeFunctions[slot]);
423 }
Jason Sams2a63bf62010-06-08 15:40:48 -0700424 ((void (*)(const void *, uint32_t))
425 mEnviroment.mInvokeFunctions[slot])(data, len);
Jason Samsb9077f42010-09-22 15:57:41 -0700426 if (rsc->props.mLogScripts) {
427 LOGV("%p ScriptC::Invoke complete", rsc);
428 }
Jason Sams2a63bf62010-06-08 15:40:48 -0700429
Jason Samsc61346b2010-05-28 18:23:22 -0700430 setTLS(oldTLS);
Jason Sams22fa3712010-05-19 17:22:57 -0700431}
432
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800433ScriptCState::ScriptCState() {
Jason Sams326e0dd2009-05-22 14:03:28 -0700434}
435
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800436ScriptCState::~ScriptCState() {
Jason Sams1f526332009-06-05 17:35:09 -0700437}
438
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800439static void* symbolLookup(void* pContext, char const* name) {
Jason Samsaeb094b2010-05-18 13:35:45 -0700440 const ScriptCState::SymbolTable_t *sym;
Jason Samsdd663fa2010-08-11 13:26:28 -0700441 ScriptC *s = (ScriptC *)pContext;
Shih-wei Liaof17b13b2010-12-07 13:44:10 -0800442 if (!strcmp(name, "__isThreadable")) {
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800443 return (void*) s->mEnviroment.mIsThreadable;
Shih-wei Liaof17b13b2010-12-07 13:44:10 -0800444 } else if (!strcmp(name, "__clearThreadable")) {
445 s->mEnviroment.mIsThreadable = false;
446 return NULL;
447 }
Jason Samsaeb094b2010-05-18 13:35:45 -0700448 sym = ScriptCState::lookupSymbol(name);
Jason Sams6bfc1b92010-11-01 14:26:30 -0700449 if (!sym) {
450 sym = ScriptCState::lookupSymbolCL(name);
Jason Samsaeb094b2010-05-18 13:35:45 -0700451 }
Jason Sams6bfc1b92010-11-01 14:26:30 -0700452 if (!sym) {
453 sym = ScriptCState::lookupSymbolGL(name);
Jason Samsaeb094b2010-05-18 13:35:45 -0700454 }
Jason Sams29df66f2009-07-16 15:08:06 -0700455 if (sym) {
Jason Sams6bfc1b92010-11-01 14:26:30 -0700456 s->mEnviroment.mIsThreadable &= sym->threadable;
Jason Sams29df66f2009-07-16 15:08:06 -0700457 return sym->mPtr;
458 }
Jason Sams29df66f2009-07-16 15:08:06 -0700459 LOGE("ScriptC sym lookup failed for %s", name);
Jason Sams29df66f2009-07-16 15:08:06 -0700460 return NULL;
461}
Jason Samsa4a54e42009-06-10 18:39:40 -0700462
Shih-wei Liao80761ec2011-01-16 02:23:04 -0800463#if 0
Shih-wei Liao1f9ba732010-10-23 02:15:57 -0700464extern const char rs_runtime_lib_bc[];
465extern unsigned rs_runtime_lib_bc_size;
Shih-wei Liao80761ec2011-01-16 02:23:04 -0800466#endif
Shih-wei Liao1f9ba732010-10-23 02:15:57 -0700467
Jason Sams26b2c9f2011-01-19 16:14:21 -0800468bool ScriptCState::runCompiler(Context *rsc,
Shih-wei Liaoce8a0792010-12-20 20:45:56 +0800469 ScriptC *s,
Shih-wei Liaoce8a0792010-12-20 20:45:56 +0800470 const char *resName,
471 const char *cacheDir) {
Stephen Hines7b337b12011-01-17 17:31:58 -0800472 s->mBccScript = bccCreateScript();
Shih-wei Liao37150de2011-01-07 18:17:07 -0800473
Stephen Hines7b337b12011-01-17 17:31:58 -0800474 s->mEnviroment.mIsThreadable = true;
Shih-wei Liao37150de2011-01-07 18:17:07 -0800475
Shih-wei Liaofa6113e2011-01-20 12:35:44 -0800476 if (bccRegisterSymbolCallback(s->mBccScript, symbolLookup, s) != 0) {
477 LOGE("bcc: FAILS to register symbol callback");
478 return false;
479 }
Shih-wei Liao37150de2011-01-07 18:17:07 -0800480
Stephen Hines7b337b12011-01-17 17:31:58 -0800481 if (bccReadBC(s->mBccScript,
482 resName,
483 s->mEnviroment.mScriptText,
484 s->mEnviroment.mScriptTextLength, 0) != 0) {
485 LOGE("bcc: FAILS to read bitcode");
Jason Sams26b2c9f2011-01-19 16:14:21 -0800486 return false;
Stephen Hines7b337b12011-01-17 17:31:58 -0800487 }
Shih-wei Liao37150de2011-01-07 18:17:07 -0800488
Shih-wei Liao54391842011-01-19 02:18:45 -0800489#if 1
Shih-wei Liaoafca6df2011-02-01 04:06:55 -0800490 if (bccLinkFile(s->mBccScript, "/system/lib/libclcore.bc", 0) != 0) {
Stephen Hines7b337b12011-01-17 17:31:58 -0800491 LOGE("bcc: FAILS to link bitcode");
Jason Sams26b2c9f2011-01-19 16:14:21 -0800492 return false;
Alex Sakhartchoukb26fb042010-09-24 15:18:12 -0700493 }
Stephen Hines7b337b12011-01-17 17:31:58 -0800494#endif
495 char *cachePath = genCacheFileName(cacheDir, resName, ".oBCC");
496
497 if (bccPrepareExecutable(s->mBccScript, cachePath, 0) != 0) {
498 LOGE("bcc: FAILS to prepare executable");
Jason Sams26b2c9f2011-01-19 16:14:21 -0800499 return false;
Stephen Hines7b337b12011-01-17 17:31:58 -0800500 }
501
502 free(cachePath);
503
504 s->mProgram.mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(s->mBccScript, "root"));
505 s->mProgram.mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(s->mBccScript, "init"));
Jason Samsf1685042009-07-16 17:47:40 -0700506
Jason Sams8c6bc692009-09-16 15:04:38 -0700507 if (s->mProgram.mInit) {
508 s->mProgram.mInit();
Jason Sams1d54f102009-09-03 15:43:13 -0700509 }
510
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800511 s->mEnviroment.mInvokeFunctionCount = bccGetExportFuncCount(s->mBccScript);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800512 if (s->mEnviroment.mInvokeFunctionCount <= 0)
Jason Sams8c880902010-06-15 12:15:57 -0700513 s->mEnviroment.mInvokeFunctions = NULL;
514 else {
515 s->mEnviroment.mInvokeFunctions = (Script::InvokeFunc_t*) calloc(s->mEnviroment.mInvokeFunctionCount, sizeof(Script::InvokeFunc_t));
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800516 bccGetExportFuncList(s->mBccScript, s->mEnviroment.mInvokeFunctionCount, (void **) s->mEnviroment.mInvokeFunctions);
Jason Sams1d54f102009-09-03 15:43:13 -0700517 }
518
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800519 s->mEnviroment.mFieldCount = bccGetExportVarCount(s->mBccScript);
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800520 if (s->mEnviroment.mFieldCount <= 0)
Shih-wei Liaoa226b162010-07-20 16:43:25 -0700521 s->mEnviroment.mFieldAddress = NULL;
522 else {
523 s->mEnviroment.mFieldAddress = (void **) calloc(s->mEnviroment.mFieldCount, sizeof(void *));
Shih-wei Liao2b2e6212011-01-14 06:21:28 -0800524 bccGetExportVarList(s->mBccScript, s->mEnviroment.mFieldCount, (void **) s->mEnviroment.mFieldAddress);
Alex Sakhartchouk700ba382010-10-08 15:00:05 -0700525 s->initSlots();
Shih-wei Liaoa226b162010-07-20 16:43:25 -0700526 }
Jason Samsa4a54e42009-06-10 18:39:40 -0700527
Jason Sams8c6bc692009-09-16 15:04:38 -0700528 s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
529 s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
Jason Samsccc010b2010-05-13 18:30:11 -0700530 s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
Jason Samsb681c8a2009-09-28 18:12:56 -0700531 s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
Jason Sams8c6bc692009-09-16 15:04:38 -0700532
Stephen Hines7b337b12011-01-17 17:31:58 -0800533 const static int pragmaMax = 16;
534 size_t pragmaCount = bccGetPragmaCount(s->mBccScript);
535 char const *keys[pragmaMax];
536 char const *values[pragmaMax];
537 bccGetPragmaList(s->mBccScript, pragmaMax, keys, values);
Jason Sams10308932009-06-09 12:15:30 -0700538
Stephen Hines7b337b12011-01-17 17:31:58 -0800539 for (size_t i=0; i < pragmaCount; ++i) {
540 //LOGE("pragma %s %s", keys[i], values[i]);
541 if (!strcmp(keys[i], "version")) {
Stephen Hinesb5dc6af2011-01-18 14:10:44 -0800542 if (!strcmp(values[i], "1")) {
543 continue;
544 }
545 LOGE("Invalid version pragma value: %s\n", values[i]);
Jason Sams26b2c9f2011-01-19 16:14:21 -0800546 return false;
Stephen Hines7b337b12011-01-17 17:31:58 -0800547 }
548
549 if (!strcmp(keys[i], "stateVertex")) {
550 if (!strcmp(values[i], "default")) {
Jason Sams10308932009-06-09 12:15:30 -0700551 continue;
Jason Sams10308932009-06-09 12:15:30 -0700552 }
Stephen Hines7b337b12011-01-17 17:31:58 -0800553 if (!strcmp(values[i], "parent")) {
554 s->mEnviroment.mVertex.clear();
555 continue;
Jason Sams10308932009-06-09 12:15:30 -0700556 }
Stephen Hinesb5dc6af2011-01-18 14:10:44 -0800557 LOGE("Unrecognized value %s passed to stateVertex", values[i]);
Jason Sams26b2c9f2011-01-19 16:14:21 -0800558 return false;
Jason Sams10308932009-06-09 12:15:30 -0700559 }
Stephen Hines7b337b12011-01-17 17:31:58 -0800560
561 if (!strcmp(keys[i], "stateRaster")) {
562 if (!strcmp(values[i], "default")) {
563 continue;
564 }
565 if (!strcmp(values[i], "parent")) {
566 s->mEnviroment.mRaster.clear();
567 continue;
568 }
Stephen Hinesb5dc6af2011-01-18 14:10:44 -0800569 LOGE("Unrecognized value %s passed to stateRaster", values[i]);
Jason Sams26b2c9f2011-01-19 16:14:21 -0800570 return false;
Stephen Hines7b337b12011-01-17 17:31:58 -0800571 }
572
573 if (!strcmp(keys[i], "stateFragment")) {
574 if (!strcmp(values[i], "default")) {
575 continue;
576 }
577 if (!strcmp(values[i], "parent")) {
578 s->mEnviroment.mFragment.clear();
579 continue;
580 }
Stephen Hinesb5dc6af2011-01-18 14:10:44 -0800581 LOGE("Unrecognized value %s passed to stateFragment", values[i]);
Jason Sams26b2c9f2011-01-19 16:14:21 -0800582 return false;
Stephen Hines7b337b12011-01-17 17:31:58 -0800583 }
584
585 if (!strcmp(keys[i], "stateStore")) {
586 if (!strcmp(values[i], "default")) {
587 continue;
588 }
589 if (!strcmp(values[i], "parent")) {
590 s->mEnviroment.mFragmentStore.clear();
591 continue;
592 }
Stephen Hinesb5dc6af2011-01-18 14:10:44 -0800593 LOGE("Unrecognized value %s passed to stateStore", values[i]);
Jason Sams26b2c9f2011-01-19 16:14:21 -0800594 return false;
Stephen Hines7b337b12011-01-17 17:31:58 -0800595 }
Jason Sams10308932009-06-09 12:15:30 -0700596 }
Jason Sams2e8665d2011-01-27 00:14:13 -0800597
598 size_t objectSlotCount = bccGetObjectSlotCount(s->mBccScript);
599 uint32_t *objectSlots = NULL;
600 if (objectSlotCount) {
601 objectSlots = new uint32_t[objectSlotCount];
602 bccGetObjectSlotList(s->mBccScript, objectSlotCount, objectSlots);
603 s->mProgram.mObjectSlotList = objectSlots;
604 s->mProgram.mObjectSlotCount = objectSlotCount;
605 }
606
Jason Sams26b2c9f2011-01-19 16:14:21 -0800607 return true;
Jason Sams326e0dd2009-05-22 14:03:28 -0700608}
609
610namespace android {
611namespace renderscript {
612
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800613void rsi_ScriptCBegin(Context * rsc) {
Jason Sams326e0dd2009-05-22 14:03:28 -0700614}
615
Alex Sakhartchoukafb743a2010-11-09 17:00:54 -0800616void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len) {
Jason Sams1f526332009-06-05 17:35:09 -0700617 ScriptCState *ss = &rsc->mScriptC;
Jason Samse402ed32009-11-03 11:25:42 -0800618
619 char *t = (char *)malloc(len + 1);
620 memcpy(t, text, len);
621 t[len] = 0;
Jason Sams249d4532011-01-23 17:48:45 -0800622 ss->mScriptText = t;
623 ss->mScriptLen = len;
Jason Sams1f526332009-06-05 17:35:09 -0700624}
625
Shih-wei Liaoce8a0792010-12-20 20:45:56 +0800626
627RsScript rsi_ScriptCCreate(Context *rsc,
Shih-wei Liao37150de2011-01-07 18:17:07 -0800628 const char *packageName /* deprecated */,
Shih-wei Liaoce8a0792010-12-20 20:45:56 +0800629 const char *resName,
630 const char *cacheDir)
Shih-wei Liao9503b662010-11-08 01:33:59 -0800631{
Jason Sams326e0dd2009-05-22 14:03:28 -0700632 ScriptCState *ss = &rsc->mScriptC;
633
Jason Sams249d4532011-01-23 17:48:45 -0800634 ScriptC *s = new ScriptC(rsc);
635 s->mEnviroment.mScriptText = ss->mScriptText;
636 s->mEnviroment.mScriptTextLength = ss->mScriptLen;
637 ss->mScriptText = NULL;
638 ss->mScriptLen = 0;
Jason Sams225afd32010-10-21 14:06:55 -0700639 s->incUserRef();
Jason Sams1f526332009-06-05 17:35:09 -0700640
Jason Sams249d4532011-01-23 17:48:45 -0800641 if (!ss->runCompiler(rsc, s, resName, cacheDir)) {
Jason Sams26b2c9f2011-01-19 16:14:21 -0800642 // Error during compile, destroy s and return null.
Jason Sams249d4532011-01-23 17:48:45 -0800643 delete s;
Jason Sams26b2c9f2011-01-19 16:14:21 -0800644 return NULL;
645 }
Jason Sams249d4532011-01-23 17:48:45 -0800646 return s;
Jason Sams326e0dd2009-05-22 14:03:28 -0700647}
648
Jason Sams326e0dd2009-05-22 14:03:28 -0700649}
650}