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