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