| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "rsContext.h" |
| #include "rsScriptC.h" |
| #include "rsMatrix.h" |
| |
| #include "utils/Timers.h" |
| |
| #include <time.h> |
| |
| using namespace android; |
| using namespace android::renderscript; |
| |
| #define GET_TLS() Context::ScriptTLSStruct * tls = \ |
| (Context::ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \ |
| Context * rsc = tls->mContext; \ |
| ScriptC * sc = (ScriptC *) tls->mScript |
| |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // Math routines |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| static float SC_sinf_fast(float x) { |
| const float A = 1.0f / (2.0f * M_PI); |
| const float B = -16.0f; |
| const float C = 8.0f; |
| |
| // scale angle for easy argument reduction |
| x *= A; |
| |
| if (fabsf(x) >= 0.5f) { |
| // argument reduction |
| x = x - ceilf(x + 0.5f) + 1.0f; |
| } |
| |
| const float y = B * x * fabsf(x) + C * x; |
| return 0.2215f * (y * fabsf(y) - y) + y; |
| } |
| |
| static float SC_cosf_fast(float x) { |
| x += float(M_PI / 2); |
| |
| const float A = 1.0f / (2.0f * M_PI); |
| const float B = -16.0f; |
| const float C = 8.0f; |
| |
| // scale angle for easy argument reduction |
| x *= A; |
| |
| if (fabsf(x) >= 0.5f) { |
| // argument reduction |
| x = x - ceilf(x + 0.5f) + 1.0f; |
| } |
| |
| const float y = B * x * fabsf(x) + C * x; |
| return 0.2215f * (y * fabsf(y) - y) + y; |
| } |
| |
| static float SC_randf(float max) { |
| float r = (float)rand(); |
| r *= max; |
| return r / RAND_MAX; |
| } |
| |
| static float SC_randf2(float min, float max) { |
| float r = (float)rand(); |
| r = r * (max - min) + min; |
| return r / RAND_MAX; |
| } |
| |
| static int SC_randi(int max) { |
| return (int)SC_randf(max); |
| } |
| |
| static int SC_randi2(int min, int max) { |
| return (int)SC_randf2(min, max); |
| } |
| |
| static float SC_frac(float v) { |
| int i = (int)floor(v); |
| return fmin(v - i, 0x1.fffffep-1f); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // Time routines |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| static time_t SC_time(time_t *timer) { |
| GET_TLS(); |
| return time(timer); |
| } |
| |
| static tm* SC_localtime(tm *local, time_t *timer) { |
| GET_TLS(); |
| if (!local) { |
| return NULL; |
| } |
| |
| // The native localtime function is not thread-safe, so we |
| // have to apply locking for proper behavior in RenderScript. |
| pthread_mutex_lock(&rsc->gLibMutex); |
| tm *tmp = localtime(timer); |
| memcpy(local, tmp, sizeof(*tmp)); |
| pthread_mutex_unlock(&rsc->gLibMutex); |
| return local; |
| } |
| |
| static int64_t SC_uptimeMillis() { |
| return nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC)); |
| } |
| |
| static int64_t SC_uptimeNanos() { |
| return systemTime(SYSTEM_TIME_MONOTONIC); |
| } |
| |
| static float SC_getDt() { |
| GET_TLS(); |
| int64_t l = sc->mEnviroment.mLastDtTime; |
| sc->mEnviroment.mLastDtTime = systemTime(SYSTEM_TIME_MONOTONIC); |
| return ((float)(sc->mEnviroment.mLastDtTime - l)) / 1.0e9; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| static uint32_t SC_allocGetDimX(RsAllocation va) { |
| const Allocation *a = static_cast<const Allocation *>(va); |
| CHECK_OBJ(a); |
| //LOGE("SC_allocGetDimX a=%p type=%p", a, a->getType()); |
| return a->getType()->getDimX(); |
| } |
| |
| static uint32_t SC_allocGetDimY(RsAllocation va) { |
| const Allocation *a = static_cast<const Allocation *>(va); |
| CHECK_OBJ(a); |
| return a->getType()->getDimY(); |
| } |
| |
| static uint32_t SC_allocGetDimZ(RsAllocation va) { |
| const Allocation *a = static_cast<const Allocation *>(va); |
| CHECK_OBJ(a); |
| return a->getType()->getDimZ(); |
| } |
| |
| static uint32_t SC_allocGetDimLOD(RsAllocation va) { |
| const Allocation *a = static_cast<const Allocation *>(va); |
| CHECK_OBJ(a); |
| return a->getType()->getDimLOD(); |
| } |
| |
| static uint32_t SC_allocGetDimFaces(RsAllocation va) { |
| const Allocation *a = static_cast<const Allocation *>(va); |
| CHECK_OBJ(a); |
| return a->getType()->getDimFaces(); |
| } |
| |
| static const void * SC_getElementAtX(RsAllocation va, uint32_t x) { |
| const Allocation *a = static_cast<const Allocation *>(va); |
| CHECK_OBJ(a); |
| const Type *t = a->getType(); |
| CHECK_OBJ(t); |
| const uint8_t *p = (const uint8_t *)a->getPtr(); |
| return &p[t->getElementSizeBytes() * x]; |
| } |
| |
| static const void * SC_getElementAtXY(RsAllocation va, uint32_t x, uint32_t y) { |
| const Allocation *a = static_cast<const Allocation *>(va); |
| CHECK_OBJ(a); |
| const Type *t = a->getType(); |
| CHECK_OBJ(t); |
| const uint8_t *p = (const uint8_t *)a->getPtr(); |
| return &p[t->getElementSizeBytes() * (x + y*t->getDimX())]; |
| } |
| |
| static const void * SC_getElementAtXYZ(RsAllocation va, uint32_t x, uint32_t y, uint32_t z) { |
| const Allocation *a = static_cast<const Allocation *>(va); |
| CHECK_OBJ(a); |
| const Type *t = a->getType(); |
| CHECK_OBJ(t); |
| const uint8_t *p = (const uint8_t *)a->getPtr(); |
| return &p[t->getElementSizeBytes() * (x + y*t->getDimX())]; |
| } |
| |
| static void SC_setObject(void **vdst, void * vsrc) { |
| //LOGE("SC_setObject %p,%p %p", vdst, *vdst, vsrc); |
| if (vsrc) { |
| CHECK_OBJ(vsrc); |
| static_cast<ObjectBase *>(vsrc)->incSysRef(); |
| } |
| if (vdst[0]) { |
| CHECK_OBJ(vdst[0]); |
| static_cast<ObjectBase *>(vdst[0])->decSysRef(); |
| } |
| *vdst = vsrc; |
| //LOGE("SC_setObject *"); |
| } |
| |
| static void SC_clearObject(void **vdst) { |
| //LOGE("SC_clearObject %p,%p", vdst, *vdst); |
| if (vdst[0]) { |
| CHECK_OBJ(vdst[0]); |
| static_cast<ObjectBase *>(vdst[0])->decSysRef(); |
| } |
| *vdst = NULL; |
| //LOGE("SC_clearObject *"); |
| } |
| |
| static bool SC_isObject(RsAllocation vsrc) { |
| return vsrc != NULL; |
| } |
| |
| static void SC_debugF(const char *s, float f) { |
| LOGD("%s %f, 0x%08x", s, f, *((int *) (&f))); |
| } |
| static void SC_debugFv2(const char *s, float f1, float f2) { |
| LOGD("%s {%f, %f}", s, f1, f2); |
| } |
| static void SC_debugFv3(const char *s, float f1, float f2, float f3) { |
| LOGD("%s {%f, %f, %f}", s, f1, f2, f3); |
| } |
| static void SC_debugFv4(const char *s, float f1, float f2, float f3, float f4) { |
| LOGD("%s {%f, %f, %f, %f}", s, f1, f2, f3, f4); |
| } |
| static void SC_debugD(const char *s, double d) { |
| LOGD("%s %f, 0x%08llx", s, d, *((long long *) (&d))); |
| } |
| static void SC_debugFM4v4(const char *s, const float *f) { |
| LOGD("%s {%f, %f, %f, %f", s, f[0], f[4], f[8], f[12]); |
| LOGD("%s %f, %f, %f, %f", s, f[1], f[5], f[9], f[13]); |
| LOGD("%s %f, %f, %f, %f", s, f[2], f[6], f[10], f[14]); |
| LOGD("%s %f, %f, %f, %f}", s, f[3], f[7], f[11], f[15]); |
| } |
| static void SC_debugFM3v3(const char *s, const float *f) { |
| LOGD("%s {%f, %f, %f", s, f[0], f[3], f[6]); |
| LOGD("%s %f, %f, %f", s, f[1], f[4], f[7]); |
| LOGD("%s %f, %f, %f}",s, f[2], f[5], f[8]); |
| } |
| static void SC_debugFM2v2(const char *s, const float *f) { |
| LOGD("%s {%f, %f", s, f[0], f[2]); |
| LOGD("%s %f, %f}",s, f[1], f[3]); |
| } |
| |
| static void SC_debugI32(const char *s, int32_t i) { |
| LOGD("%s %i 0x%x", s, i, i); |
| } |
| static void SC_debugU32(const char *s, uint32_t i) { |
| LOGD("%s %u 0x%x", s, i, i); |
| } |
| static void SC_debugLL64(const char *s, long long ll) { |
| LOGD("%s %lld 0x%llx", s, ll, ll); |
| } |
| static void SC_debugULL64(const char *s, unsigned long long ll) { |
| LOGD("%s %llu 0x%llx", s, ll, ll); |
| } |
| |
| static void SC_debugP(const char *s, const void *p) { |
| LOGD("%s %p", s, p); |
| } |
| |
| static uint32_t SC_toClient2(int cmdID, void *data, int len) { |
| GET_TLS(); |
| //LOGE("SC_toClient %i %i %i", cmdID, len); |
| return rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, cmdID, len, false); |
| } |
| |
| static uint32_t SC_toClient(int cmdID) { |
| GET_TLS(); |
| //LOGE("SC_toClient %i", cmdID); |
| return rsc->sendMessageToClient(NULL, RS_MESSAGE_TO_CLIENT_USER, cmdID, 0, false); |
| } |
| |
| static uint32_t SC_toClientBlocking2(int cmdID, void *data, int len) { |
| GET_TLS(); |
| //LOGE("SC_toClientBlocking %i %i", cmdID, len); |
| return rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, cmdID, len, true); |
| } |
| |
| static uint32_t SC_toClientBlocking(int cmdID) { |
| GET_TLS(); |
| //LOGE("SC_toClientBlocking %i", cmdID); |
| return rsc->sendMessageToClient(NULL, RS_MESSAGE_TO_CLIENT_USER, cmdID, 0, true); |
| } |
| |
| int SC_divsi3(int a, int b) { |
| return a / b; |
| } |
| |
| int SC_modsi3(int a, int b) { |
| return a % b; |
| } |
| |
| int SC_getAllocation(const void *ptr) { |
| GET_TLS(); |
| const Allocation *alloc = sc->ptrToAllocation(ptr); |
| return (int)alloc; |
| } |
| |
| void SC_allocationMarkDirty(RsAllocation a) { |
| Allocation *alloc = static_cast<Allocation *>(a); |
| alloc->sendDirty(); |
| } |
| |
| void SC_ForEach(RsScript vs, |
| RsAllocation vin, |
| RsAllocation vout, |
| const void *usr) { |
| GET_TLS(); |
| const Allocation *ain = static_cast<const Allocation *>(vin); |
| Allocation *aout = static_cast<Allocation *>(vout); |
| Script *s = static_cast<Script *>(vs); |
| s->runForEach(rsc, ain, aout, usr); |
| } |
| |
| void SC_ForEach2(RsScript vs, |
| RsAllocation vin, |
| RsAllocation vout, |
| const void *usr, |
| const RsScriptCall *call) { |
| GET_TLS(); |
| const Allocation *ain = static_cast<const Allocation *>(vin); |
| Allocation *aout = static_cast<Allocation *>(vout); |
| Script *s = static_cast<Script *>(vs); |
| s->runForEach(rsc, ain, aout, usr, call); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // Class implementation |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| // llvm name mangling ref |
| // <builtin-type> ::= v # void |
| // ::= b # bool |
| // ::= c # char |
| // ::= a # signed char |
| // ::= h # unsigned char |
| // ::= s # short |
| // ::= t # unsigned short |
| // ::= i # int |
| // ::= j # unsigned int |
| // ::= l # long |
| // ::= m # unsigned long |
| // ::= x # long long, __int64 |
| // ::= y # unsigned long long, __int64 |
| // ::= f # float |
| // ::= d # double |
| |
| static ScriptCState::SymbolTable_t gSyms[] = { |
| { "__divsi3", (void *)&SC_divsi3, true }, |
| { "__modsi3", (void *)&SC_modsi3, true }, |
| |
| // allocation |
| { "_Z19rsAllocationGetDimX13rs_allocation", (void *)&SC_allocGetDimX, true }, |
| { "_Z19rsAllocationGetDimY13rs_allocation", (void *)&SC_allocGetDimY, true }, |
| { "_Z19rsAllocationGetDimZ13rs_allocation", (void *)&SC_allocGetDimZ, true }, |
| { "_Z21rsAllocationGetDimLOD13rs_allocation", (void *)&SC_allocGetDimLOD, true }, |
| { "_Z23rsAllocationGetDimFaces13rs_allocation", (void *)&SC_allocGetDimFaces, true }, |
| { "_Z15rsGetAllocationPKv", (void *)&SC_getAllocation, true }, |
| |
| { "_Z14rsGetElementAt13rs_allocationj", (void *)&SC_getElementAtX, true }, |
| { "_Z14rsGetElementAt13rs_allocationjj", (void *)&SC_getElementAtXY, true }, |
| { "_Z14rsGetElementAt13rs_allocationjjj", (void *)&SC_getElementAtXYZ, true }, |
| |
| { "_Z11rsSetObjectP10rs_elementS_", (void *)&SC_setObject, true }, |
| { "_Z13rsClearObjectP10rs_element", (void *)&SC_clearObject, true }, |
| { "_Z10rsIsObject10rs_element", (void *)&SC_isObject, true }, |
| |
| { "_Z11rsSetObjectP7rs_typeS_", (void *)&SC_setObject, true }, |
| { "_Z13rsClearObjectP7rs_type", (void *)&SC_clearObject, true }, |
| { "_Z10rsIsObject7rs_type", (void *)&SC_isObject, true }, |
| |
| { "_Z11rsSetObjectP13rs_allocationS_", (void *)&SC_setObject, true }, |
| { "_Z13rsClearObjectP13rs_allocation", (void *)&SC_clearObject, true }, |
| { "_Z10rsIsObject13rs_allocation", (void *)&SC_isObject, true }, |
| |
| { "_Z11rsSetObjectP10rs_samplerS_", (void *)&SC_setObject, true }, |
| { "_Z13rsClearObjectP10rs_sampler", (void *)&SC_clearObject, true }, |
| { "_Z10rsIsObject10rs_sampler", (void *)&SC_isObject, true }, |
| |
| { "_Z11rsSetObjectP9rs_scriptS_", (void *)&SC_setObject, true }, |
| { "_Z13rsClearObjectP9rs_script", (void *)&SC_clearObject, true }, |
| { "_Z10rsIsObject9rs_script", (void *)&SC_isObject, true }, |
| |
| { "_Z11rsSetObjectP7rs_meshS_", (void *)&SC_setObject, true }, |
| { "_Z13rsClearObjectP7rs_mesh", (void *)&SC_clearObject, true }, |
| { "_Z10rsIsObject7rs_mesh", (void *)&SC_isObject, true }, |
| |
| { "_Z11rsSetObjectP19rs_program_fragmentS_", (void *)&SC_setObject, true }, |
| { "_Z13rsClearObjectP19rs_program_fragment", (void *)&SC_clearObject, true }, |
| { "_Z10rsIsObject19rs_program_fragment", (void *)&SC_isObject, true }, |
| |
| { "_Z11rsSetObjectP17rs_program_vertexS_", (void *)&SC_setObject, true }, |
| { "_Z13rsClearObjectP17rs_program_vertex", (void *)&SC_clearObject, true }, |
| { "_Z10rsIsObject17rs_program_vertex", (void *)&SC_isObject, true }, |
| |
| { "_Z11rsSetObjectP17rs_program_rasterS_", (void *)&SC_setObject, true }, |
| { "_Z13rsClearObjectP17rs_program_raster", (void *)&SC_clearObject, true }, |
| { "_Z10rsIsObject17rs_program_raster", (void *)&SC_isObject, true }, |
| |
| { "_Z11rsSetObjectP16rs_program_storeS_", (void *)&SC_setObject, true }, |
| { "_Z13rsClearObjectP16rs_program_store", (void *)&SC_clearObject, true }, |
| { "_Z10rsIsObject16rs_program_store", (void *)&SC_isObject, true }, |
| |
| { "_Z11rsSetObjectP7rs_fontS_", (void *)&SC_setObject, true }, |
| { "_Z13rsClearObjectP7rs_font", (void *)&SC_clearObject, true }, |
| { "_Z10rsIsObject7rs_font", (void *)&SC_isObject, true }, |
| |
| |
| { "_Z21rsAllocationMarkDirty13rs_allocation", (void *)&SC_allocationMarkDirty, true }, |
| |
| |
| // Debug |
| { "_Z7rsDebugPKcf", (void *)&SC_debugF, true }, |
| { "_Z7rsDebugPKcff", (void *)&SC_debugFv2, true }, |
| { "_Z7rsDebugPKcfff", (void *)&SC_debugFv3, true }, |
| { "_Z7rsDebugPKcffff", (void *)&SC_debugFv4, true }, |
| { "_Z7rsDebugPKcd", (void *)&SC_debugD, true }, |
| { "_Z7rsDebugPKcPK12rs_matrix4x4", (void *)&SC_debugFM4v4, true }, |
| { "_Z7rsDebugPKcPK12rs_matrix3x3", (void *)&SC_debugFM3v3, true }, |
| { "_Z7rsDebugPKcPK12rs_matrix2x2", (void *)&SC_debugFM2v2, true }, |
| { "_Z7rsDebugPKci", (void *)&SC_debugI32, true }, |
| { "_Z7rsDebugPKcj", (void *)&SC_debugU32, true }, |
| // Both "long" and "unsigned long" need to be redirected to their |
| // 64-bit counterparts, since we have hacked Slang to use 64-bit |
| // for "long" on Arm (to be similar to Java). |
| { "_Z7rsDebugPKcl", (void *)&SC_debugLL64, true }, |
| { "_Z7rsDebugPKcm", (void *)&SC_debugULL64, true }, |
| { "_Z7rsDebugPKcx", (void *)&SC_debugLL64, true }, |
| { "_Z7rsDebugPKcy", (void *)&SC_debugULL64, true }, |
| { "_Z7rsDebugPKcPKv", (void *)&SC_debugP, true }, |
| |
| // RS Math |
| { "_Z6rsRandi", (void *)&SC_randi, true }, |
| { "_Z6rsRandii", (void *)&SC_randi2, true }, |
| { "_Z6rsRandf", (void *)&SC_randf, true }, |
| { "_Z6rsRandff", (void *)&SC_randf2, true }, |
| { "_Z6rsFracf", (void *)&SC_frac, true }, |
| |
| // time |
| { "_Z6rsTimePi", (void *)&SC_time, true }, |
| { "_Z11rsLocaltimeP5rs_tmPKi", (void *)&SC_localtime, true }, |
| { "_Z14rsUptimeMillisv", (void*)&SC_uptimeMillis, true }, |
| { "_Z13rsUptimeNanosv", (void*)&SC_uptimeNanos, true }, |
| { "_Z7rsGetDtv", (void*)&SC_getDt, false }, |
| |
| { "_Z14rsSendToClienti", (void *)&SC_toClient, false }, |
| { "_Z14rsSendToClientiPKvj", (void *)&SC_toClient2, false }, |
| { "_Z22rsSendToClientBlockingi", (void *)&SC_toClientBlocking, false }, |
| { "_Z22rsSendToClientBlockingiPKvj", (void *)&SC_toClientBlocking2, false }, |
| |
| { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach, false }, |
| //{ "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach2, true }, |
| |
| //////////////////////////////////////////////////////////////////// |
| |
| //{ "sinf_fast", (void *)&SC_sinf_fast, true }, |
| //{ "cosf_fast", (void *)&SC_cosf_fast, true }, |
| |
| { NULL, NULL, false } |
| }; |
| |
| const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbol(const char *sym) { |
| ScriptCState::SymbolTable_t *syms = gSyms; |
| |
| while (syms->mPtr) { |
| if (!strcmp(syms->mName, sym)) { |
| return syms; |
| } |
| syms++; |
| } |
| return NULL; |
| } |