1 /*
2 * Copyright (C) 2009-2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
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 using namespace android;
23 using namespace android::renderscript;
24
25 #define GET_TLS() Context::ScriptTLSStruct * tls = \
26 (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
27 Context * rsc = tls->mContext; \
28 ScriptC * sc = (ScriptC *) tls->mScript
29
ScriptC(Context * rsc)30 ScriptC::ScriptC(Context *rsc) : Script(rsc) {
31 }
32
~ScriptC()33 ScriptC::~ScriptC() {
34 if (mInitialized) {
35 mRSC->mHal.funcs.script.invokeFreeChildren(mRSC, this);
36 mRSC->mHal.funcs.script.destroy(mRSC, this);
37 }
38 }
39
setupScript(Context * rsc)40 void ScriptC::setupScript(Context *rsc) {
41 mEnviroment.mStartTimeMillis
42 = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
43
44 for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) {
45 if (mSlots[ct].get() && !mTypes[ct].get()) {
46 mTypes[ct].set(mSlots[ct]->getType());
47 }
48
49 if (!mTypes[ct].get())
50 continue;
51 rsc->mHal.funcs.script.setGlobalBind(rsc, this, ct, mSlots[ct].get());
52 }
53 }
54
setupGLState(Context * rsc)55 void ScriptC::setupGLState(Context *rsc) {
56 }
57
run(Context * rsc)58 uint32_t ScriptC::run(Context *rsc) {
59 if (mHal.info.root == NULL) {
60 rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
61 return 0;
62 }
63
64 setupGLState(rsc);
65 setupScript(rsc);
66
67 uint32_t ret = 0;
68
69 if (rsc->props.mLogScripts) {
70 ALOGV("%p ScriptC::run invoking root, ptr %p", rsc, mHal.info.root);
71 }
72
73 ret = rsc->mHal.funcs.script.invokeRoot(rsc, this);
74
75 if (rsc->props.mLogScripts) {
76 ALOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret);
77 }
78
79 return ret;
80 }
81
82
runForEach(Context * rsc,uint32_t slot,const Allocation * ain,Allocation * aout,const void * usr,size_t usrBytes,const RsScriptCall * sc)83 void ScriptC::runForEach(Context *rsc,
84 uint32_t slot,
85 const Allocation * ain,
86 Allocation * aout,
87 const void * usr,
88 size_t usrBytes,
89 const RsScriptCall *sc) {
90
91 Context::PushState ps(rsc);
92
93 setupGLState(rsc);
94 setupScript(rsc);
95 rsc->mHal.funcs.script.invokeForEach(rsc, this, slot, ain, aout, usr, usrBytes, sc);
96 }
97
Invoke(Context * rsc,uint32_t slot,const void * data,size_t len)98 void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, size_t len) {
99 if (slot >= mHal.info.exportedFunctionCount) {
100 rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script");
101 return;
102 }
103 setupScript(rsc);
104
105 if (rsc->props.mLogScripts) {
106 ALOGV("%p ScriptC::Invoke invoking slot %i, ptr %p", rsc, slot, this);
107 }
108 rsc->mHal.funcs.script.invokeFunction(rsc, this, slot, data, len);
109 }
110
ScriptCState()111 ScriptCState::ScriptCState() {
112 }
113
~ScriptCState()114 ScriptCState::~ScriptCState() {
115 }
116
117 /*
118 static void* symbolLookup(void* pContext, char const* name) {
119 const ScriptCState::SymbolTable_t *sym;
120 ScriptC *s = (ScriptC *)pContext;
121 if (!strcmp(name, "__isThreadable")) {
122 return (void*) s->mHal.info.isThreadable;
123 } else if (!strcmp(name, "__clearThreadable")) {
124 s->mHal.info.isThreadable = false;
125 return NULL;
126 }
127 sym = ScriptCState::lookupSymbol(name);
128 if (!sym) {
129 sym = ScriptCState::lookupSymbolCL(name);
130 }
131 if (!sym) {
132 sym = ScriptCState::lookupSymbolGL(name);
133 }
134 if (sym) {
135 s->mHal.info.isThreadable &= sym->threadable;
136 return sym->mPtr;
137 }
138 ALOGE("ScriptC sym lookup failed for %s", name);
139 return NULL;
140 }
141 */
142
143 #if 0
144 extern const char rs_runtime_lib_bc[];
145 extern unsigned rs_runtime_lib_bc_size;
146 #endif
147
runCompiler(Context * rsc,const char * resName,const char * cacheDir,const uint8_t * bitcode,size_t bitcodeLen)148 bool ScriptC::runCompiler(Context *rsc,
149 const char *resName,
150 const char *cacheDir,
151 const uint8_t *bitcode,
152 size_t bitcodeLen) {
153
154 //ALOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen);
155
156 if (!rsc->mHal.funcs.script.init(rsc, this, resName, cacheDir, bitcode, bitcodeLen, 0)) {
157 return false;
158 }
159
160 mInitialized = true;
161
162 rsc->mHal.funcs.script.invokeInit(rsc, this);
163
164 for (size_t i=0; i < mHal.info.exportedPragmaCount; ++i) {
165 const char * key = mHal.info.exportedPragmaKeyList[i];
166 const char * value = mHal.info.exportedPragmaValueList[i];
167 //ALOGE("pragma %s %s", keys[i], values[i]);
168 if (!strcmp(key, "version")) {
169 if (!strcmp(value, "1")) {
170 continue;
171 }
172 ALOGE("Invalid version pragma value: %s\n", value);
173 return false;
174 }
175 }
176
177 mSlots = new ObjectBaseRef<Allocation>[mHal.info.exportedVariableCount];
178 mTypes = new ObjectBaseRef<const Type>[mHal.info.exportedVariableCount];
179
180 return true;
181 }
182
183 namespace android {
184 namespace renderscript {
185
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)186 RsScript rsi_ScriptCCreate(Context *rsc,
187 const char *resName, size_t resName_length,
188 const char *cacheDir, size_t cacheDir_length,
189 const char *text, size_t text_length)
190 {
191 ScriptC *s = new ScriptC(rsc);
192
193 if (!s->runCompiler(rsc, resName, cacheDir, (uint8_t *)text, text_length)) {
194 // Error during compile, destroy s and return null.
195 ObjectBase::checkDelete(s);
196 return NULL;
197 }
198
199 s->incUserRef();
200 return s;
201 }
202
203 }
204 }
205