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