Home | History | Annotate | Download | only in rs
      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 
     21 #include "acc/acc.h"
     22 #include "utils/Timers.h"
     23 
     24 #include <GLES/gl.h>
     25 #include <GLES/glext.h>
     26 
     27 using namespace android;
     28 using namespace android::renderscript;
     29 
     30 #define GET_TLS()  Context::ScriptTLSStruct * tls = \
     31     (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
     32     Context * rsc = tls->mContext; \
     33     ScriptC * sc = (ScriptC *) tls->mScript
     34 
     35 
     36 ScriptC::ScriptC(Context *rsc) : Script(rsc)
     37 {
     38     mAllocFile = __FILE__;
     39     mAllocLine = __LINE__;
     40     mAccScript = NULL;
     41     memset(&mProgram, 0, sizeof(mProgram));
     42 }
     43 
     44 ScriptC::~ScriptC()
     45 {
     46     if (mAccScript) {
     47         accDeleteScript(mAccScript);
     48     }
     49     free(mEnviroment.mScriptText);
     50     mEnviroment.mScriptText = NULL;
     51 }
     52 
     53 void ScriptC::setupScript()
     54 {
     55     for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
     56         if (mProgram.mSlotPointers[ct]) {
     57             *mProgram.mSlotPointers[ct] = mSlots[ct]->getPtr();
     58         }
     59     }
     60 }
     61 
     62 
     63 uint32_t ScriptC::run(Context *rsc, uint32_t launchIndex)
     64 {
     65     if (mProgram.mScript == NULL) {
     66         rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
     67         return 0;
     68     }
     69 
     70     Context::ScriptTLSStruct * tls =
     71     (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey);
     72     rsAssert(tls);
     73 
     74     if (mEnviroment.mFragmentStore.get()) {
     75         rsc->setFragmentStore(mEnviroment.mFragmentStore.get());
     76     }
     77     if (mEnviroment.mFragment.get()) {
     78         rsc->setFragment(mEnviroment.mFragment.get());
     79     }
     80     if (mEnviroment.mVertex.get()) {
     81         rsc->setVertex(mEnviroment.mVertex.get());
     82     }
     83     if (mEnviroment.mRaster.get()) {
     84         rsc->setRaster(mEnviroment.mRaster.get());
     85     }
     86 
     87     if (launchIndex == 0) {
     88         mEnviroment.mStartTimeMillis
     89                 = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
     90     }
     91     setupScript();
     92 
     93     uint32_t ret = 0;
     94     tls->mScript = this;
     95     ret = mProgram.mScript(launchIndex);
     96     tls->mScript = NULL;
     97     return ret;
     98 }
     99 
    100 ScriptCState::ScriptCState()
    101 {
    102     mScript = NULL;
    103     clear();
    104 }
    105 
    106 ScriptCState::~ScriptCState()
    107 {
    108     delete mScript;
    109     mScript = NULL;
    110 }
    111 
    112 void ScriptCState::clear()
    113 {
    114     for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
    115         mConstantBufferTypes[ct].clear();
    116         mSlotNames[ct].setTo("");
    117         mInvokableNames[ct].setTo("");
    118         mSlotWritable[ct] = false;
    119     }
    120 
    121     delete mScript;
    122     mScript = new ScriptC(NULL);
    123 
    124     mInt32Defines.clear();
    125     mFloatDefines.clear();
    126 }
    127 
    128 static ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name)
    129 {
    130     const ScriptCState::SymbolTable_t *sym = ScriptCState::lookupSymbol(name);
    131     if (sym) {
    132         return sym->mPtr;
    133     }
    134     LOGE("ScriptC sym lookup failed for %s", name);
    135     return NULL;
    136 }
    137 
    138 void ScriptCState::runCompiler(Context *rsc, ScriptC *s)
    139 {
    140     s->mAccScript = accCreateScript();
    141     String8 tmp;
    142 
    143     rsc->appendNameDefines(&tmp);
    144     appendDecls(&tmp);
    145     appendVarDefines(rsc, &tmp);
    146     appendTypes(rsc, &tmp);
    147     tmp.append("#line 1\n");
    148 
    149     const char* scriptSource[] = {tmp.string(), s->mEnviroment.mScriptText};
    150     int scriptLength[] = {tmp.length(), s->mEnviroment.mScriptTextLength} ;
    151     accScriptSource(s->mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength);
    152     accRegisterSymbolCallback(s->mAccScript, symbolLookup, NULL);
    153     accCompileScript(s->mAccScript);
    154     accGetScriptLabel(s->mAccScript, "main", (ACCvoid**) &s->mProgram.mScript);
    155     accGetScriptLabel(s->mAccScript, "init", (ACCvoid**) &s->mProgram.mInit);
    156     rsAssert(s->mProgram.mScript);
    157 
    158     if (!s->mProgram.mScript) {
    159         ACCchar buf[4096];
    160         ACCsizei len;
    161         accGetScriptInfoLog(s->mAccScript, sizeof(buf), &len, buf);
    162         LOGE("%s", buf);
    163         rsc->setError(RS_ERROR_BAD_SCRIPT, "Error compiling user script.");
    164         return;
    165     }
    166 
    167     if (s->mProgram.mInit) {
    168         s->mProgram.mInit();
    169     }
    170 
    171     for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
    172         if (mSlotNames[ct].length() > 0) {
    173             accGetScriptLabel(s->mAccScript,
    174                               mSlotNames[ct].string(),
    175                               (ACCvoid**) &s->mProgram.mSlotPointers[ct]);
    176         }
    177     }
    178 
    179     for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
    180         if (mInvokableNames[ct].length() > 0) {
    181             accGetScriptLabel(s->mAccScript,
    182                               mInvokableNames[ct].string(),
    183                               (ACCvoid**) &s->mEnviroment.mInvokables[ct]);
    184         }
    185     }
    186 
    187     s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
    188     s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
    189     s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore());
    190     s->mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
    191 
    192     if (s->mProgram.mScript) {
    193         const static int pragmaMax = 16;
    194         ACCsizei pragmaCount;
    195         ACCchar * str[pragmaMax];
    196         accGetPragmas(s->mAccScript, &pragmaCount, pragmaMax, &str[0]);
    197 
    198         for (int ct=0; ct < pragmaCount; ct+=2) {
    199             if (!strcmp(str[ct], "version")) {
    200                 continue;
    201             }
    202 
    203             if (!strcmp(str[ct], "stateVertex")) {
    204                 if (!strcmp(str[ct+1], "default")) {
    205                     continue;
    206                 }
    207                 if (!strcmp(str[ct+1], "parent")) {
    208                     s->mEnviroment.mVertex.clear();
    209                     continue;
    210                 }
    211                 ProgramVertex * pv = (ProgramVertex *)rsc->lookupName(str[ct+1]);
    212                 if (pv != NULL) {
    213                     s->mEnviroment.mVertex.set(pv);
    214                     continue;
    215                 }
    216                 LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
    217             }
    218 
    219             if (!strcmp(str[ct], "stateRaster")) {
    220                 if (!strcmp(str[ct+1], "default")) {
    221                     continue;
    222                 }
    223                 if (!strcmp(str[ct+1], "parent")) {
    224                     s->mEnviroment.mRaster.clear();
    225                     continue;
    226                 }
    227                 ProgramRaster * pr = (ProgramRaster *)rsc->lookupName(str[ct+1]);
    228                 if (pr != NULL) {
    229                     s->mEnviroment.mRaster.set(pr);
    230                     continue;
    231                 }
    232                 LOGE("Unreconized value %s passed to stateRaster", str[ct+1]);
    233             }
    234 
    235             if (!strcmp(str[ct], "stateFragment")) {
    236                 if (!strcmp(str[ct+1], "default")) {
    237                     continue;
    238                 }
    239                 if (!strcmp(str[ct+1], "parent")) {
    240                     s->mEnviroment.mFragment.clear();
    241                     continue;
    242                 }
    243                 ProgramFragment * pf = (ProgramFragment *)rsc->lookupName(str[ct+1]);
    244                 if (pf != NULL) {
    245                     s->mEnviroment.mFragment.set(pf);
    246                     continue;
    247                 }
    248                 LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
    249             }
    250 
    251             if (!strcmp(str[ct], "stateStore")) {
    252                 if (!strcmp(str[ct+1], "default")) {
    253                     continue;
    254                 }
    255                 if (!strcmp(str[ct+1], "parent")) {
    256                     s->mEnviroment.mFragmentStore.clear();
    257                     continue;
    258                 }
    259                 ProgramFragmentStore * pfs =
    260                     (ProgramFragmentStore *)rsc->lookupName(str[ct+1]);
    261                 if (pfs != NULL) {
    262                     s->mEnviroment.mFragmentStore.set(pfs);
    263                     continue;
    264                 }
    265                 LOGE("Unreconized value %s passed to stateStore", str[ct+1]);
    266             }
    267 
    268         }
    269 
    270 
    271     } else {
    272         // Deal with an error.
    273     }
    274 }
    275 
    276 static void appendElementBody(String8 *s, const Element *e)
    277 {
    278     s->append(" {\n");
    279     for (size_t ct2=0; ct2 < e->getFieldCount(); ct2++) {
    280         const Element *c = e->getField(ct2);
    281         s->append("    ");
    282         s->append(c->getCType());
    283         s->append(" ");
    284         s->append(e->getFieldName(ct2));
    285         s->append(";\n");
    286     }
    287     s->append("}");
    288 }
    289 
    290 void ScriptCState::appendVarDefines(const Context *rsc, String8 *str)
    291 {
    292     char buf[256];
    293     if (rsc->props.mLogScripts) {
    294         LOGD("appendVarDefines mInt32Defines.size()=%d mFloatDefines.size()=%d\n",
    295                 mInt32Defines.size(), mFloatDefines.size());
    296     }
    297     for (size_t ct=0; ct < mInt32Defines.size(); ct++) {
    298         str->append("#define ");
    299         str->append(mInt32Defines.keyAt(ct));
    300         str->append(" ");
    301         sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct));
    302         str->append(buf);
    303     }
    304     for (size_t ct=0; ct < mFloatDefines.size(); ct++) {
    305         str->append("#define ");
    306         str->append(mFloatDefines.keyAt(ct));
    307         str->append(" ");
    308         sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct));
    309         str->append(buf);
    310     }
    311 }
    312 
    313 
    314 
    315 void ScriptCState::appendTypes(const Context *rsc, String8 *str)
    316 {
    317     char buf[256];
    318     String8 tmp;
    319 
    320     str->append("struct vecF32_2_s {float x; float y;};\n");
    321     str->append("struct vecF32_3_s {float x; float y; float z;};\n");
    322     str->append("struct vecF32_4_s {float x; float y; float z; float w;};\n");
    323     str->append("struct vecU8_4_s {char r; char g; char b; char a;};\n");
    324     str->append("#define vecF32_2_t struct vecF32_2_s\n");
    325     str->append("#define vecF32_3_t struct vecF32_3_s\n");
    326     str->append("#define vecF32_4_t struct vecF32_4_s\n");
    327     str->append("#define vecU8_4_t struct vecU8_4_s\n");
    328     str->append("#define vecI8_4_t struct vecU8_4_s\n");
    329 
    330     for (size_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
    331         const Type *t = mConstantBufferTypes[ct].get();
    332         if (!t) {
    333             continue;
    334         }
    335         const Element *e = t->getElement();
    336         if (e->getName() && (e->getFieldCount() > 1)) {
    337             String8 s("struct struct_");
    338             s.append(e->getName());
    339             s.append(e->getCStructBody());
    340             s.append(";\n");
    341 
    342             s.append("#define ");
    343             s.append(e->getName());
    344             s.append("_t struct struct_");
    345             s.append(e->getName());
    346             s.append("\n\n");
    347             if (rsc->props.mLogScripts) {
    348                 LOGV("%s", static_cast<const char*>(s));
    349             }
    350             str->append(s);
    351         }
    352 
    353         if (mSlotNames[ct].length() > 0) {
    354             String8 s;
    355             if (e->getName()) {
    356                 // Use the named struct
    357                 s.setTo(e->getName());
    358             } else {
    359                 // create an struct named from the slot.
    360                 s.setTo("struct ");
    361                 s.append(mSlotNames[ct]);
    362                 s.append("_s");
    363                 s.append(e->getCStructBody());
    364                 //appendElementBody(&s, e);
    365                 s.append(";\n");
    366                 s.append("struct ");
    367                 s.append(mSlotNames[ct]);
    368                 s.append("_s");
    369             }
    370 
    371             s.append(" * ");
    372             s.append(mSlotNames[ct]);
    373             s.append(";\n");
    374             if (rsc->props.mLogScripts) {
    375                 LOGV("%s", static_cast<const char*>(s));
    376             }
    377             str->append(s);
    378         }
    379     }
    380 }
    381 
    382 
    383 namespace android {
    384 namespace renderscript {
    385 
    386 void rsi_ScriptCBegin(Context * rsc)
    387 {
    388     ScriptCState *ss = &rsc->mScriptC;
    389     ss->clear();
    390 }
    391 
    392 void rsi_ScriptCSetScript(Context * rsc, void *vp)
    393 {
    394     rsAssert(0);
    395     //ScriptCState *ss = &rsc->mScriptC;
    396     //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
    397 }
    398 
    399 void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
    400 {
    401     ScriptCState *ss = &rsc->mScriptC;
    402 
    403     char *t = (char *)malloc(len + 1);
    404     memcpy(t, text, len);
    405     t[len] = 0;
    406     ss->mScript->mEnviroment.mScriptText = t;
    407     ss->mScript->mEnviroment.mScriptTextLength = len;
    408 }
    409 
    410 
    411 RsScript rsi_ScriptCCreate(Context * rsc)
    412 {
    413     ScriptCState *ss = &rsc->mScriptC;
    414 
    415     ScriptC *s = ss->mScript;
    416     ss->mScript = NULL;
    417 
    418     ss->runCompiler(rsc, s);
    419     s->incUserRef();
    420     s->setContext(rsc);
    421     for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
    422         s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
    423         s->mSlotNames[ct] = ss->mSlotNames[ct];
    424         s->mSlotWritable[ct] = ss->mSlotWritable[ct];
    425     }
    426 
    427     ss->clear();
    428     return s;
    429 }
    430 
    431 void rsi_ScriptCSetDefineF(Context *rsc, const char* name, float value)
    432 {
    433     ScriptCState *ss = &rsc->mScriptC;
    434     ss->mFloatDefines.add(String8(name), value);
    435 }
    436 
    437 void rsi_ScriptCSetDefineI32(Context *rsc, const char* name, int32_t value)
    438 {
    439     ScriptCState *ss = &rsc->mScriptC;
    440     ss->mInt32Defines.add(String8(name), value);
    441 }
    442 
    443 }
    444 }
    445 
    446 
    447