blob: 4e8cbdcc60be591c48d2370147d3e539c7ca3ee6 [file] [log] [blame]
/*
* 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() 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<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);
}
//////////////////////////////////////////////////////////////////////////////
// Heavy math functions
//////////////////////////////////////////////////////////////////////////////
typedef struct {
float m[16];
} rs_matrix4x4;
typedef struct {
float m[9];
} rs_matrix3x3;
typedef struct {
float m[4];
} rs_matrix2x2;
static inline void
rsMatrixSet(rs_matrix4x4 *m, uint32_t row, uint32_t col, float v) {
m->m[row * 4 + col] = v;
}
static inline float
rsMatrixGet(const rs_matrix4x4 *m, uint32_t row, uint32_t col) {
return m->m[row * 4 + col];
}
static inline void
rsMatrixSet(rs_matrix3x3 *m, uint32_t row, uint32_t col, float v) {
m->m[row * 3 + col] = v;
}
static inline float
rsMatrixGet(const rs_matrix3x3 *m, uint32_t row, uint32_t col) {
return m->m[row * 3 + col];
}
static inline void
rsMatrixSet(rs_matrix2x2 *m, uint32_t row, uint32_t col, float v) {
m->m[row * 2 + col] = v;
}
static inline float
rsMatrixGet(const rs_matrix2x2 *m, uint32_t row, uint32_t col) {
return m->m[row * 2 + col];
}
static void SC_MatrixLoadIdentity_4x4(rs_matrix4x4 *m) {
m->m[0] = 1.f;
m->m[1] = 0.f;
m->m[2] = 0.f;
m->m[3] = 0.f;
m->m[4] = 0.f;
m->m[5] = 1.f;
m->m[6] = 0.f;
m->m[7] = 0.f;
m->m[8] = 0.f;
m->m[9] = 0.f;
m->m[10] = 1.f;
m->m[11] = 0.f;
m->m[12] = 0.f;
m->m[13] = 0.f;
m->m[14] = 0.f;
m->m[15] = 1.f;
}
static void SC_MatrixLoadIdentity_3x3(rs_matrix3x3 *m) {
m->m[0] = 1.f;
m->m[1] = 0.f;
m->m[2] = 0.f;
m->m[3] = 0.f;
m->m[4] = 1.f;
m->m[5] = 0.f;
m->m[6] = 0.f;
m->m[7] = 0.f;
m->m[8] = 1.f;
}
static void SC_MatrixLoadIdentity_2x2(rs_matrix2x2 *m) {
m->m[0] = 1.f;
m->m[1] = 0.f;
m->m[2] = 0.f;
m->m[3] = 1.f;
}
static void SC_MatrixLoad_4x4_f(rs_matrix4x4 *m, const float *v) {
m->m[0] = v[0];
m->m[1] = v[1];
m->m[2] = v[2];
m->m[3] = v[3];
m->m[4] = v[4];
m->m[5] = v[5];
m->m[6] = v[6];
m->m[7] = v[7];
m->m[8] = v[8];
m->m[9] = v[9];
m->m[10] = v[10];
m->m[11] = v[11];
m->m[12] = v[12];
m->m[13] = v[13];
m->m[14] = v[14];
m->m[15] = v[15];
}
static void SC_MatrixLoad_3x3_f(rs_matrix3x3 *m, const float *v) {
m->m[0] = v[0];
m->m[1] = v[1];
m->m[2] = v[2];
m->m[3] = v[3];
m->m[4] = v[4];
m->m[5] = v[5];
m->m[6] = v[6];
m->m[7] = v[7];
m->m[8] = v[8];
}
static void SC_MatrixLoad_2x2_f(rs_matrix2x2 *m, const float *v) {
m->m[0] = v[0];
m->m[1] = v[1];
m->m[2] = v[2];
m->m[3] = v[3];
}
static void SC_MatrixLoad_4x4_4x4(rs_matrix4x4 *m, const rs_matrix4x4 *v) {
m->m[0] = v->m[0];
m->m[1] = v->m[1];
m->m[2] = v->m[2];
m->m[3] = v->m[3];
m->m[4] = v->m[4];
m->m[5] = v->m[5];
m->m[6] = v->m[6];
m->m[7] = v->m[7];
m->m[8] = v->m[8];
m->m[9] = v->m[9];
m->m[10] = v->m[10];
m->m[11] = v->m[11];
m->m[12] = v->m[12];
m->m[13] = v->m[13];
m->m[14] = v->m[14];
m->m[15] = v->m[15];
}
static void SC_MatrixLoad_4x4_3x3(rs_matrix4x4 *m, const rs_matrix3x3 *v) {
m->m[0] = v->m[0];
m->m[1] = v->m[1];
m->m[2] = v->m[2];
m->m[3] = 0.f;
m->m[4] = v->m[3];
m->m[5] = v->m[4];
m->m[6] = v->m[5];
m->m[7] = 0.f;
m->m[8] = v->m[6];
m->m[9] = v->m[7];
m->m[10] = v->m[8];
m->m[11] = 0.f;
m->m[12] = 0.f;
m->m[13] = 0.f;
m->m[14] = 0.f;
m->m[15] = 1.f;
}
static void SC_MatrixLoad_4x4_2x2(rs_matrix4x4 *m, const rs_matrix2x2 *v) {
m->m[0] = v->m[0];
m->m[1] = v->m[1];
m->m[2] = 0.f;
m->m[3] = 0.f;
m->m[4] = v->m[2];
m->m[5] = v->m[3];
m->m[6] = 0.f;
m->m[7] = 0.f;
m->m[8] = 0.f;
m->m[9] = 0.f;
m->m[10] = 1.f;
m->m[11] = 0.f;
m->m[12] = 0.f;
m->m[13] = 0.f;
m->m[14] = 0.f;
m->m[15] = 1.f;
}
static void SC_MatrixLoad_3x3_3x3(rs_matrix3x3 *m, const rs_matrix3x3 *v) {
m->m[0] = v->m[0];
m->m[1] = v->m[1];
m->m[2] = v->m[2];
m->m[3] = v->m[3];
m->m[4] = v->m[4];
m->m[5] = v->m[5];
m->m[6] = v->m[6];
m->m[7] = v->m[7];
m->m[8] = v->m[8];
}
static void SC_MatrixLoad_2x2_2x2(rs_matrix2x2 *m, const rs_matrix2x2 *v) {
m->m[0] = v->m[0];
m->m[1] = v->m[1];
m->m[2] = v->m[2];
m->m[3] = v->m[3];
}
static void SC_MatrixLoadRotate(rs_matrix4x4 *m, float rot, float x, float y, float z) {
float c, s;
m->m[3] = 0;
m->m[7] = 0;
m->m[11]= 0;
m->m[12]= 0;
m->m[13]= 0;
m->m[14]= 0;
m->m[15]= 1;
rot *= (float)(M_PI / 180.0f);
c = cos(rot);
s = sin(rot);
const float len = x*x + y*y + z*z;
if (len != 1) {
const float recipLen = 1.f / sqrt(len);
x *= recipLen;
y *= recipLen;
z *= recipLen;
}
const float nc = 1.0f - c;
const float xy = x * y;
const float yz = y * z;
const float zx = z * x;
const float xs = x * s;
const float ys = y * s;
const float zs = z * s;
m->m[ 0] = x*x*nc + c;
m->m[ 4] = xy*nc - zs;
m->m[ 8] = zx*nc + ys;
m->m[ 1] = xy*nc + zs;
m->m[ 5] = y*y*nc + c;
m->m[ 9] = yz*nc - xs;
m->m[ 2] = zx*nc - ys;
m->m[ 6] = yz*nc + xs;
m->m[10] = z*z*nc + c;
}
static void SC_MatrixLoadScale(rs_matrix4x4 *m, float x, float y, float z) {
SC_MatrixLoadIdentity_4x4(m);
m->m[0] = x;
m->m[5] = y;
m->m[10] = z;
}
static void SC_MatrixLoadTranslate(rs_matrix4x4 *m, float x, float y, float z) {
SC_MatrixLoadIdentity_4x4(m);
m->m[12] = x;
m->m[13] = y;
m->m[14] = z;
}
static void SC_MatrixLoadMultiply_4x4_4x4_4x4(rs_matrix4x4 *m, const rs_matrix4x4 *lhs, const rs_matrix4x4 *rhs) {
for (int i=0 ; i<4 ; i++) {
float ri0 = 0;
float ri1 = 0;
float ri2 = 0;
float ri3 = 0;
for (int j=0 ; j<4 ; j++) {
const float rhs_ij = rsMatrixGet(rhs, i,j);
ri0 += rsMatrixGet(lhs, j, 0) * rhs_ij;
ri1 += rsMatrixGet(lhs, j, 1) * rhs_ij;
ri2 += rsMatrixGet(lhs, j, 2) * rhs_ij;
ri3 += rsMatrixGet(lhs, j, 3) * rhs_ij;
}
rsMatrixSet(m, i, 0, ri0);
rsMatrixSet(m, i, 1, ri1);
rsMatrixSet(m, i, 2, ri2);
rsMatrixSet(m, i, 3, ri3);
}
}
static void SC_MatrixMultiply_4x4_4x4(rs_matrix4x4 *m, const rs_matrix4x4 *rhs) {
rs_matrix4x4 mt;
SC_MatrixLoadMultiply_4x4_4x4_4x4(&mt, m, rhs);
SC_MatrixLoad_4x4_4x4(m, &mt);
}
static void SC_MatrixLoadMultiply_3x3_3x3_3x3(rs_matrix3x3 *m, const rs_matrix3x3 *lhs, const rs_matrix3x3 *rhs) {
for (int i=0 ; i<3 ; i++) {
float ri0 = 0;
float ri1 = 0;
float ri2 = 0;
for (int j=0 ; j<3 ; j++) {
const float rhs_ij = rsMatrixGet(rhs, i,j);
ri0 += rsMatrixGet(lhs, j, 0) * rhs_ij;
ri1 += rsMatrixGet(lhs, j, 1) * rhs_ij;
ri2 += rsMatrixGet(lhs, j, 2) * rhs_ij;
}
rsMatrixSet(m, i, 0, ri0);
rsMatrixSet(m, i, 1, ri1);
rsMatrixSet(m, i, 2, ri2);
}
}
static void SC_MatrixMultiply_3x3_3x3(rs_matrix3x3 *m, const rs_matrix3x3 *rhs) {
rs_matrix3x3 mt;
SC_MatrixLoadMultiply_3x3_3x3_3x3(&mt, m, rhs);
SC_MatrixLoad_3x3_3x3(m, &mt);
}
static void SC_MatrixLoadMultiply_2x2_2x2_2x2(rs_matrix2x2 *m, const rs_matrix2x2 *lhs, const rs_matrix2x2 *rhs) {
for (int i=0 ; i<2 ; i++) {
float ri0 = 0;
float ri1 = 0;
for (int j=0 ; j<2 ; j++) {
const float rhs_ij = rsMatrixGet(rhs, i,j);
ri0 += rsMatrixGet(lhs, j, 0) * rhs_ij;
ri1 += rsMatrixGet(lhs, j, 1) * rhs_ij;
}
rsMatrixSet(m, i, 0, ri0);
rsMatrixSet(m, i, 1, ri1);
}
}
static void SC_MatrixMultiply_2x2_2x2(rs_matrix2x2 *m, const rs_matrix2x2 *rhs) {
rs_matrix2x2 mt;
SC_MatrixLoadMultiply_2x2_2x2_2x2(&mt, m, rhs);
SC_MatrixLoad_2x2_2x2(m, &mt);
}
static void SC_MatrixRotate(rs_matrix4x4 *m, float rot, float x, float y, float z) {
rs_matrix4x4 m1;
SC_MatrixLoadRotate(&m1, rot, x, y, z);
SC_MatrixMultiply_4x4_4x4(m, &m1);
}
static void SC_MatrixScale(rs_matrix4x4 *m, float x, float y, float z) {
rs_matrix4x4 m1;
SC_MatrixLoadScale(&m1, x, y, z);
SC_MatrixMultiply_4x4_4x4(m, &m1);
}
static void SC_MatrixTranslate(rs_matrix4x4 *m, float x, float y, float z) {
rs_matrix4x4 m1;
SC_MatrixLoadTranslate(&m1, x, y, z);
SC_MatrixMultiply_4x4_4x4(m, &m1);
}
static void SC_MatrixLoadOrtho(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far) {
SC_MatrixLoadIdentity_4x4(m);
m->m[0] = 2.f / (right - left);
m->m[5] = 2.f / (top - bottom);
m->m[10]= -2.f / (far - near);
m->m[12]= -(right + left) / (right - left);
m->m[13]= -(top + bottom) / (top - bottom);
m->m[14]= -(far + near) / (far - near);
}
static void SC_MatrixLoadFrustum(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far) {
SC_MatrixLoadIdentity_4x4(m);
m->m[0] = 2.f * near / (right - left);
m->m[5] = 2.f * near / (top - bottom);
m->m[8] = (right + left) / (right - left);
m->m[9] = (top + bottom) / (top - bottom);
m->m[10]= -(far + near) / (far - near);
m->m[11]= -1.f;
m->m[14]= -2.f * far * near / (far - near);
m->m[15]= 0.f;
}
static void SC_MatrixLoadPerspective(rs_matrix4x4* m, float fovy, float aspect, float near, float far) {
float top = near * tan((float) (fovy * M_PI / 360.0f));
float bottom = -top;
float left = bottom * aspect;
float right = top * aspect;
SC_MatrixLoadFrustum(m, left, right, bottom, top, near, far);
}
// Returns true if the matrix was successfully inversed
static bool SC_MatrixInverse_4x4(rs_matrix4x4 *m) {
rs_matrix4x4 result;
int i, j;
for (i = 0; i < 4; ++i) {
for (j = 0; j < 4; ++j) {
// computeCofactor for int i, int j
int c0 = (i+1) % 4;
int c1 = (i+2) % 4;
int c2 = (i+3) % 4;
int r0 = (j+1) % 4;
int r1 = (j+2) % 4;
int r2 = (j+3) % 4;
float minor = (m->m[c0 + 4*r0] * (m->m[c1 + 4*r1] * m->m[c2 + 4*r2] - m->m[c1 + 4*r2] * m->m[c2 + 4*r1]))
- (m->m[c0 + 4*r1] * (m->m[c1 + 4*r0] * m->m[c2 + 4*r2] - m->m[c1 + 4*r2] * m->m[c2 + 4*r0]))
+ (m->m[c0 + 4*r2] * (m->m[c1 + 4*r0] * m->m[c2 + 4*r1] - m->m[c1 + 4*r1] * m->m[c2 + 4*r0]));
float cofactor = (i+j) & 1 ? -minor : minor;
result.m[4*i + j] = cofactor;
}
}
// Dot product of 0th column of source and 0th row of result
float det = m->m[0]*result.m[0] + m->m[4]*result.m[1] +
m->m[8]*result.m[2] + m->m[12]*result.m[3];
if (fabs(det) < 1e-6) {
return false;
}
det = 1.0f / det;
for (i = 0; i < 16; ++i) {
m->m[i] = result.m[i] * det;
}
return true;
}
// Returns true if the matrix was successfully inversed
static bool SC_MatrixInverseTranspose_4x4(rs_matrix4x4 *m) {
rs_matrix4x4 result;
int i, j;
for (i = 0; i < 4; ++i) {
for (j = 0; j < 4; ++j) {
// computeCofactor for int i, int j
int c0 = (i+1) % 4;
int c1 = (i+2) % 4;
int c2 = (i+3) % 4;
int r0 = (j+1) % 4;
int r1 = (j+2) % 4;
int r2 = (j+3) % 4;
float minor = (m->m[c0 + 4*r0] * (m->m[c1 + 4*r1] * m->m[c2 + 4*r2] - m->m[c1 + 4*r2] * m->m[c2 + 4*r1]))
- (m->m[c0 + 4*r1] * (m->m[c1 + 4*r0] * m->m[c2 + 4*r2] - m->m[c1 + 4*r2] * m->m[c2 + 4*r0]))
+ (m->m[c0 + 4*r2] * (m->m[c1 + 4*r0] * m->m[c2 + 4*r1] - m->m[c1 + 4*r1] * m->m[c2 + 4*r0]));
float cofactor = (i+j) & 1 ? -minor : minor;
result.m[4*j + i] = cofactor;
}
}
// Dot product of 0th column of source and 0th column of result
float det = m->m[0]*result.m[0] + m->m[4]*result.m[4] +
m->m[8]*result.m[8] + m->m[12]*result.m[12];
if (fabs(det) < 1e-6) {
return false;
}
det = 1.0f / det;
for (i = 0; i < 16; ++i) {
m->m[i] = result.m[i] * det;
}
return true;
}
static void SC_MatrixTranspose_4x4(rs_matrix4x4 *m) {
int i, j;
float temp;
for (i = 0; i < 3; ++i) {
for (j = i + 1; j < 4; ++j) {
temp = m->m[i*4 + j];
m->m[i*4 + j] = m->m[j*4 + i];
m->m[j*4 + i] = temp;
}
}
}
static void SC_MatrixTranspose_3x3(rs_matrix3x3 *m) {
int i, j;
float temp;
for (i = 0; i < 2; ++i) {
for (j = i + 1; j < 3; ++j) {
temp = m->m[i*3 + j];
m->m[i*3 + j] = m->m[j*4 + i];
m->m[j*3 + i] = temp;
}
}
}
static void SC_MatrixTranspose_2x2(rs_matrix2x2 *m) {
float temp = m->m[1];
m->m[1] = m->m[2];
m->m[2] = temp;
}
//////////////////////////////////////////////////////////////////////////////
// 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 },
{ "__udivsi3", (void *)&SC_udivsi3, true },
{ "__umodsi3", (void *)&SC_umodsi3, true },
{ "memset", (void *)&memset, true },
{ "memcpy", (void *)&memcpy, 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 *)&rsiSetObject, true },
{ "_Z13rsClearObjectP10rs_element", (void *)&rsiClearObject, true },
{ "_Z10rsIsObject10rs_element", (void *)&rsiIsObject, true },
{ "_Z11rsSetObjectP7rs_typeS_", (void *)&rsiSetObject, true },
{ "_Z13rsClearObjectP7rs_type", (void *)&rsiClearObject, true },
{ "_Z10rsIsObject7rs_type", (void *)&rsiIsObject, true },
{ "_Z11rsSetObjectP13rs_allocationS_", (void *)&rsiSetObject, true },
{ "_Z13rsClearObjectP13rs_allocation", (void *)&rsiClearObject, true },
{ "_Z10rsIsObject13rs_allocation", (void *)&rsiIsObject, true },
{ "_Z11rsSetObjectP10rs_samplerS_", (void *)&rsiSetObject, true },
{ "_Z13rsClearObjectP10rs_sampler", (void *)&rsiClearObject, true },
{ "_Z10rsIsObject10rs_sampler", (void *)&rsiIsObject, true },
{ "_Z11rsSetObjectP9rs_scriptS_", (void *)&rsiSetObject, true },
{ "_Z13rsClearObjectP9rs_script", (void *)&rsiClearObject, true },
{ "_Z10rsIsObject9rs_script", (void *)&rsiIsObject, true },
{ "_Z11rsSetObjectP7rs_meshS_", (void *)&rsiSetObject, true },
{ "_Z13rsClearObjectP7rs_mesh", (void *)&rsiClearObject, true },
{ "_Z10rsIsObject7rs_mesh", (void *)&rsiIsObject, true },
{ "_Z11rsSetObjectP19rs_program_fragmentS_", (void *)&rsiSetObject, true },
{ "_Z13rsClearObjectP19rs_program_fragment", (void *)&rsiClearObject, true },
{ "_Z10rsIsObject19rs_program_fragment", (void *)&rsiIsObject, true },
{ "_Z11rsSetObjectP17rs_program_vertexS_", (void *)&rsiSetObject, true },
{ "_Z13rsClearObjectP17rs_program_vertex", (void *)&rsiClearObject, true },
{ "_Z10rsIsObject17rs_program_vertex", (void *)&rsiIsObject, true },
{ "_Z11rsSetObjectP17rs_program_rasterS_", (void *)&rsiSetObject, true },
{ "_Z13rsClearObjectP17rs_program_raster", (void *)&rsiClearObject, true },
{ "_Z10rsIsObject17rs_program_raster", (void *)&rsiIsObject, true },
{ "_Z11rsSetObjectP16rs_program_storeS_", (void *)&rsiSetObject, true },
{ "_Z13rsClearObjectP16rs_program_store", (void *)&rsiClearObject, true },
{ "_Z10rsIsObject16rs_program_store", (void *)&rsiIsObject, true },
{ "_Z11rsSetObjectP7rs_fontS_", (void *)&rsiSetObject, true },
{ "_Z13rsClearObjectP7rs_font", (void *)&rsiClearObject, true },
{ "_Z10rsIsObject7rs_font", (void *)&rsiIsObject, 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 },
// matrix
{ "_Z20rsMatrixLoadIdentityP12rs_matrix4x4", (void *)&SC_MatrixLoadIdentity_4x4, true },
{ "_Z20rsMatrixLoadIdentityP12rs_matrix3x3", (void *)&SC_MatrixLoadIdentity_3x3, true },
{ "_Z20rsMatrixLoadIdentityP12rs_matrix2x2", (void *)&SC_MatrixLoadIdentity_2x2, true },
{ "_Z12rsMatrixLoadP12rs_matrix4x4PKf", (void *)&SC_MatrixLoad_4x4_f, true },
{ "_Z12rsMatrixLoadP12rs_matrix3x3PKf", (void *)&SC_MatrixLoad_3x3_f, true },
{ "_Z12rsMatrixLoadP12rs_matrix2x2PKf", (void *)&SC_MatrixLoad_2x2_f, true },
{ "_Z12rsMatrixLoadP12rs_matrix4x4PKS_", (void *)&SC_MatrixLoad_4x4_4x4, true },
{ "_Z12rsMatrixLoadP12rs_matrix4x4PK12rs_matrix3x3", (void *)&SC_MatrixLoad_4x4_3x3, true },
{ "_Z12rsMatrixLoadP12rs_matrix4x4PK12rs_matrix2x2", (void *)&SC_MatrixLoad_4x4_2x2, true },
{ "_Z12rsMatrixLoadP12rs_matrix3x3PKS_", (void *)&SC_MatrixLoad_3x3_3x3, true },
{ "_Z12rsMatrixLoadP12rs_matrix2x2PKS_", (void *)&SC_MatrixLoad_2x2_2x2, true },
{ "_Z18rsMatrixLoadRotateP12rs_matrix4x4ffff", (void *)&SC_MatrixLoadRotate, true },
{ "_Z17rsMatrixLoadScaleP12rs_matrix4x4fff", (void *)&SC_MatrixLoadScale, true },
{ "_Z21rsMatrixLoadTranslateP12rs_matrix4x4fff", (void *)&SC_MatrixLoadTranslate, true },
{ "_Z14rsMatrixRotateP12rs_matrix4x4ffff", (void *)&SC_MatrixRotate, true },
{ "_Z13rsMatrixScaleP12rs_matrix4x4fff", (void *)&SC_MatrixScale, true },
{ "_Z17rsMatrixTranslateP12rs_matrix4x4fff", (void *)&SC_MatrixTranslate, true },
{ "_Z20rsMatrixLoadMultiplyP12rs_matrix4x4PKS_S2_", (void *)&SC_MatrixLoadMultiply_4x4_4x4_4x4, true },
{ "_Z16rsMatrixMultiplyP12rs_matrix4x4PKS_", (void *)&SC_MatrixMultiply_4x4_4x4, true },
{ "_Z20rsMatrixLoadMultiplyP12rs_matrix3x3PKS_S2_", (void *)&SC_MatrixLoadMultiply_3x3_3x3_3x3, true },
{ "_Z16rsMatrixMultiplyP12rs_matrix3x3PKS_", (void *)&SC_MatrixMultiply_3x3_3x3, true },
{ "_Z20rsMatrixLoadMultiplyP12rs_matrix2x2PKS_S2_", (void *)&SC_MatrixLoadMultiply_2x2_2x2_2x2, true },
{ "_Z16rsMatrixMultiplyP12rs_matrix2x2PKS_", (void *)&SC_MatrixMultiply_2x2_2x2, true },
{ "_Z17rsMatrixLoadOrthoP12rs_matrix4x4ffffff", (void *)&SC_MatrixLoadOrtho, true },
{ "_Z19rsMatrixLoadFrustumP12rs_matrix4x4ffffff", (void *)&SC_MatrixLoadFrustum, true },
{ "_Z23rsMatrixLoadPerspectiveP12rs_matrix4x4ffff", (void *)&SC_MatrixLoadPerspective, true },
{ "_Z15rsMatrixInverseP12rs_matrix4x4", (void *)&SC_MatrixInverse_4x4, true },
{ "_Z24rsMatrixInverseTransposeP12rs_matrix4x4", (void *)&SC_MatrixInverseTranspose_4x4, true },
{ "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_4x4, true },
{ "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_3x3, true },
{ "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_2x2, true },
{ "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach, false },
//{ "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach2, false },
////////////////////////////////////////////////////////////////////
//{ "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;
}