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