rsScriptC_Lib.cpp revision fca82b1b10bb7d2f774cf6116f6424be05c75c67
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 21#include "utils/Timers.h" 22 23#include <time.h> 24 25using namespace android; 26using namespace android::renderscript; 27 28#define GET_TLS() Context::ScriptTLSStruct * tls = \ 29 (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \ 30 Context * rsc = tls->mContext; \ 31 ScriptC * sc = (ScriptC *) tls->mScript 32 33 34////////////////////////////////////////////////////////////////////////////// 35// Math routines 36////////////////////////////////////////////////////////////////////////////// 37 38static float SC_sinf_fast(float x) { 39 const float A = 1.0f / (2.0f * M_PI); 40 const float B = -16.0f; 41 const float C = 8.0f; 42 43 // scale angle for easy argument reduction 44 x *= A; 45 46 if (fabsf(x) >= 0.5f) { 47 // argument reduction 48 x = x - ceilf(x + 0.5f) + 1.0f; 49 } 50 51 const float y = B * x * fabsf(x) + C * x; 52 return 0.2215f * (y * fabsf(y) - y) + y; 53} 54 55static float SC_cosf_fast(float x) { 56 x += float(M_PI / 2); 57 58 const float A = 1.0f / (2.0f * M_PI); 59 const float B = -16.0f; 60 const float C = 8.0f; 61 62 // scale angle for easy argument reduction 63 x *= A; 64 65 if (fabsf(x) >= 0.5f) { 66 // argument reduction 67 x = x - ceilf(x + 0.5f) + 1.0f; 68 } 69 70 const float y = B * x * fabsf(x) + C * x; 71 return 0.2215f * (y * fabsf(y) - y) + y; 72} 73 74static float SC_randf(float max) { 75 float r = (float)rand(); 76 r *= max; 77 return r / RAND_MAX; 78} 79 80static float SC_randf2(float min, float max) { 81 float r = (float)rand(); 82 r = r * (max - min) + min; 83 return r / RAND_MAX; 84} 85 86static int SC_randi(int max) { 87 return (int)SC_randf(max); 88} 89 90static int SC_randi2(int min, int max) { 91 return (int)SC_randf2(min, max); 92} 93 94static float SC_frac(float v) { 95 int i = (int)floor(v); 96 return fmin(v - i, 0x1.fffffep-1f); 97} 98 99////////////////////////////////////////////////////////////////////////////// 100// Time routines 101////////////////////////////////////////////////////////////////////////////// 102 103static time_t SC_time(time_t *timer) { 104 GET_TLS(); 105 return time(timer); 106} 107 108static tm* SC_localtime(tm *local, time_t *timer) { 109 GET_TLS(); 110 if (!local) { 111 return NULL; 112 } 113 114 // The native localtime function is not thread-safe, so we 115 // have to apply locking for proper behavior in RenderScript. 116 pthread_mutex_lock(&rsc->gLibMutex); 117 tm *tmp = localtime(timer); 118 memcpy(local, tmp, sizeof(*tmp)); 119 pthread_mutex_unlock(&rsc->gLibMutex); 120 return local; 121} 122 123static int64_t SC_uptimeMillis() { 124 return nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC)); 125} 126 127static int64_t SC_uptimeNanos() { 128 return systemTime(SYSTEM_TIME_MONOTONIC); 129} 130 131static float SC_getDt() { 132 GET_TLS(); 133 int64_t l = sc->mEnviroment.mLastDtTime; 134 sc->mEnviroment.mLastDtTime = systemTime(SYSTEM_TIME_MONOTONIC); 135 return ((float)(sc->mEnviroment.mLastDtTime - l)) / 1.0e9; 136} 137 138////////////////////////////////////////////////////////////////////////////// 139// 140////////////////////////////////////////////////////////////////////////////// 141 142static uint32_t SC_allocGetDimX(RsAllocation va) { 143 const Allocation *a = static_cast<const Allocation *>(va); 144 CHECK_OBJ(a); 145 //LOGE("SC_allocGetDimX a=%p type=%p", a, a->getType()); 146 return a->getType()->getDimX(); 147} 148 149static uint32_t SC_allocGetDimY(RsAllocation va) { 150 const Allocation *a = static_cast<const Allocation *>(va); 151 CHECK_OBJ(a); 152 return a->getType()->getDimY(); 153} 154 155static uint32_t SC_allocGetDimZ(RsAllocation va) { 156 const Allocation *a = static_cast<const Allocation *>(va); 157 CHECK_OBJ(a); 158 return a->getType()->getDimZ(); 159} 160 161static uint32_t SC_allocGetDimLOD(RsAllocation va) { 162 const Allocation *a = static_cast<const Allocation *>(va); 163 CHECK_OBJ(a); 164 return a->getType()->getDimLOD(); 165} 166 167static uint32_t SC_allocGetDimFaces(RsAllocation va) { 168 const Allocation *a = static_cast<const Allocation *>(va); 169 CHECK_OBJ(a); 170 return a->getType()->getDimFaces(); 171} 172 173static const void * SC_getElementAtX(RsAllocation va, uint32_t x) { 174 const Allocation *a = static_cast<const Allocation *>(va); 175 CHECK_OBJ(a); 176 const Type *t = a->getType(); 177 CHECK_OBJ(t); 178 const uint8_t *p = (const uint8_t *)a->getPtr(); 179 return &p[t->getElementSizeBytes() * x]; 180} 181 182static const void * SC_getElementAtXY(RsAllocation va, uint32_t x, uint32_t y) { 183 const Allocation *a = static_cast<const Allocation *>(va); 184 CHECK_OBJ(a); 185 const Type *t = a->getType(); 186 CHECK_OBJ(t); 187 const uint8_t *p = (const uint8_t *)a->getPtr(); 188 return &p[t->getElementSizeBytes() * (x + y*t->getDimX())]; 189} 190 191static const void * SC_getElementAtXYZ(RsAllocation va, uint32_t x, uint32_t y, uint32_t z) { 192 const Allocation *a = static_cast<const Allocation *>(va); 193 CHECK_OBJ(a); 194 const Type *t = a->getType(); 195 CHECK_OBJ(t); 196 const uint8_t *p = (const uint8_t *)a->getPtr(); 197 return &p[t->getElementSizeBytes() * (x + y*t->getDimX())]; 198} 199 200static void SC_setObject(void **vdst, void * vsrc) { 201 //LOGE("SC_setObject %p,%p %p", vdst, *vdst, vsrc); 202 if (vsrc) { 203 CHECK_OBJ(vsrc); 204 static_cast<ObjectBase *>(vsrc)->incSysRef(); 205 } 206 if (vdst[0]) { 207 CHECK_OBJ(vdst[0]); 208 static_cast<ObjectBase *>(vdst[0])->decSysRef(); 209 } 210 *vdst = vsrc; 211 //LOGE("SC_setObject *"); 212} 213 214static void SC_clearObject(void **vdst) { 215 //LOGE("SC_clearObject %p,%p", vdst, *vdst); 216 if (vdst[0]) { 217 CHECK_OBJ(vdst[0]); 218 static_cast<ObjectBase *>(vdst[0])->decSysRef(); 219 } 220 *vdst = NULL; 221 //LOGE("SC_clearObject *"); 222} 223 224static bool SC_isObject(RsAllocation vsrc) { 225 return vsrc != NULL; 226} 227 228static void SC_debugF(const char *s, float f) { 229 LOGD("%s %f, 0x%08x", s, f, *((int *) (&f))); 230} 231static void SC_debugFv2(const char *s, float f1, float f2) { 232 LOGD("%s {%f, %f}", s, f1, f2); 233} 234static void SC_debugFv3(const char *s, float f1, float f2, float f3) { 235 LOGD("%s {%f, %f, %f}", s, f1, f2, f3); 236} 237static void SC_debugFv4(const char *s, float f1, float f2, float f3, float f4) { 238 LOGD("%s {%f, %f, %f, %f}", s, f1, f2, f3, f4); 239} 240static void SC_debugD(const char *s, double d) { 241 LOGD("%s %f, 0x%08llx", s, d, *((long long *) (&d))); 242} 243static void SC_debugFM4v4(const char *s, const float *f) { 244 LOGD("%s {%f, %f, %f, %f", s, f[0], f[4], f[8], f[12]); 245 LOGD("%s %f, %f, %f, %f", s, f[1], f[5], f[9], f[13]); 246 LOGD("%s %f, %f, %f, %f", s, f[2], f[6], f[10], f[14]); 247 LOGD("%s %f, %f, %f, %f}", s, f[3], f[7], f[11], f[15]); 248} 249static void SC_debugFM3v3(const char *s, const float *f) { 250 LOGD("%s {%f, %f, %f", s, f[0], f[3], f[6]); 251 LOGD("%s %f, %f, %f", s, f[1], f[4], f[7]); 252 LOGD("%s %f, %f, %f}",s, f[2], f[5], f[8]); 253} 254static void SC_debugFM2v2(const char *s, const float *f) { 255 LOGD("%s {%f, %f", s, f[0], f[2]); 256 LOGD("%s %f, %f}",s, f[1], f[3]); 257} 258 259static void SC_debugI32(const char *s, int32_t i) { 260 LOGD("%s %i 0x%x", s, i, i); 261} 262static void SC_debugU32(const char *s, uint32_t i) { 263 LOGD("%s %u 0x%x", s, i, i); 264} 265static void SC_debugLL64(const char *s, long long ll) { 266 LOGD("%s %lld 0x%llx", s, ll, ll); 267} 268static void SC_debugULL64(const char *s, unsigned long long ll) { 269 LOGD("%s %llu 0x%llx", s, ll, ll); 270} 271 272static void SC_debugP(const char *s, const void *p) { 273 LOGD("%s %p", s, p); 274} 275 276static uint32_t SC_toClient2(int cmdID, void *data, int len) { 277 GET_TLS(); 278 //LOGE("SC_toClient %i %i %i", cmdID, len); 279 return rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, cmdID, len, false); 280} 281 282static uint32_t SC_toClient(int cmdID) { 283 GET_TLS(); 284 //LOGE("SC_toClient %i", cmdID); 285 return rsc->sendMessageToClient(NULL, RS_MESSAGE_TO_CLIENT_USER, cmdID, 0, false); 286} 287 288static uint32_t SC_toClientBlocking2(int cmdID, void *data, int len) { 289 GET_TLS(); 290 //LOGE("SC_toClientBlocking %i %i", cmdID, len); 291 return rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, cmdID, len, true); 292} 293 294static uint32_t SC_toClientBlocking(int cmdID) { 295 GET_TLS(); 296 //LOGE("SC_toClientBlocking %i", cmdID); 297 return rsc->sendMessageToClient(NULL, RS_MESSAGE_TO_CLIENT_USER, cmdID, 0, true); 298} 299 300int SC_divsi3(int a, int b) { 301 return a / b; 302} 303 304int SC_modsi3(int a, int b) { 305 return a % b; 306} 307 308int SC_getAllocation(const void *ptr) { 309 GET_TLS(); 310 const Allocation *alloc = sc->ptrToAllocation(ptr); 311 return (int)alloc; 312} 313 314void SC_allocationMarkDirty(RsAllocation a) { 315 Allocation *alloc = static_cast<Allocation *>(a); 316 alloc->sendDirty(); 317} 318 319void SC_ForEach(RsScript vs, 320 RsAllocation vin, 321 RsAllocation vout, 322 const void *usr) { 323 GET_TLS(); 324 const Allocation *ain = static_cast<const Allocation *>(vin); 325 Allocation *aout = static_cast<Allocation *>(vout); 326 Script *s = static_cast<Script *>(vs); 327 s->runForEach(rsc, ain, aout, usr); 328} 329 330void SC_ForEach2(RsScript vs, 331 RsAllocation vin, 332 RsAllocation vout, 333 const void *usr, 334 const RsScriptCall *call) { 335 GET_TLS(); 336 const Allocation *ain = static_cast<const Allocation *>(vin); 337 Allocation *aout = static_cast<Allocation *>(vout); 338 Script *s = static_cast<Script *>(vs); 339 s->runForEach(rsc, ain, aout, usr, call); 340} 341 342////////////////////////////////////////////////////////////////////////////// 343// Class implementation 344////////////////////////////////////////////////////////////////////////////// 345 346// llvm name mangling ref 347// <builtin-type> ::= v # void 348// ::= b # bool 349// ::= c # char 350// ::= a # signed char 351// ::= h # unsigned char 352// ::= s # short 353// ::= t # unsigned short 354// ::= i # int 355// ::= j # unsigned int 356// ::= l # long 357// ::= m # unsigned long 358// ::= x # long long, __int64 359// ::= y # unsigned long long, __int64 360// ::= f # float 361// ::= d # double 362 363static ScriptCState::SymbolTable_t gSyms[] = { 364 { "__divsi3", (void *)&SC_divsi3, true }, 365 { "__modsi3", (void *)&SC_modsi3, true }, 366 367 // allocation 368 { "_Z19rsAllocationGetDimX13rs_allocation", (void *)&SC_allocGetDimX, true }, 369 { "_Z19rsAllocationGetDimY13rs_allocation", (void *)&SC_allocGetDimY, true }, 370 { "_Z19rsAllocationGetDimZ13rs_allocation", (void *)&SC_allocGetDimZ, true }, 371 { "_Z21rsAllocationGetDimLOD13rs_allocation", (void *)&SC_allocGetDimLOD, true }, 372 { "_Z23rsAllocationGetDimFaces13rs_allocation", (void *)&SC_allocGetDimFaces, true }, 373 { "_Z15rsGetAllocationPKv", (void *)&SC_getAllocation, true }, 374 375 { "_Z14rsGetElementAt13rs_allocationj", (void *)&SC_getElementAtX, true }, 376 { "_Z14rsGetElementAt13rs_allocationjj", (void *)&SC_getElementAtXY, true }, 377 { "_Z14rsGetElementAt13rs_allocationjjj", (void *)&SC_getElementAtXYZ, true }, 378 379 { "_Z11rsSetObjectP10rs_elementS_", (void *)&SC_setObject, true }, 380 { "_Z13rsClearObjectP10rs_element", (void *)&SC_clearObject, true }, 381 { "_Z10rsIsObject10rs_element", (void *)&SC_isObject, true }, 382 383 { "_Z11rsSetObjectP7rs_typeS_", (void *)&SC_setObject, true }, 384 { "_Z13rsClearObjectP7rs_type", (void *)&SC_clearObject, true }, 385 { "_Z10rsIsObject7rs_type", (void *)&SC_isObject, true }, 386 387 { "_Z11rsSetObjectP13rs_allocationS_", (void *)&SC_setObject, true }, 388 { "_Z13rsClearObjectP13rs_allocation", (void *)&SC_clearObject, true }, 389 { "_Z10rsIsObject13rs_allocation", (void *)&SC_isObject, true }, 390 391 { "_Z11rsSetObjectP10rs_samplerS_", (void *)&SC_setObject, true }, 392 { "_Z13rsClearObjectP10rs_sampler", (void *)&SC_clearObject, true }, 393 { "_Z10rsIsObject10rs_sampler", (void *)&SC_isObject, true }, 394 395 { "_Z11rsSetObjectP9rs_scriptS_", (void *)&SC_setObject, true }, 396 { "_Z13rsClearObjectP9rs_script", (void *)&SC_clearObject, true }, 397 { "_Z10rsIsObject9rs_script", (void *)&SC_isObject, true }, 398 399 { "_Z11rsSetObjectP7rs_meshS_", (void *)&SC_setObject, true }, 400 { "_Z13rsClearObjectP7rs_mesh", (void *)&SC_clearObject, true }, 401 { "_Z10rsIsObject7rs_mesh", (void *)&SC_isObject, true }, 402 403 { "_Z11rsSetObjectP19rs_program_fragmentS_", (void *)&SC_setObject, true }, 404 { "_Z13rsClearObjectP19rs_program_fragment", (void *)&SC_clearObject, true }, 405 { "_Z10rsIsObject19rs_program_fragment", (void *)&SC_isObject, true }, 406 407 { "_Z11rsSetObjectP17rs_program_vertexS_", (void *)&SC_setObject, true }, 408 { "_Z13rsClearObjectP17rs_program_vertex", (void *)&SC_clearObject, true }, 409 { "_Z10rsIsObject17rs_program_vertex", (void *)&SC_isObject, true }, 410 411 { "_Z11rsSetObjectP17rs_program_rasterS_", (void *)&SC_setObject, true }, 412 { "_Z13rsClearObjectP17rs_program_raster", (void *)&SC_clearObject, true }, 413 { "_Z10rsIsObject17rs_program_raster", (void *)&SC_isObject, true }, 414 415 { "_Z11rsSetObjectP16rs_program_storeS_", (void *)&SC_setObject, true }, 416 { "_Z13rsClearObjectP16rs_program_store", (void *)&SC_clearObject, true }, 417 { "_Z10rsIsObject16rs_program_store", (void *)&SC_isObject, true }, 418 419 { "_Z11rsSetObjectP7rs_fontS_", (void *)&SC_setObject, true }, 420 { "_Z13rsClearObjectP7rs_font", (void *)&SC_clearObject, true }, 421 { "_Z10rsIsObject7rs_font", (void *)&SC_isObject, true }, 422 423 424 { "_Z21rsAllocationMarkDirty13rs_allocation", (void *)&SC_allocationMarkDirty, true }, 425 426 427 // Debug 428 { "_Z7rsDebugPKcf", (void *)&SC_debugF, true }, 429 { "_Z7rsDebugPKcff", (void *)&SC_debugFv2, true }, 430 { "_Z7rsDebugPKcfff", (void *)&SC_debugFv3, true }, 431 { "_Z7rsDebugPKcffff", (void *)&SC_debugFv4, true }, 432 { "_Z7rsDebugPKcd", (void *)&SC_debugD, true }, 433 { "_Z7rsDebugPKcPK12rs_matrix4x4", (void *)&SC_debugFM4v4, true }, 434 { "_Z7rsDebugPKcPK12rs_matrix3x3", (void *)&SC_debugFM3v3, true }, 435 { "_Z7rsDebugPKcPK12rs_matrix2x2", (void *)&SC_debugFM2v2, true }, 436 { "_Z7rsDebugPKci", (void *)&SC_debugI32, true }, 437 { "_Z7rsDebugPKcj", (void *)&SC_debugU32, true }, 438 // Both "long" and "unsigned long" need to be redirected to their 439 // 64-bit counterparts, since we have hacked Slang to use 64-bit 440 // for "long" on Arm (to be similar to Java). 441 { "_Z7rsDebugPKcl", (void *)&SC_debugLL64, true }, 442 { "_Z7rsDebugPKcm", (void *)&SC_debugULL64, true }, 443 { "_Z7rsDebugPKcx", (void *)&SC_debugLL64, true }, 444 { "_Z7rsDebugPKcy", (void *)&SC_debugULL64, true }, 445 { "_Z7rsDebugPKcPKv", (void *)&SC_debugP, true }, 446 447 // RS Math 448 { "_Z6rsRandi", (void *)&SC_randi, true }, 449 { "_Z6rsRandii", (void *)&SC_randi2, true }, 450 { "_Z6rsRandf", (void *)&SC_randf, true }, 451 { "_Z6rsRandff", (void *)&SC_randf2, true }, 452 { "_Z6rsFracf", (void *)&SC_frac, true }, 453 454 // time 455 { "_Z6rsTimePi", (void *)&SC_time, true }, 456 { "_Z11rsLocaltimeP5rs_tmPKi", (void *)&SC_localtime, true }, 457 { "_Z14rsUptimeMillisv", (void*)&SC_uptimeMillis, true }, 458 { "_Z13rsUptimeNanosv", (void*)&SC_uptimeNanos, true }, 459 { "_Z7rsGetDtv", (void*)&SC_getDt, false }, 460 461 { "_Z14rsSendToClienti", (void *)&SC_toClient, false }, 462 { "_Z14rsSendToClientiPKvj", (void *)&SC_toClient2, false }, 463 { "_Z22rsSendToClientBlockingi", (void *)&SC_toClientBlocking, false }, 464 { "_Z22rsSendToClientBlockingiPKvj", (void *)&SC_toClientBlocking2, false }, 465 466 { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach, false }, 467 //{ "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach2, true }, 468 469//////////////////////////////////////////////////////////////////// 470 471 //{ "sinf_fast", (void *)&SC_sinf_fast, true }, 472 //{ "cosf_fast", (void *)&SC_cosf_fast, true }, 473 474 { NULL, NULL, false } 475}; 476 477const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbol(const char *sym) { 478 ScriptCState::SymbolTable_t *syms = gSyms; 479 480 while (syms->mPtr) { 481 if (!strcmp(syms->mName, sym)) { 482 return syms; 483 } 484 syms++; 485 } 486 return NULL; 487} 488