rsScriptC.cpp revision 4419977d78018a9933c7f455fe001f644f2d638b
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 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 uint32_t slot, 132 const Allocation * ain, 133 Allocation * aout, 134 const void * usr, 135 size_t usrBytes, 136 const RsScriptCall *sc) { 137 138 Context::PushState ps(rsc); 139 140 setupGLState(rsc); 141 setupScript(rsc); 142 rsc->mHal.funcs.script.invokeForEach(rsc, this, slot, ain, aout, usr, usrBytes, sc); 143} 144 145void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, size_t len) { 146 if (slot >= mHal.info.exportedFunctionCount) { 147 rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script"); 148 return; 149 } 150 setupScript(rsc); 151 152 if (rsc->props.mLogScripts) { 153 ALOGV("%p ScriptC::Invoke invoking slot %i, ptr %p", rsc, slot, this); 154 } 155 rsc->mHal.funcs.script.invokeFunction(rsc, this, slot, data, len); 156} 157 158ScriptCState::ScriptCState() { 159} 160 161ScriptCState::~ScriptCState() { 162} 163 164/* 165static void* symbolLookup(void* pContext, char const* name) { 166 const ScriptCState::SymbolTable_t *sym; 167 ScriptC *s = (ScriptC *)pContext; 168 if (!strcmp(name, "__isThreadable")) { 169 return (void*) s->mHal.info.isThreadable; 170 } else if (!strcmp(name, "__clearThreadable")) { 171 s->mHal.info.isThreadable = false; 172 return NULL; 173 } 174 sym = ScriptCState::lookupSymbol(name); 175 if (!sym) { 176 sym = ScriptCState::lookupSymbolCL(name); 177 } 178 if (!sym) { 179 sym = ScriptCState::lookupSymbolGL(name); 180 } 181 if (sym) { 182 s->mHal.info.isThreadable &= sym->threadable; 183 return sym->mPtr; 184 } 185 ALOGE("ScriptC sym lookup failed for %s", name); 186 return NULL; 187} 188*/ 189 190#if 0 191extern const char rs_runtime_lib_bc[]; 192extern unsigned rs_runtime_lib_bc_size; 193#endif 194 195bool ScriptC::runCompiler(Context *rsc, 196 const char *resName, 197 const char *cacheDir, 198 const uint8_t *bitcode, 199 size_t bitcodeLen) { 200 201 //ALOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen); 202#ifndef ANDROID_RS_SERIALIZE 203 uint32_t sdkVersion = 0; 204 bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeLen); 205 if (!bcWrapper.unwrap()) { 206 ALOGE("Bitcode is not in proper container format (raw or wrapper)"); 207 return false; 208 } 209 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 ALOGE("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 //ALOGE("pragma %s %s", keys[i], values[i]); 251 if (!strcmp(key, "version")) { 252 if (!strcmp(value, "1")) { 253 continue; 254 } 255 ALOGE("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 ALOGE("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 ALOGE("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 ALOGE("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 ALOGE("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 ObjectBase::checkDelete(s); 327 return NULL; 328 } 329 330 s->incUserRef(); 331 return s; 332} 333 334} 335} 336