rsScriptC.cpp revision d38f9254a345062dd44d910aa589f94e76d27092
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 //ALOGE("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 ALOGE("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 ALOGE("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 //ALOGE("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 ALOGE("Bitcode is not in proper container format (raw or wrapper)"); 206 return false; 207 } 208 209 if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) { 210 sdkVersion = bcWrapper.getTargetAPI(); 211 } 212 213 if (sdkVersion == 0) { 214 // This signals that we didn't have a wrapper containing information 215 // about the bitcode. 216 sdkVersion = rsc->getTargetSdkVersion(); 217 } 218 219 if (BT) { 220 delete BT; 221 } 222 BT = new bcinfo::BitcodeTranslator((const char *)bitcode, bitcodeLen, 223 sdkVersion); 224 if (!BT->translate()) { 225 ALOGE("Failed to translate bitcode from version: %u", sdkVersion); 226 delete BT; 227 BT = NULL; 228 return false; 229 } 230 bitcode = (const uint8_t *) BT->getTranslatedBitcode(); 231 bitcodeLen = BT->getTranslatedBitcodeSize(); 232#endif 233 234 if (!rsc->mHal.funcs.script.init(rsc, this, resName, cacheDir, bitcode, bitcodeLen, 0)) { 235 return false; 236 } 237 238 mInitialized = true; 239 mEnviroment.mFragment.set(rsc->getDefaultProgramFragment()); 240 mEnviroment.mVertex.set(rsc->getDefaultProgramVertex()); 241 mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore()); 242 mEnviroment.mRaster.set(rsc->getDefaultProgramRaster()); 243 244 rsc->mHal.funcs.script.invokeInit(rsc, this); 245 246 for (size_t i=0; i < mHal.info.exportedPragmaCount; ++i) { 247 const char * key = mHal.info.exportedPragmaKeyList[i]; 248 const char * value = mHal.info.exportedPragmaValueList[i]; 249 //ALOGE("pragma %s %s", keys[i], values[i]); 250 if (!strcmp(key, "version")) { 251 if (!strcmp(value, "1")) { 252 continue; 253 } 254 ALOGE("Invalid version pragma value: %s\n", value); 255 return false; 256 } 257 258 if (!strcmp(key, "stateVertex")) { 259 if (!strcmp(value, "default")) { 260 continue; 261 } 262 if (!strcmp(value, "parent")) { 263 mEnviroment.mVertex.clear(); 264 continue; 265 } 266 ALOGE("Unrecognized value %s passed to stateVertex", value); 267 return false; 268 } 269 270 if (!strcmp(key, "stateRaster")) { 271 if (!strcmp(value, "default")) { 272 continue; 273 } 274 if (!strcmp(value, "parent")) { 275 mEnviroment.mRaster.clear(); 276 continue; 277 } 278 ALOGE("Unrecognized value %s passed to stateRaster", value); 279 return false; 280 } 281 282 if (!strcmp(key, "stateFragment")) { 283 if (!strcmp(value, "default")) { 284 continue; 285 } 286 if (!strcmp(value, "parent")) { 287 mEnviroment.mFragment.clear(); 288 continue; 289 } 290 ALOGE("Unrecognized value %s passed to stateFragment", value); 291 return false; 292 } 293 294 if (!strcmp(key, "stateStore")) { 295 if (!strcmp(value, "default")) { 296 continue; 297 } 298 if (!strcmp(value, "parent")) { 299 mEnviroment.mFragmentStore.clear(); 300 continue; 301 } 302 ALOGE("Unrecognized value %s passed to stateStore", value); 303 return false; 304 } 305 } 306 307 mSlots = new ObjectBaseRef<Allocation>[mHal.info.exportedVariableCount]; 308 mTypes = new ObjectBaseRef<const Type>[mHal.info.exportedVariableCount]; 309 310 return true; 311} 312 313namespace android { 314namespace renderscript { 315 316RsScript rsi_ScriptCCreate(Context *rsc, 317 const char *resName, size_t resName_length, 318 const char *cacheDir, size_t cacheDir_length, 319 const char *text, size_t text_length) 320{ 321 ScriptC *s = new ScriptC(rsc); 322 323 if (!s->runCompiler(rsc, resName, cacheDir, (uint8_t *)text, text_length)) { 324 // Error during compile, destroy s and return null. 325 delete s; 326 return NULL; 327 } 328 329 s->incUserRef(); 330 return s; 331} 332 333} 334} 335