rsdBcc.cpp revision bad807405b2b9764372af1ad24bcfd4fb1f33d8e
1/* 2 * Copyright (C) 2011 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 18#include "rsdCore.h" 19#include "rsdBcc.h" 20 21#include "rsContext.h" 22#include "rsScriptC.h" 23 24#include "utils/Timers.h" 25#include "utils/StopWatch.h" 26extern "C" { 27#include "libdex/ZipArchive.h" 28} 29 30 31using namespace android; 32using namespace android::renderscript; 33 34struct DrvScript { 35 int (*mRoot)(); 36 void (*mInit)(); 37 38 BCCScriptRef mBccScript; 39 40 uint32_t mInvokeFunctionCount; 41 InvokeFunc_t *mInvokeFunctions; 42 uint32_t mFieldCount; 43 void ** mFieldAddress; 44 bool * mFieldIsObject; 45 46 const uint8_t * mScriptText; 47 uint32_t mScriptTextLength; 48 49 //uint32_t * mObjectSlots; 50 //uint32_t mObjectSlotCount; 51 52 uint32_t mPragmaCount; 53 const char ** mPragmaKeys; 54 const char ** mPragmaValues; 55 56}; 57 58// Input: cacheDir 59// Input: resName 60// Input: extName 61// 62// Note: cacheFile = resName + extName 63// 64// Output: Returns cachePath == cacheDir + cacheFile 65static char *genCacheFileName(const char *cacheDir, 66 const char *resName, 67 const char *extName) { 68 char cachePath[512]; 69 char cacheFile[sizeof(cachePath)]; 70 const size_t kBufLen = sizeof(cachePath) - 1; 71 72 cacheFile[0] = '\0'; 73 // Note: resName today is usually something like 74 // "/com.android.fountain:raw/fountain" 75 if (resName[0] != '/') { 76 // Get the absolute path of the raw/***.bc file. 77 78 // Generate the absolute path. This doesn't do everything it 79 // should, e.g. if resName is "./out/whatever" it doesn't crunch 80 // the leading "./" out because this if-block is not triggered, 81 // but it'll make do. 82 // 83 if (getcwd(cacheFile, kBufLen) == NULL) { 84 LOGE("Can't get CWD while opening raw/***.bc file\n"); 85 return NULL; 86 } 87 // Append "/" at the end of cacheFile so far. 88 strncat(cacheFile, "/", kBufLen); 89 } 90 91 // cacheFile = resName + extName 92 // 93 strncat(cacheFile, resName, kBufLen); 94 if (extName != NULL) { 95 // TODO(srhines): strncat() is a bit dangerous 96 strncat(cacheFile, extName, kBufLen); 97 } 98 99 // Turn the path into a flat filename by replacing 100 // any slashes after the first one with '@' characters. 101 char *cp = cacheFile + 1; 102 while (*cp != '\0') { 103 if (*cp == '/') { 104 *cp = '@'; 105 } 106 cp++; 107 } 108 109 // Tack on the file name for the actual cache file path. 110 strncpy(cachePath, cacheDir, kBufLen); 111 strncat(cachePath, cacheFile, kBufLen); 112 113 LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath); 114 return strdup(cachePath); 115} 116 117bool rsdScriptInit(const Context *rsc, 118 ScriptC *script, 119 char const *resName, 120 char const *cacheDir, 121 uint8_t const *bitcode, 122 size_t bitcodeSize, 123 uint32_t flags, 124 RsHalSymbolLookupFunc lookupFunc) { 125 //LOGE("rsdScriptCreate %p %p %p %p %i %i %p", rsc, resName, cacheDir, bitcode, bitcodeSize, flags, lookupFunc); 126 127 char *cachePath = NULL; 128 uint32_t objectSlotCount = 0; 129 130 DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript)); 131 if (drv == NULL) { 132 return false; 133 } 134 script->mHal.drv = drv; 135 136 drv->mBccScript = bccCreateScript(); 137 script->mHal.info.isThreadable = true; 138 drv->mScriptText = bitcode; 139 drv->mScriptTextLength = bitcodeSize; 140 141 //LOGE("mBccScript %p", script->mBccScript); 142 143 if (bccRegisterSymbolCallback(drv->mBccScript, lookupFunc, script) != 0) { 144 LOGE("bcc: FAILS to register symbol callback"); 145 goto error; 146 } 147 148 if (bccReadBC(drv->mBccScript, 149 resName, 150 (char const *)drv->mScriptText, 151 drv->mScriptTextLength, 0) != 0) { 152 LOGE("bcc: FAILS to read bitcode"); 153 return NULL; 154 } 155 156#if 1 157 if (bccLinkFile(drv->mBccScript, "/system/lib/libclcore.bc", 0) != 0) { 158 LOGE("bcc: FAILS to link bitcode"); 159 return NULL; 160 } 161#endif 162 cachePath = genCacheFileName(cacheDir, resName, ".oBCC"); 163 164 if (bccPrepareExecutable(drv->mBccScript, cachePath, 0) != 0) { 165 LOGE("bcc: FAILS to prepare executable"); 166 return NULL; 167 } 168 169 free(cachePath); 170 171 drv->mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(drv->mBccScript, "root")); 172 drv->mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(drv->mBccScript, "init")); 173 174 drv->mInvokeFunctionCount = bccGetExportFuncCount(drv->mBccScript); 175 if (drv->mInvokeFunctionCount <= 0) 176 drv->mInvokeFunctions = NULL; 177 else { 178 drv->mInvokeFunctions = (InvokeFunc_t*) calloc(drv->mInvokeFunctionCount, sizeof(InvokeFunc_t)); 179 bccGetExportFuncList(drv->mBccScript, drv->mInvokeFunctionCount, (void **) drv->mInvokeFunctions); 180 } 181 182 drv->mFieldCount = bccGetExportVarCount(drv->mBccScript); 183 if (drv->mFieldCount <= 0) { 184 drv->mFieldAddress = NULL; 185 drv->mFieldIsObject = NULL; 186 } else { 187 drv->mFieldAddress = (void **) calloc(drv->mFieldCount, sizeof(void *)); 188 drv->mFieldIsObject = (bool *) calloc(drv->mFieldCount, sizeof(bool)); 189 bccGetExportVarList(drv->mBccScript, drv->mFieldCount, (void **) drv->mFieldAddress); 190 } 191 192 objectSlotCount = bccGetObjectSlotCount(drv->mBccScript); 193 if (objectSlotCount) { 194 uint32_t * slots = new uint32_t[objectSlotCount]; 195 bccGetObjectSlotList(drv->mBccScript, objectSlotCount, slots); 196 for (uint32_t ct=0; ct < objectSlotCount; ct++) { 197 drv->mFieldIsObject[slots[ct]] = true; 198 } 199 delete [] slots; 200 } 201 202 uint32_t mPragmaCount; 203 const char ** mPragmaKeys; 204 const char ** mPragmaValues; 205 206 const static int pragmaMax = 16; 207 drv->mPragmaCount = bccGetPragmaCount(drv->mBccScript); 208 if (drv->mPragmaCount <= 0) { 209 drv->mPragmaKeys = NULL; 210 drv->mPragmaValues = NULL; 211 } else { 212 drv->mPragmaKeys = (const char **) calloc(drv->mFieldCount, sizeof(const char *)); 213 drv->mPragmaValues = (const char **) calloc(drv->mFieldCount, sizeof(const char *)); 214 bccGetPragmaList(drv->mBccScript, drv->mPragmaCount, drv->mPragmaKeys, drv->mPragmaValues); 215 } 216 217 218 219 // Copy info over to runtime 220 script->mHal.info.exportedFunctionCount = drv->mInvokeFunctionCount; 221 script->mHal.info.exportedVariableCount = drv->mFieldCount; 222 script->mHal.info.exportedPragmaCount = drv->mPragmaCount; 223 script->mHal.info.exportedPragmaKeyList = drv->mPragmaKeys; 224 script->mHal.info.exportedPragmaValueList = drv->mPragmaValues; 225 script->mHal.info.root = drv->mRoot; 226 227 228 return true; 229 230error: 231 232 free(drv); 233 return false; 234 235} 236 237 238int rsdScriptInvokeRoot(const Context *dc, const Script *script) { 239 DrvScript *drv = (DrvScript *)script->mHal.drv; 240 return drv->mRoot(); 241} 242 243void rsdScriptInvokeInit(const Context *dc, const Script *script) { 244 DrvScript *drv = (DrvScript *)script->mHal.drv; 245 246 if (drv->mInit) { 247 drv->mInit(); 248 } 249} 250 251 252void rsdScriptInvokeFunction(const Context *dc, const Script *script, 253 uint32_t slot, 254 const void *params, 255 size_t paramLength) { 256 DrvScript *drv = (DrvScript *)script->mHal.drv; 257 //LOGE("invoke %p %p %i %p %i", dc, script, slot, params, paramLength); 258 259 ((void (*)(const void *, uint32_t)) 260 drv->mInvokeFunctions[slot])(params, paramLength); 261} 262 263void rsdScriptSetGlobalVar(const Context *dc, const Script *script, 264 uint32_t slot, void *data, size_t dataLength) { 265 DrvScript *drv = (DrvScript *)script->mHal.drv; 266 //rsAssert(!script->mFieldIsObject[slot]); 267 //LOGE("setGlobalVar %p %p %i %p %i", dc, script, slot, data, dataLength); 268 269 int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot]; 270 if (!destPtr) { 271 //LOGV("Calling setVar on slot = %i which is null", slot); 272 return; 273 } 274 275 memcpy(destPtr, data, dataLength); 276} 277 278void rsdScriptSetGlobalBind(const Context *dc, const Script *script, uint32_t slot, void *data) { 279 DrvScript *drv = (DrvScript *)script->mHal.drv; 280 //rsAssert(!script->mFieldIsObject[slot]); 281 //LOGE("setGlobalBind %p %p %i %p", dc, script, slot, data); 282 283 int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot]; 284 if (!destPtr) { 285 //LOGV("Calling setVar on slot = %i which is null", slot); 286 return; 287 } 288 289 memcpy(destPtr, &data, sizeof(void *)); 290} 291 292void rsdScriptSetGlobalObj(const Context *dc, const Script *script, uint32_t slot, ObjectBase *data) { 293 DrvScript *drv = (DrvScript *)script->mHal.drv; 294 //rsAssert(script->mFieldIsObject[slot]); 295 //LOGE("setGlobalObj %p %p %i %p", dc, script, slot, data); 296 297 int32_t *destPtr = ((int32_t **)drv->mFieldAddress)[slot]; 298 if (!destPtr) { 299 //LOGV("Calling setVar on slot = %i which is null", slot); 300 return; 301 } 302 303 rsiSetObject((ObjectBase **)destPtr, data); 304} 305 306void rsdScriptDestroy(const Context *dc, Script *script) { 307 DrvScript *drv = (DrvScript *)script->mHal.drv; 308 309 if (drv->mFieldAddress) { 310 for (size_t ct=0; ct < drv->mFieldCount; ct++) { 311 if (drv->mFieldIsObject[ct]) { 312 rsiClearObject((ObjectBase **)&drv->mFieldAddress[ct]); 313 } 314 } 315 delete [] drv->mFieldAddress; 316 delete [] drv->mFieldIsObject; 317 drv->mFieldAddress = NULL; 318 drv->mFieldIsObject = NULL; 319 drv->mFieldCount = 0; 320 } 321 322 if (drv->mInvokeFunctions) { 323 delete [] drv->mInvokeFunctions; 324 drv->mInvokeFunctions = NULL; 325 drv->mInvokeFunctionCount = 0; 326 } 327 free(drv); 328 script->mHal.drv = NULL; 329 330} 331 332 333