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