rsScriptC_Lib.cpp revision cdfdb8f2cdf4668c476cac842212892b2505ff3f
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()  ScriptTLSStruct * tls = \
29    (ScriptTLSStruct *)pthread_getspecific(Context::gThreadTLSKey); \
30    Context * rsc = tls->mContext; \
31    ScriptC * sc = (ScriptC *) tls->mScript
32
33
34//////////////////////////////////////////////////////////////////////////////
35// Math routines
36//////////////////////////////////////////////////////////////////////////////
37
38#if 0
39static float SC_sinf_fast(float x) {
40    const float A =   1.0f / (2.0f * M_PI);
41    const float B = -16.0f;
42    const float C =   8.0f;
43
44    // scale angle for easy argument reduction
45    x *= A;
46
47    if (fabsf(x) >= 0.5f) {
48        // argument reduction
49        x = x - ceilf(x + 0.5f) + 1.0f;
50    }
51
52    const float y = B * x * fabsf(x) + C * x;
53    return 0.2215f * (y * fabsf(y) - y) + y;
54}
55
56static float SC_cosf_fast(float x) {
57    x += float(M_PI / 2);
58
59    const float A =   1.0f / (2.0f * M_PI);
60    const float B = -16.0f;
61    const float C =   8.0f;
62
63    // scale angle for easy argument reduction
64    x *= A;
65
66    if (fabsf(x) >= 0.5f) {
67        // argument reduction
68        x = x - ceilf(x + 0.5f) + 1.0f;
69    }
70
71    const float y = B * x * fabsf(x) + C * x;
72    return 0.2215f * (y * fabsf(y) - y) + y;
73}
74#endif
75
76static float SC_randf(float max) {
77    float r = (float)rand();
78    r *= max;
79    return r / RAND_MAX;
80}
81
82static float SC_randf2(float min, float max) {
83    float r = (float)rand();
84    r = r * (max - min) + min;
85    return r / RAND_MAX;
86}
87
88static int SC_randi(int max) {
89    return (int)SC_randf(max);
90}
91
92static int SC_randi2(int min, int max) {
93    return (int)SC_randf2(min, max);
94}
95
96static float SC_frac(float v) {
97    int i = (int)floor(v);
98    return fmin(v - i, 0x1.fffffep-1f);
99}
100
101//////////////////////////////////////////////////////////////////////////////
102// Time routines
103//////////////////////////////////////////////////////////////////////////////
104
105static time_t SC_time(time_t *timer) {
106    GET_TLS();
107    return time(timer);
108}
109
110static tm* SC_localtime(tm *local, time_t *timer) {
111    GET_TLS();
112    if (!local) {
113      return NULL;
114    }
115
116    // The native localtime function is not thread-safe, so we
117    // have to apply locking for proper behavior in RenderScript.
118    pthread_mutex_lock(&rsc->gLibMutex);
119    tm *tmp = localtime(timer);
120    memcpy(local, tmp, sizeof(*tmp));
121    pthread_mutex_unlock(&rsc->gLibMutex);
122    return local;
123}
124
125static int64_t SC_uptimeMillis() {
126    return nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
127}
128
129static int64_t SC_uptimeNanos() {
130    return systemTime(SYSTEM_TIME_MONOTONIC);
131}
132
133static float SC_getDt() {
134    GET_TLS();
135    int64_t l = sc->mEnviroment.mLastDtTime;
136    sc->mEnviroment.mLastDtTime = systemTime(SYSTEM_TIME_MONOTONIC);
137    return ((float)(sc->mEnviroment.mLastDtTime - l)) / 1.0e9;
138}
139
140//////////////////////////////////////////////////////////////////////////////
141//
142//////////////////////////////////////////////////////////////////////////////
143
144static uint32_t SC_allocGetDimX(Allocation *a) {
145    CHECK_OBJ(a);
146    return a->mHal.state.dimensionX;
147}
148
149static uint32_t SC_allocGetDimY(Allocation *a) {
150    CHECK_OBJ(a);
151    return a->mHal.state.dimensionY;
152}
153
154static uint32_t SC_allocGetDimZ(Allocation *a) {
155    CHECK_OBJ(a);
156    return a->mHal.state.dimensionZ;
157}
158
159static uint32_t SC_allocGetDimLOD(Allocation *a) {
160    CHECK_OBJ(a);
161    return a->mHal.state.hasMipmaps;
162}
163
164static uint32_t SC_allocGetDimFaces(Allocation *a) {
165    CHECK_OBJ(a);
166    return a->mHal.state.hasFaces;
167}
168
169static const void * SC_getElementAtX(Allocation *a, uint32_t x) {
170    CHECK_OBJ(a);
171    const uint8_t *p = (const uint8_t *)a->getPtr();
172    return &p[a->mHal.state.elementSizeBytes * x];
173}
174
175static const void * SC_getElementAtXY(Allocation *a, uint32_t x, uint32_t y) {
176    CHECK_OBJ(a);
177    const uint8_t *p = (const uint8_t *)a->getPtr();
178    return &p[a->mHal.state.elementSizeBytes * (x + y * a->mHal.state.dimensionX)];
179}
180
181static const void * SC_getElementAtXYZ(Allocation *a, uint32_t x, uint32_t y, uint32_t z) {
182    CHECK_OBJ(a);
183    const uint8_t *p = (const uint8_t *)a->getPtr();
184    return &p[a->mHal.state.elementSizeBytes * (x + y * a->mHal.state.dimensionX +
185              z * a->mHal.state.dimensionX * a->mHal.state.dimensionY)];
186}
187
188void android::renderscript::rsiSetObject(ObjectBase **dst, ObjectBase * src) {
189    //LOGE("rsiSetObject  %p,%p  %p", vdst, *vdst, vsrc);
190    if (src) {
191        CHECK_OBJ(src);
192        src->incSysRef();
193    }
194    if (dst[0]) {
195        CHECK_OBJ(dst[0]);
196        dst[0]->decSysRef();
197    }
198    *dst = src;
199}
200
201void android::renderscript::rsiClearObject(ObjectBase **dst) {
202    //LOGE("rsiClearObject  %p,%p", vdst, *vdst);
203    if (dst[0]) {
204        CHECK_OBJ(dst[0]);
205        dst[0]->decSysRef();
206    }
207    *dst = NULL;
208}
209
210bool android::renderscript::rsiIsObject(const ObjectBase *src) {
211    return src != NULL;
212}
213
214static void SC_debugF(const char *s, float f) {
215    LOGD("%s %f, 0x%08x", s, f, *((int *) (&f)));
216}
217static void SC_debugFv2(const char *s, float f1, float f2) {
218    LOGD("%s {%f, %f}", s, f1, f2);
219}
220static void SC_debugFv3(const char *s, float f1, float f2, float f3) {
221    LOGD("%s {%f, %f, %f}", s, f1, f2, f3);
222}
223static void SC_debugFv4(const char *s, float f1, float f2, float f3, float f4) {
224    LOGD("%s {%f, %f, %f, %f}", s, f1, f2, f3, f4);
225}
226static void SC_debugD(const char *s, double d) {
227    LOGD("%s %f, 0x%08llx", s, d, *((long long *) (&d)));
228}
229static void SC_debugFM4v4(const char *s, const float *f) {
230    LOGD("%s {%f, %f, %f, %f", s, f[0], f[4], f[8], f[12]);
231    LOGD("%s  %f, %f, %f, %f", s, f[1], f[5], f[9], f[13]);
232    LOGD("%s  %f, %f, %f, %f", s, f[2], f[6], f[10], f[14]);
233    LOGD("%s  %f, %f, %f, %f}", s, f[3], f[7], f[11], f[15]);
234}
235static void SC_debugFM3v3(const char *s, const float *f) {
236    LOGD("%s {%f, %f, %f", s, f[0], f[3], f[6]);
237    LOGD("%s  %f, %f, %f", s, f[1], f[4], f[7]);
238    LOGD("%s  %f, %f, %f}",s, f[2], f[5], f[8]);
239}
240static void SC_debugFM2v2(const char *s, const float *f) {
241    LOGD("%s {%f, %f", s, f[0], f[2]);
242    LOGD("%s  %f, %f}",s, f[1], f[3]);
243}
244
245static void SC_debugI32(const char *s, int32_t i) {
246    LOGD("%s %i  0x%x", s, i, i);
247}
248static void SC_debugU32(const char *s, uint32_t i) {
249    LOGD("%s %u  0x%x", s, i, i);
250}
251static void SC_debugLL64(const char *s, long long ll) {
252    LOGD("%s %lld  0x%llx", s, ll, ll);
253}
254static void SC_debugULL64(const char *s, unsigned long long ll) {
255    LOGD("%s %llu  0x%llx", s, ll, ll);
256}
257
258static void SC_debugP(const char *s, const void *p) {
259    LOGD("%s %p", s, p);
260}
261
262static uint32_t SC_toClient2(int cmdID, void *data, int len) {
263    GET_TLS();
264    //LOGE("SC_toClient %i %i %i", cmdID, len);
265    return rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, cmdID, len, false);
266}
267
268static uint32_t SC_toClient(int cmdID) {
269    GET_TLS();
270    //LOGE("SC_toClient %i", cmdID);
271    return rsc->sendMessageToClient(NULL, RS_MESSAGE_TO_CLIENT_USER, cmdID, 0, false);
272}
273
274static uint32_t SC_toClientBlocking2(int cmdID, void *data, int len) {
275    GET_TLS();
276    //LOGE("SC_toClientBlocking %i %i", cmdID, len);
277    return rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, cmdID, len, true);
278}
279
280static uint32_t SC_toClientBlocking(int cmdID) {
281    GET_TLS();
282    //LOGE("SC_toClientBlocking %i", cmdID);
283    return rsc->sendMessageToClient(NULL, RS_MESSAGE_TO_CLIENT_USER, cmdID, 0, true);
284}
285
286int SC_divsi3(int a, int b) {
287    return a / b;
288}
289
290int SC_modsi3(int a, int b) {
291    return a % b;
292}
293
294unsigned int SC_udivsi3(unsigned int a, unsigned int b) {
295    return a / b;
296}
297
298unsigned int SC_umodsi3(unsigned int a, unsigned int b) {
299    return a % b;
300}
301
302int SC_getAllocation(const void *ptr) {
303    GET_TLS();
304    const Allocation *alloc = sc->ptrToAllocation(ptr);
305    return (int)alloc;
306}
307
308void SC_allocationMarkDirty(RsAllocation a) {
309    Allocation *alloc = static_cast<Allocation *>(a);
310    alloc->sendDirty();
311}
312
313void SC_ForEach(RsScript vs,
314                RsAllocation vin,
315                RsAllocation vout,
316                const void *usr) {
317    GET_TLS();
318    const Allocation *ain = static_cast<const Allocation *>(vin);
319    Allocation *aout = static_cast<Allocation *>(vout);
320    Script *s = static_cast<Script *>(vs);
321    s->runForEach(rsc, ain, aout, usr);
322}
323
324void SC_ForEach2(RsScript vs,
325                RsAllocation vin,
326                RsAllocation vout,
327                const void *usr,
328                const RsScriptCall *call) {
329    GET_TLS();
330    const Allocation *ain = static_cast<const Allocation *>(vin);
331    Allocation *aout = static_cast<Allocation *>(vout);
332    Script *s = static_cast<Script *>(vs);
333    s->runForEach(rsc, ain, aout, usr, call);
334}
335
336
337//////////////////////////////////////////////////////////////////////////////
338// Heavy math functions
339//////////////////////////////////////////////////////////////////////////////
340
341typedef struct {
342    float m[16];
343} rs_matrix4x4;
344
345typedef struct {
346    float m[9];
347} rs_matrix3x3;
348
349typedef struct {
350    float m[4];
351} rs_matrix2x2;
352
353static inline void
354rsMatrixSet(rs_matrix4x4 *m, uint32_t row, uint32_t col, float v) {
355    m->m[row * 4 + col] = v;
356}
357
358static inline float
359rsMatrixGet(const rs_matrix4x4 *m, uint32_t row, uint32_t col) {
360    return m->m[row * 4 + col];
361}
362
363static inline void
364rsMatrixSet(rs_matrix3x3 *m, uint32_t row, uint32_t col, float v) {
365    m->m[row * 3 + col] = v;
366}
367
368static inline float
369rsMatrixGet(const rs_matrix3x3 *m, uint32_t row, uint32_t col) {
370    return m->m[row * 3 + col];
371}
372
373static inline void
374rsMatrixSet(rs_matrix2x2 *m, uint32_t row, uint32_t col, float v) {
375    m->m[row * 2 + col] = v;
376}
377
378static inline float
379rsMatrixGet(const rs_matrix2x2 *m, uint32_t row, uint32_t col) {
380    return m->m[row * 2 + col];
381}
382
383
384static void SC_MatrixLoadIdentity_4x4(rs_matrix4x4 *m) {
385    m->m[0] = 1.f;
386    m->m[1] = 0.f;
387    m->m[2] = 0.f;
388    m->m[3] = 0.f;
389    m->m[4] = 0.f;
390    m->m[5] = 1.f;
391    m->m[6] = 0.f;
392    m->m[7] = 0.f;
393    m->m[8] = 0.f;
394    m->m[9] = 0.f;
395    m->m[10] = 1.f;
396    m->m[11] = 0.f;
397    m->m[12] = 0.f;
398    m->m[13] = 0.f;
399    m->m[14] = 0.f;
400    m->m[15] = 1.f;
401}
402
403static void SC_MatrixLoadIdentity_3x3(rs_matrix3x3 *m) {
404    m->m[0] = 1.f;
405    m->m[1] = 0.f;
406    m->m[2] = 0.f;
407    m->m[3] = 0.f;
408    m->m[4] = 1.f;
409    m->m[5] = 0.f;
410    m->m[6] = 0.f;
411    m->m[7] = 0.f;
412    m->m[8] = 1.f;
413}
414
415static void SC_MatrixLoadIdentity_2x2(rs_matrix2x2 *m) {
416    m->m[0] = 1.f;
417    m->m[1] = 0.f;
418    m->m[2] = 0.f;
419    m->m[3] = 1.f;
420}
421
422static void SC_MatrixLoad_4x4_f(rs_matrix4x4 *m, const float *v) {
423    m->m[0] = v[0];
424    m->m[1] = v[1];
425    m->m[2] = v[2];
426    m->m[3] = v[3];
427    m->m[4] = v[4];
428    m->m[5] = v[5];
429    m->m[6] = v[6];
430    m->m[7] = v[7];
431    m->m[8] = v[8];
432    m->m[9] = v[9];
433    m->m[10] = v[10];
434    m->m[11] = v[11];
435    m->m[12] = v[12];
436    m->m[13] = v[13];
437    m->m[14] = v[14];
438    m->m[15] = v[15];
439}
440
441static void SC_MatrixLoad_3x3_f(rs_matrix3x3 *m, const float *v) {
442    m->m[0] = v[0];
443    m->m[1] = v[1];
444    m->m[2] = v[2];
445    m->m[3] = v[3];
446    m->m[4] = v[4];
447    m->m[5] = v[5];
448    m->m[6] = v[6];
449    m->m[7] = v[7];
450    m->m[8] = v[8];
451}
452
453static void SC_MatrixLoad_2x2_f(rs_matrix2x2 *m, const float *v) {
454    m->m[0] = v[0];
455    m->m[1] = v[1];
456    m->m[2] = v[2];
457    m->m[3] = v[3];
458}
459
460static void SC_MatrixLoad_4x4_4x4(rs_matrix4x4 *m, const rs_matrix4x4 *v) {
461    m->m[0] = v->m[0];
462    m->m[1] = v->m[1];
463    m->m[2] = v->m[2];
464    m->m[3] = v->m[3];
465    m->m[4] = v->m[4];
466    m->m[5] = v->m[5];
467    m->m[6] = v->m[6];
468    m->m[7] = v->m[7];
469    m->m[8] = v->m[8];
470    m->m[9] = v->m[9];
471    m->m[10] = v->m[10];
472    m->m[11] = v->m[11];
473    m->m[12] = v->m[12];
474    m->m[13] = v->m[13];
475    m->m[14] = v->m[14];
476    m->m[15] = v->m[15];
477}
478
479static void SC_MatrixLoad_4x4_3x3(rs_matrix4x4 *m, const rs_matrix3x3 *v) {
480    m->m[0] = v->m[0];
481    m->m[1] = v->m[1];
482    m->m[2] = v->m[2];
483    m->m[3] = 0.f;
484    m->m[4] = v->m[3];
485    m->m[5] = v->m[4];
486    m->m[6] = v->m[5];
487    m->m[7] = 0.f;
488    m->m[8] = v->m[6];
489    m->m[9] = v->m[7];
490    m->m[10] = v->m[8];
491    m->m[11] = 0.f;
492    m->m[12] = 0.f;
493    m->m[13] = 0.f;
494    m->m[14] = 0.f;
495    m->m[15] = 1.f;
496}
497
498static void SC_MatrixLoad_4x4_2x2(rs_matrix4x4 *m, const rs_matrix2x2 *v) {
499    m->m[0] = v->m[0];
500    m->m[1] = v->m[1];
501    m->m[2] = 0.f;
502    m->m[3] = 0.f;
503    m->m[4] = v->m[2];
504    m->m[5] = v->m[3];
505    m->m[6] = 0.f;
506    m->m[7] = 0.f;
507    m->m[8] = 0.f;
508    m->m[9] = 0.f;
509    m->m[10] = 1.f;
510    m->m[11] = 0.f;
511    m->m[12] = 0.f;
512    m->m[13] = 0.f;
513    m->m[14] = 0.f;
514    m->m[15] = 1.f;
515}
516
517static void SC_MatrixLoad_3x3_3x3(rs_matrix3x3 *m, const rs_matrix3x3 *v) {
518    m->m[0] = v->m[0];
519    m->m[1] = v->m[1];
520    m->m[2] = v->m[2];
521    m->m[3] = v->m[3];
522    m->m[4] = v->m[4];
523    m->m[5] = v->m[5];
524    m->m[6] = v->m[6];
525    m->m[7] = v->m[7];
526    m->m[8] = v->m[8];
527}
528
529static void SC_MatrixLoad_2x2_2x2(rs_matrix2x2 *m, const rs_matrix2x2 *v) {
530    m->m[0] = v->m[0];
531    m->m[1] = v->m[1];
532    m->m[2] = v->m[2];
533    m->m[3] = v->m[3];
534}
535
536static void SC_MatrixLoadRotate(rs_matrix4x4 *m, float rot, float x, float y, float z) {
537    float c, s;
538    m->m[3] = 0;
539    m->m[7] = 0;
540    m->m[11]= 0;
541    m->m[12]= 0;
542    m->m[13]= 0;
543    m->m[14]= 0;
544    m->m[15]= 1;
545    rot *= (float)(M_PI / 180.0f);
546    c = cos(rot);
547    s = sin(rot);
548
549    const float len = x*x + y*y + z*z;
550    if (len != 1) {
551        const float recipLen = 1.f / sqrt(len);
552        x *= recipLen;
553        y *= recipLen;
554        z *= recipLen;
555    }
556    const float nc = 1.0f - c;
557    const float xy = x * y;
558    const float yz = y * z;
559    const float zx = z * x;
560    const float xs = x * s;
561    const float ys = y * s;
562    const float zs = z * s;
563    m->m[ 0] = x*x*nc +  c;
564    m->m[ 4] =  xy*nc - zs;
565    m->m[ 8] =  zx*nc + ys;
566    m->m[ 1] =  xy*nc + zs;
567    m->m[ 5] = y*y*nc +  c;
568    m->m[ 9] =  yz*nc - xs;
569    m->m[ 2] =  zx*nc - ys;
570    m->m[ 6] =  yz*nc + xs;
571    m->m[10] = z*z*nc +  c;
572}
573
574static void SC_MatrixLoadScale(rs_matrix4x4 *m, float x, float y, float z) {
575    SC_MatrixLoadIdentity_4x4(m);
576    m->m[0] = x;
577    m->m[5] = y;
578    m->m[10] = z;
579}
580
581static void SC_MatrixLoadTranslate(rs_matrix4x4 *m, float x, float y, float z) {
582    SC_MatrixLoadIdentity_4x4(m);
583    m->m[12] = x;
584    m->m[13] = y;
585    m->m[14] = z;
586}
587
588static void SC_MatrixLoadMultiply_4x4_4x4_4x4(rs_matrix4x4 *m, const rs_matrix4x4 *lhs, const rs_matrix4x4 *rhs) {
589    for (int i=0 ; i<4 ; i++) {
590        float ri0 = 0;
591        float ri1 = 0;
592        float ri2 = 0;
593        float ri3 = 0;
594        for (int j=0 ; j<4 ; j++) {
595            const float rhs_ij = rsMatrixGet(rhs, i,j);
596            ri0 += rsMatrixGet(lhs, j, 0) * rhs_ij;
597            ri1 += rsMatrixGet(lhs, j, 1) * rhs_ij;
598            ri2 += rsMatrixGet(lhs, j, 2) * rhs_ij;
599            ri3 += rsMatrixGet(lhs, j, 3) * rhs_ij;
600        }
601        rsMatrixSet(m, i, 0, ri0);
602        rsMatrixSet(m, i, 1, ri1);
603        rsMatrixSet(m, i, 2, ri2);
604        rsMatrixSet(m, i, 3, ri3);
605    }
606}
607
608static void SC_MatrixMultiply_4x4_4x4(rs_matrix4x4 *m, const rs_matrix4x4 *rhs) {
609    rs_matrix4x4 mt;
610    SC_MatrixLoadMultiply_4x4_4x4_4x4(&mt, m, rhs);
611    SC_MatrixLoad_4x4_4x4(m, &mt);
612}
613
614static void SC_MatrixLoadMultiply_3x3_3x3_3x3(rs_matrix3x3 *m, const rs_matrix3x3 *lhs, const rs_matrix3x3 *rhs) {
615    for (int i=0 ; i<3 ; i++) {
616        float ri0 = 0;
617        float ri1 = 0;
618        float ri2 = 0;
619        for (int j=0 ; j<3 ; j++) {
620            const float rhs_ij = rsMatrixGet(rhs, i,j);
621            ri0 += rsMatrixGet(lhs, j, 0) * rhs_ij;
622            ri1 += rsMatrixGet(lhs, j, 1) * rhs_ij;
623            ri2 += rsMatrixGet(lhs, j, 2) * rhs_ij;
624        }
625        rsMatrixSet(m, i, 0, ri0);
626        rsMatrixSet(m, i, 1, ri1);
627        rsMatrixSet(m, i, 2, ri2);
628    }
629}
630
631static void SC_MatrixMultiply_3x3_3x3(rs_matrix3x3 *m, const rs_matrix3x3 *rhs) {
632    rs_matrix3x3 mt;
633    SC_MatrixLoadMultiply_3x3_3x3_3x3(&mt, m, rhs);
634    SC_MatrixLoad_3x3_3x3(m, &mt);
635}
636
637static void SC_MatrixLoadMultiply_2x2_2x2_2x2(rs_matrix2x2 *m, const rs_matrix2x2 *lhs, const rs_matrix2x2 *rhs) {
638    for (int i=0 ; i<2 ; i++) {
639        float ri0 = 0;
640        float ri1 = 0;
641        for (int j=0 ; j<2 ; j++) {
642            const float rhs_ij = rsMatrixGet(rhs, i,j);
643            ri0 += rsMatrixGet(lhs, j, 0) * rhs_ij;
644            ri1 += rsMatrixGet(lhs, j, 1) * rhs_ij;
645        }
646        rsMatrixSet(m, i, 0, ri0);
647        rsMatrixSet(m, i, 1, ri1);
648    }
649}
650
651static void SC_MatrixMultiply_2x2_2x2(rs_matrix2x2 *m, const rs_matrix2x2 *rhs) {
652    rs_matrix2x2 mt;
653    SC_MatrixLoadMultiply_2x2_2x2_2x2(&mt, m, rhs);
654    SC_MatrixLoad_2x2_2x2(m, &mt);
655}
656
657static void SC_MatrixRotate(rs_matrix4x4 *m, float rot, float x, float y, float z) {
658    rs_matrix4x4 m1;
659    SC_MatrixLoadRotate(&m1, rot, x, y, z);
660    SC_MatrixMultiply_4x4_4x4(m, &m1);
661}
662
663static void SC_MatrixScale(rs_matrix4x4 *m, float x, float y, float z) {
664    rs_matrix4x4 m1;
665    SC_MatrixLoadScale(&m1, x, y, z);
666    SC_MatrixMultiply_4x4_4x4(m, &m1);
667}
668
669static void SC_MatrixTranslate(rs_matrix4x4 *m, float x, float y, float z) {
670    rs_matrix4x4 m1;
671    SC_MatrixLoadTranslate(&m1, x, y, z);
672    SC_MatrixMultiply_4x4_4x4(m, &m1);
673}
674
675static void SC_MatrixLoadOrtho(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far) {
676    SC_MatrixLoadIdentity_4x4(m);
677    m->m[0] = 2.f / (right - left);
678    m->m[5] = 2.f / (top - bottom);
679    m->m[10]= -2.f / (far - near);
680    m->m[12]= -(right + left) / (right - left);
681    m->m[13]= -(top + bottom) / (top - bottom);
682    m->m[14]= -(far + near) / (far - near);
683}
684
685static void SC_MatrixLoadFrustum(rs_matrix4x4 *m, float left, float right, float bottom, float top, float near, float far) {
686    SC_MatrixLoadIdentity_4x4(m);
687    m->m[0] = 2.f * near / (right - left);
688    m->m[5] = 2.f * near / (top - bottom);
689    m->m[8] = (right + left) / (right - left);
690    m->m[9] = (top + bottom) / (top - bottom);
691    m->m[10]= -(far + near) / (far - near);
692    m->m[11]= -1.f;
693    m->m[14]= -2.f * far * near / (far - near);
694    m->m[15]= 0.f;
695}
696
697static void SC_MatrixLoadPerspective(rs_matrix4x4* m, float fovy, float aspect, float near, float far) {
698    float top = near * tan((float) (fovy * M_PI / 360.0f));
699    float bottom = -top;
700    float left = bottom * aspect;
701    float right = top * aspect;
702    SC_MatrixLoadFrustum(m, left, right, bottom, top, near, far);
703}
704
705
706// Returns true if the matrix was successfully inversed
707static bool SC_MatrixInverse_4x4(rs_matrix4x4 *m) {
708    rs_matrix4x4 result;
709
710    int i, j;
711    for (i = 0; i < 4; ++i) {
712        for (j = 0; j < 4; ++j) {
713            // computeCofactor for int i, int j
714            int c0 = (i+1) % 4;
715            int c1 = (i+2) % 4;
716            int c2 = (i+3) % 4;
717            int r0 = (j+1) % 4;
718            int r1 = (j+2) % 4;
719            int r2 = (j+3) % 4;
720
721            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]))
722                         - (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]))
723                         + (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]));
724
725            float cofactor = (i+j) & 1 ? -minor : minor;
726
727            result.m[4*i + j] = cofactor;
728        }
729    }
730
731    // Dot product of 0th column of source and 0th row of result
732    float det = m->m[0]*result.m[0] + m->m[4]*result.m[1] +
733                 m->m[8]*result.m[2] + m->m[12]*result.m[3];
734
735    if (fabs(det) < 1e-6) {
736        return false;
737    }
738
739    det = 1.0f / det;
740    for (i = 0; i < 16; ++i) {
741        m->m[i] = result.m[i] * det;
742    }
743
744    return true;
745}
746
747// Returns true if the matrix was successfully inversed
748static bool SC_MatrixInverseTranspose_4x4(rs_matrix4x4 *m) {
749    rs_matrix4x4 result;
750
751    int i, j;
752    for (i = 0; i < 4; ++i) {
753        for (j = 0; j < 4; ++j) {
754            // computeCofactor for int i, int j
755            int c0 = (i+1) % 4;
756            int c1 = (i+2) % 4;
757            int c2 = (i+3) % 4;
758            int r0 = (j+1) % 4;
759            int r1 = (j+2) % 4;
760            int r2 = (j+3) % 4;
761
762            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]))
763                         - (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]))
764                         + (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]));
765
766            float cofactor = (i+j) & 1 ? -minor : minor;
767
768            result.m[4*j + i] = cofactor;
769        }
770    }
771
772    // Dot product of 0th column of source and 0th column of result
773    float det = m->m[0]*result.m[0] + m->m[4]*result.m[4] +
774                 m->m[8]*result.m[8] + m->m[12]*result.m[12];
775
776    if (fabs(det) < 1e-6) {
777        return false;
778    }
779
780    det = 1.0f / det;
781    for (i = 0; i < 16; ++i) {
782        m->m[i] = result.m[i] * det;
783    }
784
785    return true;
786}
787
788static void SC_MatrixTranspose_4x4(rs_matrix4x4 *m) {
789    int i, j;
790    float temp;
791    for (i = 0; i < 3; ++i) {
792        for (j = i + 1; j < 4; ++j) {
793            temp = m->m[i*4 + j];
794            m->m[i*4 + j] = m->m[j*4 + i];
795            m->m[j*4 + i] = temp;
796        }
797    }
798}
799
800static void SC_MatrixTranspose_3x3(rs_matrix3x3 *m) {
801    int i, j;
802    float temp;
803    for (i = 0; i < 2; ++i) {
804        for (j = i + 1; j < 3; ++j) {
805            temp = m->m[i*3 + j];
806            m->m[i*3 + j] = m->m[j*4 + i];
807            m->m[j*3 + i] = temp;
808        }
809    }
810}
811
812static void SC_MatrixTranspose_2x2(rs_matrix2x2 *m) {
813    float temp = m->m[1];
814    m->m[1] = m->m[2];
815    m->m[2] = temp;
816}
817
818
819//////////////////////////////////////////////////////////////////////////////
820// Class implementation
821//////////////////////////////////////////////////////////////////////////////
822
823// llvm name mangling ref
824//  <builtin-type> ::= v  # void
825//                 ::= b  # bool
826//                 ::= c  # char
827//                 ::= a  # signed char
828//                 ::= h  # unsigned char
829//                 ::= s  # short
830//                 ::= t  # unsigned short
831//                 ::= i  # int
832//                 ::= j  # unsigned int
833//                 ::= l  # long
834//                 ::= m  # unsigned long
835//                 ::= x  # long long, __int64
836//                 ::= y  # unsigned long long, __int64
837//                 ::= f  # float
838//                 ::= d  # double
839
840static ScriptCState::SymbolTable_t gSyms[] = {
841    { "__divsi3", (void *)&SC_divsi3, true },
842    { "__modsi3", (void *)&SC_modsi3, true },
843    { "__udivsi3", (void *)&SC_udivsi3, true },
844    { "__umodsi3", (void *)&SC_umodsi3, true },
845    { "memset", (void *)&memset, true },
846    { "memcpy", (void *)&memcpy, true },
847
848    // allocation
849    { "_Z19rsAllocationGetDimX13rs_allocation", (void *)&SC_allocGetDimX, true },
850    { "_Z19rsAllocationGetDimY13rs_allocation", (void *)&SC_allocGetDimY, true },
851    { "_Z19rsAllocationGetDimZ13rs_allocation", (void *)&SC_allocGetDimZ, true },
852    { "_Z21rsAllocationGetDimLOD13rs_allocation", (void *)&SC_allocGetDimLOD, true },
853    { "_Z23rsAllocationGetDimFaces13rs_allocation", (void *)&SC_allocGetDimFaces, true },
854    { "_Z15rsGetAllocationPKv", (void *)&SC_getAllocation, true },
855
856    { "_Z14rsGetElementAt13rs_allocationj", (void *)&SC_getElementAtX, true },
857    { "_Z14rsGetElementAt13rs_allocationjj", (void *)&SC_getElementAtXY, true },
858    { "_Z14rsGetElementAt13rs_allocationjjj", (void *)&SC_getElementAtXYZ, true },
859
860    { "_Z11rsSetObjectP10rs_elementS_", (void *)&rsiSetObject, true },
861    { "_Z13rsClearObjectP10rs_element", (void *)&rsiClearObject, true },
862    { "_Z10rsIsObject10rs_element", (void *)&rsiIsObject, true },
863
864    { "_Z11rsSetObjectP7rs_typeS_", (void *)&rsiSetObject, true },
865    { "_Z13rsClearObjectP7rs_type", (void *)&rsiClearObject, true },
866    { "_Z10rsIsObject7rs_type", (void *)&rsiIsObject, true },
867
868    { "_Z11rsSetObjectP13rs_allocationS_", (void *)&rsiSetObject, true },
869    { "_Z13rsClearObjectP13rs_allocation", (void *)&rsiClearObject, true },
870    { "_Z10rsIsObject13rs_allocation", (void *)&rsiIsObject, true },
871
872    { "_Z11rsSetObjectP10rs_samplerS_", (void *)&rsiSetObject, true },
873    { "_Z13rsClearObjectP10rs_sampler", (void *)&rsiClearObject, true },
874    { "_Z10rsIsObject10rs_sampler", (void *)&rsiIsObject, true },
875
876    { "_Z11rsSetObjectP9rs_scriptS_", (void *)&rsiSetObject, true },
877    { "_Z13rsClearObjectP9rs_script", (void *)&rsiClearObject, true },
878    { "_Z10rsIsObject9rs_script", (void *)&rsiIsObject, true },
879
880    { "_Z11rsSetObjectP7rs_meshS_", (void *)&rsiSetObject, true },
881    { "_Z13rsClearObjectP7rs_mesh", (void *)&rsiClearObject, true },
882    { "_Z10rsIsObject7rs_mesh", (void *)&rsiIsObject, true },
883
884    { "_Z11rsSetObjectP19rs_program_fragmentS_", (void *)&rsiSetObject, true },
885    { "_Z13rsClearObjectP19rs_program_fragment", (void *)&rsiClearObject, true },
886    { "_Z10rsIsObject19rs_program_fragment", (void *)&rsiIsObject, true },
887
888    { "_Z11rsSetObjectP17rs_program_vertexS_", (void *)&rsiSetObject, true },
889    { "_Z13rsClearObjectP17rs_program_vertex", (void *)&rsiClearObject, true },
890    { "_Z10rsIsObject17rs_program_vertex", (void *)&rsiIsObject, true },
891
892    { "_Z11rsSetObjectP17rs_program_rasterS_", (void *)&rsiSetObject, true },
893    { "_Z13rsClearObjectP17rs_program_raster", (void *)&rsiClearObject, true },
894    { "_Z10rsIsObject17rs_program_raster", (void *)&rsiIsObject, true },
895
896    { "_Z11rsSetObjectP16rs_program_storeS_", (void *)&rsiSetObject, true },
897    { "_Z13rsClearObjectP16rs_program_store", (void *)&rsiClearObject, true },
898    { "_Z10rsIsObject16rs_program_store", (void *)&rsiIsObject, true },
899
900    { "_Z11rsSetObjectP7rs_fontS_", (void *)&rsiSetObject, true },
901    { "_Z13rsClearObjectP7rs_font", (void *)&rsiClearObject, true },
902    { "_Z10rsIsObject7rs_font", (void *)&rsiIsObject, true },
903
904
905    { "_Z21rsAllocationMarkDirty13rs_allocation", (void *)&SC_allocationMarkDirty, true },
906
907
908    // Debug
909    { "_Z7rsDebugPKcf", (void *)&SC_debugF, true },
910    { "_Z7rsDebugPKcff", (void *)&SC_debugFv2, true },
911    { "_Z7rsDebugPKcfff", (void *)&SC_debugFv3, true },
912    { "_Z7rsDebugPKcffff", (void *)&SC_debugFv4, true },
913    { "_Z7rsDebugPKcd", (void *)&SC_debugD, true },
914    { "_Z7rsDebugPKcPK12rs_matrix4x4", (void *)&SC_debugFM4v4, true },
915    { "_Z7rsDebugPKcPK12rs_matrix3x3", (void *)&SC_debugFM3v3, true },
916    { "_Z7rsDebugPKcPK12rs_matrix2x2", (void *)&SC_debugFM2v2, true },
917    { "_Z7rsDebugPKci", (void *)&SC_debugI32, true },
918    { "_Z7rsDebugPKcj", (void *)&SC_debugU32, true },
919    // Both "long" and "unsigned long" need to be redirected to their
920    // 64-bit counterparts, since we have hacked Slang to use 64-bit
921    // for "long" on Arm (to be similar to Java).
922    { "_Z7rsDebugPKcl", (void *)&SC_debugLL64, true },
923    { "_Z7rsDebugPKcm", (void *)&SC_debugULL64, true },
924    { "_Z7rsDebugPKcx", (void *)&SC_debugLL64, true },
925    { "_Z7rsDebugPKcy", (void *)&SC_debugULL64, true },
926    { "_Z7rsDebugPKcPKv", (void *)&SC_debugP, true },
927
928    // RS Math
929    { "_Z6rsRandi", (void *)&SC_randi, true },
930    { "_Z6rsRandii", (void *)&SC_randi2, true },
931    { "_Z6rsRandf", (void *)&SC_randf, true },
932    { "_Z6rsRandff", (void *)&SC_randf2, true },
933    { "_Z6rsFracf", (void *)&SC_frac, true },
934
935    // time
936    { "_Z6rsTimePi", (void *)&SC_time, true },
937    { "_Z11rsLocaltimeP5rs_tmPKi", (void *)&SC_localtime, true },
938    { "_Z14rsUptimeMillisv", (void*)&SC_uptimeMillis, true },
939    { "_Z13rsUptimeNanosv", (void*)&SC_uptimeNanos, true },
940    { "_Z7rsGetDtv", (void*)&SC_getDt, false },
941
942    { "_Z14rsSendToClienti", (void *)&SC_toClient, false },
943    { "_Z14rsSendToClientiPKvj", (void *)&SC_toClient2, false },
944    { "_Z22rsSendToClientBlockingi", (void *)&SC_toClientBlocking, false },
945    { "_Z22rsSendToClientBlockingiPKvj", (void *)&SC_toClientBlocking2, false },
946
947    // matrix
948    { "_Z20rsMatrixLoadIdentityP12rs_matrix4x4", (void *)&SC_MatrixLoadIdentity_4x4, true },
949    { "_Z20rsMatrixLoadIdentityP12rs_matrix3x3", (void *)&SC_MatrixLoadIdentity_3x3, true },
950    { "_Z20rsMatrixLoadIdentityP12rs_matrix2x2", (void *)&SC_MatrixLoadIdentity_2x2, true },
951
952    { "_Z12rsMatrixLoadP12rs_matrix4x4PKf", (void *)&SC_MatrixLoad_4x4_f, true },
953    { "_Z12rsMatrixLoadP12rs_matrix3x3PKf", (void *)&SC_MatrixLoad_3x3_f, true },
954    { "_Z12rsMatrixLoadP12rs_matrix2x2PKf", (void *)&SC_MatrixLoad_2x2_f, true },
955
956    { "_Z12rsMatrixLoadP12rs_matrix4x4PKS_", (void *)&SC_MatrixLoad_4x4_4x4, true },
957    { "_Z12rsMatrixLoadP12rs_matrix4x4PK12rs_matrix3x3", (void *)&SC_MatrixLoad_4x4_3x3, true },
958    { "_Z12rsMatrixLoadP12rs_matrix4x4PK12rs_matrix2x2", (void *)&SC_MatrixLoad_4x4_2x2, true },
959    { "_Z12rsMatrixLoadP12rs_matrix3x3PKS_", (void *)&SC_MatrixLoad_3x3_3x3, true },
960    { "_Z12rsMatrixLoadP12rs_matrix2x2PKS_", (void *)&SC_MatrixLoad_2x2_2x2, true },
961
962    { "_Z18rsMatrixLoadRotateP12rs_matrix4x4ffff", (void *)&SC_MatrixLoadRotate, true },
963    { "_Z17rsMatrixLoadScaleP12rs_matrix4x4fff", (void *)&SC_MatrixLoadScale, true },
964    { "_Z21rsMatrixLoadTranslateP12rs_matrix4x4fff", (void *)&SC_MatrixLoadTranslate, true },
965    { "_Z14rsMatrixRotateP12rs_matrix4x4ffff", (void *)&SC_MatrixRotate, true },
966    { "_Z13rsMatrixScaleP12rs_matrix4x4fff", (void *)&SC_MatrixScale, true },
967    { "_Z17rsMatrixTranslateP12rs_matrix4x4fff", (void *)&SC_MatrixTranslate, true },
968
969    { "_Z20rsMatrixLoadMultiplyP12rs_matrix4x4PKS_S2_", (void *)&SC_MatrixLoadMultiply_4x4_4x4_4x4, true },
970    { "_Z16rsMatrixMultiplyP12rs_matrix4x4PKS_", (void *)&SC_MatrixMultiply_4x4_4x4, true },
971    { "_Z20rsMatrixLoadMultiplyP12rs_matrix3x3PKS_S2_", (void *)&SC_MatrixLoadMultiply_3x3_3x3_3x3, true },
972    { "_Z16rsMatrixMultiplyP12rs_matrix3x3PKS_", (void *)&SC_MatrixMultiply_3x3_3x3, true },
973    { "_Z20rsMatrixLoadMultiplyP12rs_matrix2x2PKS_S2_", (void *)&SC_MatrixLoadMultiply_2x2_2x2_2x2, true },
974    { "_Z16rsMatrixMultiplyP12rs_matrix2x2PKS_", (void *)&SC_MatrixMultiply_2x2_2x2, true },
975
976    { "_Z17rsMatrixLoadOrthoP12rs_matrix4x4ffffff", (void *)&SC_MatrixLoadOrtho, true },
977    { "_Z19rsMatrixLoadFrustumP12rs_matrix4x4ffffff", (void *)&SC_MatrixLoadFrustum, true },
978    { "_Z23rsMatrixLoadPerspectiveP12rs_matrix4x4ffff", (void *)&SC_MatrixLoadPerspective, true },
979
980    { "_Z15rsMatrixInverseP12rs_matrix4x4", (void *)&SC_MatrixInverse_4x4, true },
981    { "_Z24rsMatrixInverseTransposeP12rs_matrix4x4", (void *)&SC_MatrixInverseTranspose_4x4, true },
982    { "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_4x4, true },
983    { "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_3x3, true },
984    { "_Z17rsMatrixTransposeP12rs_matrix4x4", (void *)&SC_MatrixTranspose_2x2, true },
985
986    { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach, false },
987    //{ "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach2, false },
988
989////////////////////////////////////////////////////////////////////
990
991    //{ "sinf_fast", (void *)&SC_sinf_fast, true },
992    //{ "cosf_fast", (void *)&SC_cosf_fast, true },
993
994    { NULL, NULL, false }
995};
996
997const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbol(const char *sym) {
998    ScriptCState::SymbolTable_t *syms = gSyms;
999
1000    while (syms->mPtr) {
1001        if (!strcmp(syms->mName, sym)) {
1002            return syms;
1003        }
1004        syms++;
1005    }
1006    return NULL;
1007}
1008
1009