rsScriptC.cpp revision ce92d4baf7a5bce097228fdd4498601764cd4014
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 "../../../external/llvm/libbcc/include/bcc/bcc.h"
21#include "utils/Timers.h"
22
23#include <GLES/gl.h>
24#include <GLES/glext.h>
25
26using namespace android;
27using 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
34
35ScriptC::ScriptC(Context *rsc) : Script(rsc)
36{
37    mAllocFile = __FILE__;
38    mAllocLine = __LINE__;
39    mBccScript = NULL;
40    memset(&mProgram, 0, sizeof(mProgram));
41}
42
43ScriptC::~ScriptC()
44{
45    if (mBccScript) {
46        bccDeleteScript(mBccScript);
47    }
48    free(mEnviroment.mScriptText);
49    mEnviroment.mScriptText = NULL;
50}
51
52void ScriptC::setupScript()
53{
54    for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
55        if (!mSlots[ct].get())
56            continue;
57        void *ptr = mSlots[ct]->getPtr();
58        void **dest = ((void ***)mEnviroment.mFieldAddress)[ct];
59        //LOGE("setupScript %i %p = %p    %p %i", ct, dest, ptr, mSlots[ct]->getType(), mSlots[ct]->getType()->getDimX());
60
61        //const uint32_t *p32 = (const uint32_t *)ptr;
62        //for (uint32_t ct2=0; ct2 < mSlots[ct]->getType()->getDimX(); ct2++) {
63            //LOGE("  %i = 0x%08x ", ct2, p32[ct2]);
64        //}
65
66        if (dest) {
67            *dest = ptr;
68        } else {
69            LOGE("ScriptC::setupScript, NULL var binding address.");
70        }
71    }
72}
73
74const Allocation *ScriptC::ptrToAllocation(const void *ptr) const
75{
76    if (!ptr) {
77        return NULL;
78    }
79    for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
80        if (!mSlots[ct].get())
81            continue;
82        if (mSlots[ct]->getPtr() == ptr) {
83            return mSlots[ct].get();
84        }
85    }
86    LOGE("ScriptC::ptrToAllocation, failed to find %p", ptr);
87    return NULL;
88}
89
90
91uint32_t ScriptC::run(Context *rsc, uint32_t launchIndex)
92{
93    if (mProgram.mRoot == NULL) {
94        rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
95        return 0;
96    }
97
98    Context::ScriptTLSStruct * tls =
99    (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey);
100    rsAssert(tls);
101
102    if (mEnviroment.mFragmentStore.get()) {
103        rsc->setFragmentStore(mEnviroment.mFragmentStore.get());
104    }
105    if (mEnviroment.mFragment.get()) {
106        rsc->setFragment(mEnviroment.mFragment.get());
107    }
108    if (mEnviroment.mVertex.get()) {
109        rsc->setVertex(mEnviroment.mVertex.get());
110    }
111    if (mEnviroment.mRaster.get()) {
112        rsc->setRaster(mEnviroment.mRaster.get());
113    }
114
115    if (launchIndex == 0) {
116        mEnviroment.mStartTimeMillis
117                = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
118    }
119    setupScript();
120
121    uint32_t ret = 0;
122    tls->mScript = this;
123    //LOGE("ScriptC::run %p", mProgram.mRoot);
124    ret = mProgram.mRoot();
125    tls->mScript = NULL;
126    //LOGE("ScriptC::run ret %i", ret);
127    return ret;
128}
129
130ScriptCState::ScriptCState()
131{
132    mScript = NULL;
133    clear();
134}
135
136ScriptCState::~ScriptCState()
137{
138    delete mScript;
139    mScript = NULL;
140}
141
142void ScriptCState::clear()
143{
144    for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
145        mConstantBufferTypes[ct].clear();
146        mSlotWritable[ct] = false;
147    }
148
149    delete mScript;
150    mScript = new ScriptC(NULL);
151}
152
153static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name)
154{
155    const ScriptCState::SymbolTable_t *sym = ScriptCState::lookupSymbol(name);
156    if (sym) {
157        return sym->mPtr;
158    }
159    LOGE("ScriptC sym lookup failed for %s", name);
160    return NULL;
161}
162
163void ScriptCState::runCompiler(Context *rsc, ScriptC *s)
164{
165    LOGE("ScriptCState::runCompiler ");
166
167    s->mBccScript = bccCreateScript();
168    bccScriptBitcode(s->mBccScript, s->mEnviroment.mScriptText, s->mEnviroment.mScriptTextLength);
169    bccRegisterSymbolCallback(s->mBccScript, symbolLookup, NULL);
170    LOGE("ScriptCState::runCompiler 3");
171    bccCompileScript(s->mBccScript);
172    LOGE("ScriptCState::runCompiler 4");
173    bccGetScriptLabel(s->mBccScript, "root", (BCCvoid**) &s->mProgram.mRoot);
174    bccGetScriptLabel(s->mBccScript, "init", (BCCvoid**) &s->mProgram.mInit);
175    LOGE("root %p,  init %p", s->mProgram.mRoot, s->mProgram.mInit);
176
177    if (s->mProgram.mInit) {
178        s->mProgram.mInit();
179    }
180
181    s->mEnviroment.mInvokeFunctions = (Script::InvokeFunc_t *)calloc(100, sizeof(void *));
182    BCCchar **labels = new char*[100];
183    bccGetFunctions(s->mBccScript, (BCCsizei *)&s->mEnviroment.mInvokeFunctionCount,
184                    100, (BCCchar **)labels);
185    //LOGE("func count %i", s->mEnviroment.mInvokeFunctionCount);
186    for (uint32_t i=0; i < s->mEnviroment.mInvokeFunctionCount; i++) {
187        BCCsizei length;
188        bccGetFunctionBinary(s->mBccScript, labels[i], (BCCvoid **)&(s->mEnviroment.mInvokeFunctions[i]), &length);
189        //LOGE("func %i %p", i, s->mEnviroment.mInvokeFunctions[i]);
190    }
191
192    s->mEnviroment.mFieldAddress = (void **)calloc(100, sizeof(void *));
193    bccGetExportVars(s->mBccScript, (BCCsizei *)&s->mEnviroment.mFieldCount,
194                     100, s->mEnviroment.mFieldAddress);
195    //LOGE("var count %i", s->mEnviroment.mFieldCount);
196    for (uint32_t i=0; i < s->mEnviroment.mFieldCount; i++) {
197        //LOGE("var %i %p", i, s->mEnviroment.mFieldAddress[i]);
198    }
199
200    s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
201    s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
202    s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
203    s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
204
205    if (s->mProgram.mRoot) {
206        const static int pragmaMax = 16;
207        BCCsizei pragmaCount;
208        BCCchar * str[pragmaMax];
209        bccGetPragmas(s->mBccScript, &pragmaCount, pragmaMax, &str[0]);
210
211        for (int ct=0; ct < pragmaCount; ct+=2) {
212            if (!strcmp(str[ct], "version")) {
213                continue;
214            }
215
216            if (!strcmp(str[ct], "stateVertex")) {
217                if (!strcmp(str[ct+1], "default")) {
218                    continue;
219                }
220                if (!strcmp(str[ct+1], "parent")) {
221                    s->mEnviroment.mVertex.clear();
222                    continue;
223                }
224                LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
225            }
226
227            if (!strcmp(str[ct], "stateRaster")) {
228                if (!strcmp(str[ct+1], "default")) {
229                    continue;
230                }
231                if (!strcmp(str[ct+1], "parent")) {
232                    s->mEnviroment.mRaster.clear();
233                    continue;
234                }
235                LOGE("Unreconized value %s passed to stateRaster", str[ct+1]);
236            }
237
238            if (!strcmp(str[ct], "stateFragment")) {
239                if (!strcmp(str[ct+1], "default")) {
240                    continue;
241                }
242                if (!strcmp(str[ct+1], "parent")) {
243                    s->mEnviroment.mFragment.clear();
244                    continue;
245                }
246                LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
247            }
248
249            if (!strcmp(str[ct], "stateStore")) {
250                if (!strcmp(str[ct+1], "default")) {
251                    continue;
252                }
253                if (!strcmp(str[ct+1], "parent")) {
254                    s->mEnviroment.mFragmentStore.clear();
255                    continue;
256                }
257                LOGE("Unreconized value %s passed to stateStore", str[ct+1]);
258            }
259
260        }
261
262
263    } else {
264        // Deal with an error.
265    }
266}
267
268
269
270namespace android {
271namespace renderscript {
272
273void rsi_ScriptCBegin(Context * rsc)
274{
275    ScriptCState *ss = &rsc->mScriptC;
276    ss->clear();
277}
278
279void rsi_ScriptCSetScript(Context * rsc, void *vp)
280{
281    rsAssert(0);
282    //ScriptCState *ss = &rsc->mScriptC;
283    //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
284}
285
286void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
287{
288    ScriptCState *ss = &rsc->mScriptC;
289
290    char *t = (char *)malloc(len + 1);
291    memcpy(t, text, len);
292    t[len] = 0;
293    ss->mScript->mEnviroment.mScriptText = t;
294    ss->mScript->mEnviroment.mScriptTextLength = len;
295}
296
297
298RsScript rsi_ScriptCCreate(Context * rsc)
299{
300    ScriptCState *ss = &rsc->mScriptC;
301
302    ScriptC *s = ss->mScript;
303    ss->mScript = NULL;
304
305    ss->runCompiler(rsc, s);
306    s->incUserRef();
307    s->setContext(rsc);
308    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
309        s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
310        s->mSlotWritable[ct] = ss->mSlotWritable[ct];
311    }
312
313    ss->clear();
314    return s;
315}
316
317}
318}
319
320
321