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 "utils/Timers.h"
     20 #include "utils/StopWatch.h"
     21 
     22 #ifndef ANDROID_RS_SERIALIZE
     23 #include <bcinfo/BitcodeTranslator.h>
     24 #include <bcinfo/BitcodeWrapper.h>
     25 #endif
     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 ScriptC::ScriptC(Context *rsc) : Script(rsc) {
     36 #ifndef ANDROID_RS_SERIALIZE
     37     BT = NULL;
     38 #endif
     39 }
     40 
     41 ScriptC::~ScriptC() {
     42 #ifndef ANDROID_RS_SERIALIZE
     43     if (BT) {
     44         delete BT;
     45         BT = NULL;
     46     }
     47 #endif
     48     mRSC->mHal.funcs.script.invokeFreeChildren(mRSC, this);
     49     mRSC->mHal.funcs.script.destroy(mRSC, this);
     50 }
     51 
     52 void ScriptC::setupScript(Context *rsc) {
     53     mEnviroment.mStartTimeMillis
     54                 = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
     55 
     56     for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) {
     57         if (mSlots[ct].get() && !mTypes[ct].get()) {
     58             mTypes[ct].set(mSlots[ct]->getType());
     59         }
     60 
     61         if (!mTypes[ct].get())
     62             continue;
     63         void *ptr = NULL;
     64         if (mSlots[ct].get()) {
     65             ptr = mSlots[ct]->getPtr();
     66         }
     67 
     68         rsc->mHal.funcs.script.setGlobalBind(rsc, this, ct, ptr);
     69     }
     70 }
     71 
     72 const Allocation *ScriptC::ptrToAllocation(const void *ptr) const {
     73     //LOGE("ptr to alloc %p", ptr);
     74     if (!ptr) {
     75         return NULL;
     76     }
     77     for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) {
     78         if (!mSlots[ct].get())
     79             continue;
     80         if (mSlots[ct]->getPtr() == ptr) {
     81             return mSlots[ct].get();
     82         }
     83     }
     84     LOGE("ScriptC::ptrToAllocation, failed to find %p", ptr);
     85     return NULL;
     86 }
     87 
     88 void ScriptC::setupGLState(Context *rsc) {
     89     if (mEnviroment.mFragmentStore.get()) {
     90         rsc->setProgramStore(mEnviroment.mFragmentStore.get());
     91     }
     92     if (mEnviroment.mFragment.get()) {
     93         rsc->setProgramFragment(mEnviroment.mFragment.get());
     94     }
     95     if (mEnviroment.mVertex.get()) {
     96         rsc->setProgramVertex(mEnviroment.mVertex.get());
     97     }
     98     if (mEnviroment.mRaster.get()) {
     99         rsc->setProgramRaster(mEnviroment.mRaster.get());
    100     }
    101 }
    102 
    103 uint32_t ScriptC::run(Context *rsc) {
    104     if (mHal.info.root == NULL) {
    105         rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script");
    106         return 0;
    107     }
    108 
    109     setupGLState(rsc);
    110     setupScript(rsc);
    111 
    112     uint32_t ret = 0;
    113 
    114     if (rsc->props.mLogScripts) {
    115         LOGV("%p ScriptC::run invoking root,  ptr %p", rsc, mHal.info.root);
    116     }
    117 
    118     ret = rsc->mHal.funcs.script.invokeRoot(rsc, this);
    119 
    120     if (rsc->props.mLogScripts) {
    121         LOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret);
    122     }
    123 
    124     return ret;
    125 }
    126 
    127 
    128 void ScriptC::runForEach(Context *rsc,
    129                          const Allocation * ain,
    130                          Allocation * aout,
    131                          const void * usr,
    132                          size_t usrBytes,
    133                          const RsScriptCall *sc) {
    134 
    135     Context::PushState ps(rsc);
    136 
    137     setupGLState(rsc);
    138     setupScript(rsc);
    139     rsc->mHal.funcs.script.invokeForEach(rsc, this, 0, ain, aout, usr, usrBytes, sc);
    140 }
    141 
    142 void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, size_t len) {
    143     if (slot >= mHal.info.exportedFunctionCount) {
    144         rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script");
    145         return;
    146     }
    147     setupScript(rsc);
    148 
    149     if (rsc->props.mLogScripts) {
    150         LOGV("%p ScriptC::Invoke invoking slot %i,  ptr %p", rsc, slot, this);
    151     }
    152     rsc->mHal.funcs.script.invokeFunction(rsc, this, slot, data, len);
    153 }
    154 
    155 ScriptCState::ScriptCState() {
    156 }
    157 
    158 ScriptCState::~ScriptCState() {
    159 }
    160 
    161 /*
    162 static void* symbolLookup(void* pContext, char const* name) {
    163     const ScriptCState::SymbolTable_t *sym;
    164     ScriptC *s = (ScriptC *)pContext;
    165     if (!strcmp(name, "__isThreadable")) {
    166       return (void*) s->mHal.info.isThreadable;
    167     } else if (!strcmp(name, "__clearThreadable")) {
    168       s->mHal.info.isThreadable = false;
    169       return NULL;
    170     }
    171     sym = ScriptCState::lookupSymbol(name);
    172     if (!sym) {
    173         sym = ScriptCState::lookupSymbolCL(name);
    174     }
    175     if (!sym) {
    176         sym = ScriptCState::lookupSymbolGL(name);
    177     }
    178     if (sym) {
    179         s->mHal.info.isThreadable &= sym->threadable;
    180         return sym->mPtr;
    181     }
    182     LOGE("ScriptC sym lookup failed for %s", name);
    183     return NULL;
    184 }
    185 */
    186 
    187 #if 0
    188 extern const char rs_runtime_lib_bc[];
    189 extern unsigned rs_runtime_lib_bc_size;
    190 #endif
    191 
    192 bool ScriptC::runCompiler(Context *rsc,
    193                           const char *resName,
    194                           const char *cacheDir,
    195                           const uint8_t *bitcode,
    196                           size_t bitcodeLen) {
    197 
    198     //LOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen);
    199 #ifndef ANDROID_RS_SERIALIZE
    200     uint32_t sdkVersion = 0;
    201     bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeLen);
    202     if (!bcWrapper.unwrap()) {
    203         LOGE("Bitcode is not in proper container format (raw or wrapper)");
    204         return false;
    205     }
    206 
    207     rsAssert(bcWrapper.getHeaderVersion() == 0);
    208     if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) {
    209         sdkVersion = bcWrapper.getTargetAPI();
    210     }
    211 
    212     if (sdkVersion == 0) {
    213         // This signals that we didn't have a wrapper containing information
    214         // about the bitcode.
    215         sdkVersion = rsc->getTargetSdkVersion();
    216     }
    217 
    218     if (BT) {
    219         delete BT;
    220     }
    221     BT = new bcinfo::BitcodeTranslator((const char *)bitcode, bitcodeLen,
    222                                        sdkVersion);
    223     if (!BT->translate()) {
    224         LOGE("Failed to translate bitcode from version: %u", sdkVersion);
    225         delete BT;
    226         BT = NULL;
    227         return false;
    228     }
    229     bitcode = (const uint8_t *) BT->getTranslatedBitcode();
    230     bitcodeLen = BT->getTranslatedBitcodeSize();
    231 #endif
    232 
    233     rsc->mHal.funcs.script.init(rsc, this, resName, cacheDir, bitcode, bitcodeLen, 0);
    234 
    235     mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
    236     mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
    237     mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore());
    238     mEnviroment.mRaster.set(rsc->getDefaultProgramRaster());
    239 
    240     rsc->mHal.funcs.script.invokeInit(rsc, this);
    241 
    242     for (size_t i=0; i < mHal.info.exportedPragmaCount; ++i) {
    243         const char * key = mHal.info.exportedPragmaKeyList[i];
    244         const char * value = mHal.info.exportedPragmaValueList[i];
    245         //LOGE("pragma %s %s", keys[i], values[i]);
    246         if (!strcmp(key, "version")) {
    247             if (!strcmp(value, "1")) {
    248                 continue;
    249             }
    250             LOGE("Invalid version pragma value: %s\n", value);
    251             return false;
    252         }
    253 
    254         if (!strcmp(key, "stateVertex")) {
    255             if (!strcmp(value, "default")) {
    256                 continue;
    257             }
    258             if (!strcmp(value, "parent")) {
    259                 mEnviroment.mVertex.clear();
    260                 continue;
    261             }
    262             LOGE("Unrecognized value %s passed to stateVertex", value);
    263             return false;
    264         }
    265 
    266         if (!strcmp(key, "stateRaster")) {
    267             if (!strcmp(value, "default")) {
    268                 continue;
    269             }
    270             if (!strcmp(value, "parent")) {
    271                 mEnviroment.mRaster.clear();
    272                 continue;
    273             }
    274             LOGE("Unrecognized value %s passed to stateRaster", value);
    275             return false;
    276         }
    277 
    278         if (!strcmp(key, "stateFragment")) {
    279             if (!strcmp(value, "default")) {
    280                 continue;
    281             }
    282             if (!strcmp(value, "parent")) {
    283                 mEnviroment.mFragment.clear();
    284                 continue;
    285             }
    286             LOGE("Unrecognized value %s passed to stateFragment", value);
    287             return false;
    288         }
    289 
    290         if (!strcmp(key, "stateStore")) {
    291             if (!strcmp(value, "default")) {
    292                 continue;
    293             }
    294             if (!strcmp(value, "parent")) {
    295                 mEnviroment.mFragmentStore.clear();
    296                 continue;
    297             }
    298             LOGE("Unrecognized value %s passed to stateStore", value);
    299             return false;
    300         }
    301     }
    302 
    303     mSlots = new ObjectBaseRef<Allocation>[mHal.info.exportedVariableCount];
    304     mTypes = new ObjectBaseRef<const Type>[mHal.info.exportedVariableCount];
    305 
    306     return true;
    307 }
    308 
    309 namespace android {
    310 namespace renderscript {
    311 
    312 RsScript rsi_ScriptCCreate(Context *rsc,
    313                            const char *resName, size_t resName_length,
    314                            const char *cacheDir, size_t cacheDir_length,
    315                            const char *text, size_t text_length)
    316 {
    317     ScriptC *s = new ScriptC(rsc);
    318 
    319     if (!s->runCompiler(rsc, resName, cacheDir, (uint8_t *)text, text_length)) {
    320         // Error during compile, destroy s and return null.
    321         delete s;
    322         return NULL;
    323     }
    324 
    325     s->incUserRef();
    326     return s;
    327 }
    328 
    329 }
    330 }
    331