rsScriptC.cpp revision 2a63bf6c293d89c8e3725cfb7ee2add3dd3f0246
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(Context *rsc)
53{
54    setupGLState(rsc);
55    mEnviroment.mStartTimeMillis
56                = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
57
58    for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
59        if (!mSlots[ct].get())
60            continue;
61        void *ptr = mSlots[ct]->getPtr();
62        void **dest = ((void ***)mEnviroment.mFieldAddress)[ct];
63        //LOGE("setupScript %i %p = %p    %p %i", ct, dest, ptr, mSlots[ct]->getType(), mSlots[ct]->getType()->getDimX());
64
65        //const uint32_t *p32 = (const uint32_t *)ptr;
66        //for (uint32_t ct2=0; ct2 < mSlots[ct]->getType()->getDimX(); ct2++) {
67            //LOGE("  %i = 0x%08x ", ct2, p32[ct2]);
68        //}
69
70        if (dest) {
71            *dest = ptr;
72        } else {
73            LOGE("ScriptC::setupScript, NULL var binding address.");
74        }
75    }
76}
77
78const Allocation *ScriptC::ptrToAllocation(const void *ptr) const
79{
80    if (!ptr) {
81        return NULL;
82    }
83    for (uint32_t ct=0; ct < mEnviroment.mFieldCount; ct++) {
84        if (!mSlots[ct].get())
85            continue;
86        if (mSlots[ct]->getPtr() == ptr) {
87            return mSlots[ct].get();
88        }
89    }
90    LOGE("ScriptC::ptrToAllocation, failed to find %p", ptr);
91    return NULL;
92}
93
94Script * ScriptC::setTLS(Script *sc)
95{
96    Context::ScriptTLSStruct * tls = (Context::ScriptTLSStruct *)
97                                  pthread_getspecific(Context::gThreadTLSKey);
98    rsAssert(tls);
99    Script *old = tls->mScript;
100    tls->mScript = sc;
101    return old;
102}
103
104
105void ScriptC::setupGLState(Context *rsc)
106{
107    if (mEnviroment.mFragmentStore.get()) {
108        rsc->setFragmentStore(mEnviroment.mFragmentStore.get());
109    }
110    if (mEnviroment.mFragment.get()) {
111        rsc->setFragment(mEnviroment.mFragment.get());
112    }
113    if (mEnviroment.mVertex.get()) {
114        rsc->setVertex(mEnviroment.mVertex.get());
115    }
116    if (mEnviroment.mRaster.get()) {
117        rsc->setRaster(mEnviroment.mRaster.get());
118    }
119}
120
121uint32_t ScriptC::run(Context *rsc)
122{
123    if (mProgram.mRoot == NULL) {
124        rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
125        return 0;
126    }
127
128    setupScript(rsc);
129
130    uint32_t ret = 0;
131    Script * oldTLS = setTLS(this);
132    //LOGE("ScriptC::run %p", mProgram.mRoot);
133    ret = mProgram.mRoot();
134    setTLS(oldTLS);
135    //LOGE("ScriptC::run ret %i", ret);
136    return ret;
137}
138
139void ScriptC::runForEach(Context *rsc, const Allocation *ain, Allocation *aout,
140                         uint32_t xStart, uint32_t yStart, uint32_t xEnd, uint32_t yEnd)
141{
142    LOGE("ScriptC::runForEach not implemented");
143}
144
145void ScriptC::runForEach(Context *rsc, const Allocation *ain, Allocation *aout, uint32_t xStart, uint32_t xEnd)
146{
147    uint32_t dimX = ain->getType()->getDimX();
148    rsAssert(xStart < dimX);
149    rsAssert(xEnd <= dimX);
150    rsAssert(ain->getType()->getDimY() == 0);
151    rsAssert(ain->getType()->getDimZ() == 0);
152
153    if (xStart >= dimX) xStart = dimX - 1;
154    if (xEnd >= dimX) xEnd = dimX - 1;
155    if (xStart > xEnd) return;
156
157    setupScript(rsc);
158    Script * oldTLS = setTLS(this);
159
160    typedef int (*rs_t)(const void *, void *, uint32_t);
161    const uint8_t *ptrIn = (const uint8_t *)ain->getPtr();
162    uint32_t strideIn = ain->getType()->getElementSizeBytes();
163
164    uint8_t *ptrOut = NULL;
165    uint32_t strideOut = 0;
166    if (aout) {
167        ptrOut = (uint8_t *)aout->getPtr();
168        strideOut = aout->getType()->getElementSizeBytes();
169    }
170
171    for (uint32_t ct=xStart; ct < xEnd; ct++) {
172        ((rs_t)mProgram.mRoot) (ptrIn + (strideIn * ct), ptrOut + (strideOut * ct), ct);
173    }
174
175    setTLS(oldTLS);
176}
177
178void ScriptC::runForEach(Context *rsc, const Allocation *ain, Allocation *aout)
179{
180    if (ain->getType()->getDimY()) {
181        runForEach(rsc, ain, aout, 0, 0, 0xffffffff, 0xffffffff);
182    } else {
183        runForEach(rsc, ain, aout, 0, 0xffffffff);
184    }
185}
186
187
188void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len)
189{
190    //LOGE("rsi_ScriptInvoke %i", slot);
191    if ((slot >= mEnviroment.mInvokeFunctionCount) ||
192        (mEnviroment.mInvokeFunctions[slot] == NULL)) {
193        rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script");
194        return;
195    }
196    setupScript(rsc);
197    Script * oldTLS = setTLS(this);
198
199    ((void (*)(const void *, uint32_t))
200        mEnviroment.mInvokeFunctions[slot])(data, len);
201
202    setTLS(oldTLS);
203}
204
205ScriptCState::ScriptCState()
206{
207    mScript = NULL;
208    clear();
209}
210
211ScriptCState::~ScriptCState()
212{
213    delete mScript;
214    mScript = NULL;
215}
216
217void ScriptCState::clear()
218{
219    for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
220        mConstantBufferTypes[ct].clear();
221        mSlotWritable[ct] = false;
222    }
223
224    delete mScript;
225    mScript = new ScriptC(NULL);
226}
227
228static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name)
229{
230    const ScriptCState::SymbolTable_t *sym;
231    sym = ScriptCState::lookupSymbol(name);
232    if (sym) {
233        return sym->mPtr;
234    }
235    sym = ScriptCState::lookupSymbolCL(name);
236    if (sym) {
237        return sym->mPtr;
238    }
239    sym = ScriptCState::lookupSymbolGL(name);
240    if (sym) {
241        return sym->mPtr;
242    }
243    LOGE("ScriptC sym lookup failed for %s", name);
244    return NULL;
245}
246
247void ScriptCState::runCompiler(Context *rsc, ScriptC *s)
248{
249    LOGE("ScriptCState::runCompiler ");
250
251    s->mBccScript = bccCreateScript();
252    bccScriptBitcode(s->mBccScript, s->mEnviroment.mScriptText, s->mEnviroment.mScriptTextLength);
253    bccRegisterSymbolCallback(s->mBccScript, symbolLookup, NULL);
254    bccCompileScript(s->mBccScript);
255    bccGetScriptLabel(s->mBccScript, "root", (BCCvoid**) &s->mProgram.mRoot);
256    bccGetScriptLabel(s->mBccScript, "init", (BCCvoid**) &s->mProgram.mInit);
257    LOGE("root %p,  init %p", s->mProgram.mRoot, s->mProgram.mInit);
258
259    if (s->mProgram.mInit) {
260        s->mProgram.mInit();
261    }
262
263    s->mEnviroment.mInvokeFunctions = (Script::InvokeFunc_t *)calloc(100, sizeof(void *));
264    BCCchar **labels = new char*[100];
265    bccGetFunctions(s->mBccScript, (BCCsizei *)&s->mEnviroment.mInvokeFunctionCount,
266                    100, (BCCchar **)labels);
267    //LOGE("func count %i", s->mEnviroment.mInvokeFunctionCount);
268    for (uint32_t i=0; i < s->mEnviroment.mInvokeFunctionCount; i++) {
269        BCCsizei length;
270        bccGetFunctionBinary(s->mBccScript, labels[i], (BCCvoid **)&(s->mEnviroment.mInvokeFunctions[i]), &length);
271        //LOGE("func %i %p", i, s->mEnviroment.mInvokeFunctions[i]);
272    }
273
274    s->mEnviroment.mFieldAddress = (void **)calloc(100, sizeof(void *));
275    bccGetExportVars(s->mBccScript, (BCCsizei *)&s->mEnviroment.mFieldCount,
276                     100, s->mEnviroment.mFieldAddress);
277    //LOGE("var count %i", s->mEnviroment.mFieldCount);
278    for (uint32_t i=0; i < s->mEnviroment.mFieldCount; i++) {
279        //LOGE("var %i %p", i, s->mEnviroment.mFieldAddress[i]);
280    }
281
282    s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
283    s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
284    s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
285    s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
286
287    if (s->mProgram.mRoot) {
288        const static int pragmaMax = 16;
289        BCCsizei pragmaCount;
290        BCCchar * str[pragmaMax];
291        bccGetPragmas(s->mBccScript, &pragmaCount, pragmaMax, &str[0]);
292
293        for (int ct=0; ct < pragmaCount; ct+=2) {
294            //LOGE("pragme %s %s", str[ct], str[ct+1]);
295            if (!strcmp(str[ct], "version")) {
296                continue;
297            }
298
299            if (!strcmp(str[ct], "stateVertex")) {
300                if (!strcmp(str[ct+1], "default")) {
301                    continue;
302                }
303                if (!strcmp(str[ct+1], "parent")) {
304                    s->mEnviroment.mVertex.clear();
305                    continue;
306                }
307                LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
308            }
309
310            if (!strcmp(str[ct], "stateRaster")) {
311                if (!strcmp(str[ct+1], "default")) {
312                    continue;
313                }
314                if (!strcmp(str[ct+1], "parent")) {
315                    s->mEnviroment.mRaster.clear();
316                    continue;
317                }
318                LOGE("Unreconized value %s passed to stateRaster", str[ct+1]);
319            }
320
321            if (!strcmp(str[ct], "stateFragment")) {
322                if (!strcmp(str[ct+1], "default")) {
323                    continue;
324                }
325                if (!strcmp(str[ct+1], "parent")) {
326                    s->mEnviroment.mFragment.clear();
327                    continue;
328                }
329                LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
330            }
331
332            if (!strcmp(str[ct], "stateStore")) {
333                if (!strcmp(str[ct+1], "default")) {
334                    continue;
335                }
336                if (!strcmp(str[ct+1], "parent")) {
337                    s->mEnviroment.mFragmentStore.clear();
338                    continue;
339                }
340                LOGE("Unreconized value %s passed to stateStore", str[ct+1]);
341            }
342
343        }
344
345
346    } else {
347        // Deal with an error.
348    }
349}
350
351
352
353namespace android {
354namespace renderscript {
355
356void rsi_ScriptCBegin(Context * rsc)
357{
358    ScriptCState *ss = &rsc->mScriptC;
359    ss->clear();
360}
361
362void rsi_ScriptCSetScript(Context * rsc, void *vp)
363{
364    rsAssert(0);
365    //ScriptCState *ss = &rsc->mScriptC;
366    //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
367}
368
369void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
370{
371    ScriptCState *ss = &rsc->mScriptC;
372
373    char *t = (char *)malloc(len + 1);
374    memcpy(t, text, len);
375    t[len] = 0;
376    ss->mScript->mEnviroment.mScriptText = t;
377    ss->mScript->mEnviroment.mScriptTextLength = len;
378}
379
380
381RsScript rsi_ScriptCCreate(Context * rsc)
382{
383    ScriptCState *ss = &rsc->mScriptC;
384
385    ScriptC *s = ss->mScript;
386    ss->mScript = NULL;
387
388    ss->runCompiler(rsc, s);
389    s->incUserRef();
390    s->setContext(rsc);
391    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
392        s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
393        s->mSlotWritable[ct] = ss->mSlotWritable[ct];
394    }
395
396    ss->clear();
397    return s;
398}
399
400}
401}
402
403
404