rsScriptC.cpp revision b81a0eb8180791e4eaab1253b59fa8bd562b046b
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 22using namespace android; 23using namespace android::renderscript; 24 25#define GET_TLS() Context::ScriptTLSStruct * tls = \ 26 (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \ 27 Context * rsc = tls->mContext; \ 28 ScriptC * sc = (ScriptC *) tls->mScript 29 30ScriptC::ScriptC(Context *rsc) : Script(rsc) { 31} 32 33ScriptC::~ScriptC() { 34 mRSC->mHal.funcs.script.destroy(mRSC, this); 35} 36 37void ScriptC::setupScript(Context *rsc) { 38 mEnviroment.mStartTimeMillis 39 = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC)); 40 41 for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) { 42 if (mSlots[ct].get() && !mTypes[ct].get()) { 43 mTypes[ct].set(mSlots[ct]->getType()); 44 } 45 46 if (!mTypes[ct].get()) 47 continue; 48 void *ptr = NULL; 49 if (mSlots[ct].get()) { 50 ptr = mSlots[ct]->getPtr(); 51 } 52 53 rsc->mHal.funcs.script.setGlobalBind(rsc, this, ct, ptr); 54 } 55} 56 57const Allocation *ScriptC::ptrToAllocation(const void *ptr) const { 58 //LOGE("ptr to alloc %p", ptr); 59 if (!ptr) { 60 return NULL; 61 } 62 for (uint32_t ct=0; ct < mHal.info.exportedVariableCount; ct++) { 63 if (!mSlots[ct].get()) 64 continue; 65 if (mSlots[ct]->getPtr() == ptr) { 66 return mSlots[ct].get(); 67 } 68 } 69 LOGE("ScriptC::ptrToAllocation, failed to find %p", ptr); 70 return NULL; 71} 72 73void ScriptC::setupGLState(Context *rsc) { 74 if (mEnviroment.mFragmentStore.get()) { 75 rsc->setProgramStore(mEnviroment.mFragmentStore.get()); 76 } 77 if (mEnviroment.mFragment.get()) { 78 rsc->setProgramFragment(mEnviroment.mFragment.get()); 79 } 80 if (mEnviroment.mVertex.get()) { 81 rsc->setProgramVertex(mEnviroment.mVertex.get()); 82 } 83 if (mEnviroment.mRaster.get()) { 84 rsc->setProgramRaster(mEnviroment.mRaster.get()); 85 } 86} 87 88uint32_t ScriptC::run(Context *rsc) { 89 if (mHal.info.root == NULL) { 90 rsc->setError(RS_ERROR_BAD_SCRIPT, "Attempted to run bad script"); 91 return 0; 92 } 93 94 setupGLState(rsc); 95 setupScript(rsc); 96 97 uint32_t ret = 0; 98 99 if (rsc->props.mLogScripts) { 100 LOGV("%p ScriptC::run invoking root, ptr %p", rsc, mHal.info.root); 101 } 102 103 ret = rsc->mHal.funcs.script.invokeRoot(rsc, this); 104 105 if (rsc->props.mLogScripts) { 106 LOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret); 107 } 108 109 return ret; 110} 111 112 113void ScriptC::runForEach(Context *rsc, 114 const Allocation * ain, 115 Allocation * aout, 116 const void * usr, 117 size_t usrBytes, 118 const RsScriptCall *sc) { 119 120 Context::PushState ps(rsc); 121 122 setupGLState(rsc); 123 setupScript(rsc); 124 rsc->mHal.funcs.script.invokeForEach(rsc, this, ain, aout, usr, usrBytes, sc); 125} 126 127void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, size_t len) { 128 if (slot >= mHal.info.exportedFunctionCount) { 129 rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script"); 130 return; 131 } 132 setupScript(rsc); 133 134 if (rsc->props.mLogScripts) { 135 LOGV("%p ScriptC::Invoke invoking slot %i, ptr %p", rsc, slot, this); 136 } 137 rsc->mHal.funcs.script.invokeFunction(rsc, this, slot, data, len); 138} 139 140ScriptCState::ScriptCState() { 141} 142 143ScriptCState::~ScriptCState() { 144} 145 146/* 147static void* symbolLookup(void* pContext, char const* name) { 148 const ScriptCState::SymbolTable_t *sym; 149 ScriptC *s = (ScriptC *)pContext; 150 if (!strcmp(name, "__isThreadable")) { 151 return (void*) s->mHal.info.isThreadable; 152 } else if (!strcmp(name, "__clearThreadable")) { 153 s->mHal.info.isThreadable = false; 154 return NULL; 155 } 156 sym = ScriptCState::lookupSymbol(name); 157 if (!sym) { 158 sym = ScriptCState::lookupSymbolCL(name); 159 } 160 if (!sym) { 161 sym = ScriptCState::lookupSymbolGL(name); 162 } 163 if (sym) { 164 s->mHal.info.isThreadable &= sym->threadable; 165 return sym->mPtr; 166 } 167 LOGE("ScriptC sym lookup failed for %s", name); 168 return NULL; 169} 170*/ 171 172#if 0 173extern const char rs_runtime_lib_bc[]; 174extern unsigned rs_runtime_lib_bc_size; 175#endif 176 177bool ScriptC::runCompiler(Context *rsc, 178 const char *resName, 179 const char *cacheDir, 180 const uint8_t *bitcode, 181 size_t bitcodeLen) { 182 183 //LOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen); 184 185 rsc->mHal.funcs.script.init(rsc, this, resName, cacheDir, bitcode, bitcodeLen, 0); 186 187 mEnviroment.mFragment.set(rsc->getDefaultProgramFragment()); 188 mEnviroment.mVertex.set(rsc->getDefaultProgramVertex()); 189 mEnviroment.mFragmentStore.set(rsc->getDefaultProgramStore()); 190 mEnviroment.mRaster.set(rsc->getDefaultProgramRaster()); 191 192 rsc->mHal.funcs.script.invokeInit(rsc, this); 193 194 for (size_t i=0; i < mHal.info.exportedPragmaCount; ++i) { 195 const char * key = mHal.info.exportedPragmaKeyList[i]; 196 const char * value = mHal.info.exportedPragmaValueList[i]; 197 //LOGE("pragma %s %s", keys[i], values[i]); 198 if (!strcmp(key, "version")) { 199 if (!strcmp(value, "1")) { 200 continue; 201 } 202 LOGE("Invalid version pragma value: %s\n", value); 203 return false; 204 } 205 206 if (!strcmp(key, "stateVertex")) { 207 if (!strcmp(value, "default")) { 208 continue; 209 } 210 if (!strcmp(value, "parent")) { 211 mEnviroment.mVertex.clear(); 212 continue; 213 } 214 LOGE("Unrecognized value %s passed to stateVertex", value); 215 return false; 216 } 217 218 if (!strcmp(key, "stateRaster")) { 219 if (!strcmp(value, "default")) { 220 continue; 221 } 222 if (!strcmp(value, "parent")) { 223 mEnviroment.mRaster.clear(); 224 continue; 225 } 226 LOGE("Unrecognized value %s passed to stateRaster", value); 227 return false; 228 } 229 230 if (!strcmp(key, "stateFragment")) { 231 if (!strcmp(value, "default")) { 232 continue; 233 } 234 if (!strcmp(value, "parent")) { 235 mEnviroment.mFragment.clear(); 236 continue; 237 } 238 LOGE("Unrecognized value %s passed to stateFragment", value); 239 return false; 240 } 241 242 if (!strcmp(key, "stateStore")) { 243 if (!strcmp(value, "default")) { 244 continue; 245 } 246 if (!strcmp(value, "parent")) { 247 mEnviroment.mFragmentStore.clear(); 248 continue; 249 } 250 LOGE("Unrecognized value %s passed to stateStore", value); 251 return false; 252 } 253 } 254 255 mSlots = new ObjectBaseRef<Allocation>[mHal.info.exportedVariableCount]; 256 mTypes = new ObjectBaseRef<const Type>[mHal.info.exportedVariableCount]; 257 258 return true; 259} 260 261namespace android { 262namespace renderscript { 263 264RsScript rsi_ScriptCCreate(Context *rsc, 265 const char *resName, size_t resName_length, 266 const char *cacheDir, size_t cacheDir_length, 267 const char *text, size_t text_length) 268{ 269 ScriptC *s = new ScriptC(rsc); 270 271 if (!s->runCompiler(rsc, resName, cacheDir, (uint8_t *)text, text_length)) { 272 // Error during compile, destroy s and return null. 273 delete s; 274 return NULL; 275 } 276 277 s->incUserRef(); 278 return s; 279} 280 281} 282} 283