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