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