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