/* * 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 using namespace android; using namespace android::renderscript; #define GET_TLS() ScriptTLSStruct * tls = \ (ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \ Context * rsc = tls->mContext; \ ScriptC * sc = (ScriptC *) tls->mScript ////////////////////////////////////////////////////////////////////////////// // Math routines ////////////////////////////////////////////////////////////////////////////// #if 0 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; } #endif 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(Allocation *a) { CHECK_OBJ(a); return a->mHal.state.dimensionX; } static uint32_t SC_allocGetDimY(Allocation *a) { CHECK_OBJ(a); return a->mHal.state.dimensionY; } static uint32_t SC_allocGetDimZ(Allocation *a) { CHECK_OBJ(a); return a->mHal.state.dimensionZ; } static uint32_t SC_allocGetDimLOD(Allocation *a) { CHECK_OBJ(a); return a->mHal.state.hasMipmaps; } static uint32_t SC_allocGetDimFaces(Allocation *a) { CHECK_OBJ(a); return a->mHal.state.hasFaces; } static const void * SC_getElementAtX(Allocation *a, uint32_t x) { CHECK_OBJ(a); const uint8_t *p = (const uint8_t *)a->getPtr(); return &p[a->mHal.state.elementSizeBytes * x]; } static const void * SC_getElementAtXY(Allocation *a, uint32_t x, uint32_t y) { CHECK_OBJ(a); const uint8_t *p = (const uint8_t *)a->getPtr(); return &p[a->mHal.state.elementSizeBytes * (x + y * a->mHal.state.dimensionX)]; } static const void * SC_getElementAtXYZ(Allocation *a, uint32_t x, uint32_t y, uint32_t z) { CHECK_OBJ(a); const uint8_t *p = (const uint8_t *)a->getPtr(); return &p[a->mHal.state.elementSizeBytes * (x + y * a->mHal.state.dimensionX + z * a->mHal.state.dimensionX * a->mHal.state.dimensionY)]; } void android::renderscript::rsiSetObject(ObjectBase **dst, ObjectBase * src) { //LOGE("rsiSetObject %p,%p %p", vdst, *vdst, vsrc); if (src) { CHECK_OBJ(src); src->incSysRef(); } if (dst[0]) { CHECK_OBJ(dst[0]); dst[0]->decSysRef(); } *dst = src; } void android::renderscript::rsiClearObject(ObjectBase **dst) { //LOGE("rsiClearObject %p,%p", vdst, *vdst); if (dst[0]) { CHECK_OBJ(dst[0]); dst[0]->decSysRef(); } *dst = NULL; } bool android::renderscript::rsiIsObject(const ObjectBase *src) { return src != 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; } unsigned int SC_udivsi3(unsigned int a, unsigned int b) { return a / b; } unsigned int SC_umodsi3(unsigned int a, unsigned 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(a); alloc->sendDirty(); } void SC_ForEach(RsScript vs, RsAllocation vin, RsAllocation vout, const void *usr) { GET_TLS(); const Allocation *ain = static_cast(vin); Allocation *aout = static_cast(vout); Script *s = static_cast