• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "utils/Timers.h"
20 #include "utils/StopWatch.h"
21 
22 #ifndef ANDROID_RS_SERIALIZE
23 #include <bcinfo/BitcodeTranslator.h>
24 #endif
25 
26 using namespace android;
27 using namespace android::renderscript;
28 
29 #define GET_TLS()  Context::ScriptTLSStruct * tls = \
30     (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
31     Context * rsc = tls->mContext; \
32     ScriptC * sc = (ScriptC *) tls->mScript
33 
ScriptC(Context * rsc)34 ScriptC::ScriptC(Context *rsc) : Script(rsc) {
35 #ifndef ANDROID_RS_SERIALIZE
36     BT = NULL;
37 #endif
38 }
39 
~ScriptC()40 ScriptC::~ScriptC() {
41 #ifndef ANDROID_RS_SERIALIZE
42     if (BT) {
43         delete BT;
44         BT = NULL;
45     }
46 #endif
47     mRSC->mHal.funcs.script.invokeFreeChildren(mRSC, this);
48     mRSC->mHal.funcs.script.destroy(mRSC, this);
49 }
50 
setupScript(Context * rsc)51 void ScriptC::setupScript(Context *rsc) {
52     mEnviroment.mStartTimeMillis
53                 = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
54 
55     for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) {
56         if (mSlots[ct].get() && !mTypes[ct].get()) {
57             mTypes[ct].set(mSlots[ct]->getType());
58         }
59 
60         if (!mTypes[ct].get())
61             continue;
62         void *ptr = NULL;
63         if (mSlots[ct].get()) {
64             ptr = mSlots[ct]->getPtr();
65         }
66 
67         rsc->mHal.funcs.script.setGlobalBind(rsc, this, ct, ptr);
68     }
69 }
70 
ptrToAllocation(const void * ptr) const71 const Allocation *ScriptC::ptrToAllocation(const void *ptr) const {
72     //LOGE("ptr to alloc %p", ptr);
73     if (!ptr) {
74         return NULL;
75     }
76     for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) {
77         if (!mSlots[ct].get())
78             continue;
79         if (mSlots[ct]->getPtr() == ptr) {
80             return mSlots[ct].get();
81         }
82     }
83     LOGE("ScriptC::ptrToAllocation, failed to find %p", ptr);
84     return NULL;
85 }
86 
setupGLState(Context * rsc)87 void ScriptC::setupGLState(Context *rsc) {
88     if (mEnviroment.mFragmentStore.get()) {
89         rsc->setProgramStore(mEnviroment.mFragmentStore.get());
90     }
91     if (mEnviroment.mFragment.get()) {
92         rsc->setProgramFragment(mEnviroment.mFragment.get());
93     }
94     if (mEnviroment.mVertex.get()) {
95         rsc->setProgramVertex(mEnviroment.mVertex.get());
96     }
97     if (mEnviroment.mRaster.get()) {
98         rsc->setProgramRaster(mEnviroment.mRaster.get());
99     }
100 }
101 
run(Context * rsc)102 uint32_t ScriptC::run(Context *rsc) {
103     if (mHal.info.root == NULL) {
104         rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
105         return 0;
106     }
107 
108     setupGLState(rsc);
109     setupScript(rsc);
110 
111     uint32_t ret = 0;
112 
113     if (rsc->props.mLogScripts) {
114         LOGV("%p ScriptC::run invoking root,  ptr %p", rsc, mHal.info.root);
115     }
116 
117     ret = rsc->mHal.funcs.script.invokeRoot(rsc, this);
118 
119     if (rsc->props.mLogScripts) {
120         LOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret);
121     }
122 
123     return ret;
124 }
125 
126 
runForEach(Context * rsc,const Allocation * ain,Allocation * aout,const void * usr,size_t usrBytes,const RsScriptCall * sc)127 void ScriptC::runForEach(Context *rsc,
128                          const Allocation * ain,
129                          Allocation * aout,
130                          const void * usr,
131                          size_t usrBytes,
132                          const RsScriptCall *sc) {
133 
134     Context::PushState ps(rsc);
135 
136     setupGLState(rsc);
137     setupScript(rsc);
138     rsc->mHal.funcs.script.invokeForEach(rsc, this, 0, ain, aout, usr, usrBytes, sc);
139 }
140 
Invoke(Context * rsc,uint32_t slot,const void * data,size_t len)141 void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, size_t len) {
142     if (slot >= mHal.info.exportedFunctionCount) {
143         rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script");
144         return;
145     }
146     setupScript(rsc);
147 
148     if (rsc->props.mLogScripts) {
149         LOGV("%p ScriptC::Invoke invoking slot %i,  ptr %p", rsc, slot, this);
150     }
151     rsc->mHal.funcs.script.invokeFunction(rsc, this, slot, data, len);
152 }
153 
ScriptCState()154 ScriptCState::ScriptCState() {
155 }
156 
~ScriptCState()157 ScriptCState::~ScriptCState() {
158 }
159 
160 /*
161 static void* symbolLookup(void* pContext, char const* name) {
162     const ScriptCState::SymbolTable_t *sym;
163     ScriptC *s = (ScriptC *)pContext;
164     if (!strcmp(name, "__isThreadable")) {
165       return (void*) s->mHal.info.isThreadable;
166     } else if (!strcmp(name, "__clearThreadable")) {
167       s->mHal.info.isThreadable = false;
168       return NULL;
169     }
170     sym = ScriptCState::lookupSymbol(name);
171     if (!sym) {
172         sym = ScriptCState::lookupSymbolCL(name);
173     }
174     if (!sym) {
175         sym = ScriptCState::lookupSymbolGL(name);
176     }
177     if (sym) {
178         s->mHal.info.isThreadable &= sym->threadable;
179         return sym->mPtr;
180     }
181     LOGE("ScriptC sym lookup failed for %s", name);
182     return NULL;
183 }
184 */
185 
186 #if 0
187 extern const char rs_runtime_lib_bc[];
188 extern unsigned rs_runtime_lib_bc_size;
189 #endif
190 
runCompiler(Context * rsc,const char * resName,const char * cacheDir,const uint8_t * bitcode,size_t bitcodeLen)191 bool ScriptC::runCompiler(Context *rsc,
192                           const char *resName,
193                           const char *cacheDir,
194                           const uint8_t *bitcode,
195                           size_t bitcodeLen) {
196 
197     //LOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen);
198 #ifndef ANDROID_RS_SERIALIZE
199     uint32_t sdkVersion = rsc->getTargetSdkVersion();
200     if (BT) {
201         delete BT;
202     }
203     BT = new bcinfo::BitcodeTranslator((const char *)bitcode, bitcodeLen,
204                                        sdkVersion);
205     if (!BT->translate()) {
206         LOGE("Failed to translate bitcode from version: %u", sdkVersion);
207         delete BT;
208         BT = NULL;
209         return false;
210     }
211     bitcode = (const uint8_t *) BT->getTranslatedBitcode();
212     bitcodeLen = BT->getTranslatedBitcodeSize();
213 #endif
214 
215     rsc->mHal.funcs.script.init(rsc, this, resName, cacheDir, bitcode, bitcodeLen, 0);
216 
217     mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
218     mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
219     mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
220     mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
221 
222     rsc->mHal.funcs.script.invokeInit(rsc, this);
223 
224     for (size_t i=0; i < mHal.info.exportedPragmaCount; ++i) {
225         const char * key = mHal.info.exportedPragmaKeyList[i];
226         const char * value = mHal.info.exportedPragmaValueList[i];
227         //LOGE("pragma %s %s", keys[i], values[i]);
228         if (!strcmp(key, "version")) {
229             if (!strcmp(value, "1")) {
230                 continue;
231             }
232             LOGE("Invalid version pragma value: %s\n", value);
233             return false;
234         }
235 
236         if (!strcmp(key, "stateVertex")) {
237             if (!strcmp(value, "default")) {
238                 continue;
239             }
240             if (!strcmp(value, "parent")) {
241                 mEnviroment.mVertex.clear();
242                 continue;
243             }
244             LOGE("Unrecognized value %s passed to stateVertex", value);
245             return false;
246         }
247 
248         if (!strcmp(key, "stateRaster")) {
249             if (!strcmp(value, "default")) {
250                 continue;
251             }
252             if (!strcmp(value, "parent")) {
253                 mEnviroment.mRaster.clear();
254                 continue;
255             }
256             LOGE("Unrecognized value %s passed to stateRaster", value);
257             return false;
258         }
259 
260         if (!strcmp(key, "stateFragment")) {
261             if (!strcmp(value, "default")) {
262                 continue;
263             }
264             if (!strcmp(value, "parent")) {
265                 mEnviroment.mFragment.clear();
266                 continue;
267             }
268             LOGE("Unrecognized value %s passed to stateFragment", value);
269             return false;
270         }
271 
272         if (!strcmp(key, "stateStore")) {
273             if (!strcmp(value, "default")) {
274                 continue;
275             }
276             if (!strcmp(value, "parent")) {
277                 mEnviroment.mFragmentStore.clear();
278                 continue;
279             }
280             LOGE("Unrecognized value %s passed to stateStore", value);
281             return false;
282         }
283     }
284 
285     mSlots = new ObjectBaseRef<Allocation>[mHal.info.exportedVariableCount];
286     mTypes = new ObjectBaseRef<const Type>[mHal.info.exportedVariableCount];
287 
288     return true;
289 }
290 
291 namespace android {
292 namespace renderscript {
293 
rsi_ScriptCCreate(Context * rsc,const char * resName,size_t resName_length,const char * cacheDir,size_t cacheDir_length,const char * text,size_t text_length)294 RsScript rsi_ScriptCCreate(Context *rsc,
295                            const char *resName, size_t resName_length,
296                            const char *cacheDir, size_t cacheDir_length,
297                            const char *text, size_t text_length)
298 {
299     ScriptC *s = new ScriptC(rsc);
300 
301     if (!s->runCompiler(rsc, resName, cacheDir, (uint8_t *)text, text_length)) {
302         // Error during compile, destroy s and return null.
303         delete s;
304         return NULL;
305     }
306 
307     s->incUserRef();
308     return s;
309 }
310 
311 }
312 }
313