rsScriptC_Lib.cpp revision df09719cbeb426a4c8279f2ce226b5874ad7c2c9
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{
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{
58    x += float(M_PI / 2);
59
60    const float A =   1.0f / (2.0f * M_PI);
61    const float B = -16.0f;
62    const float C =   8.0f;
63
64    // scale angle for easy argument reduction
65    x *= A;
66
67    if (fabsf(x) >= 0.5f) {
68        // argument reduction
69        x = x - ceilf(x + 0.5f) + 1.0f;
70    }
71
72    const float y = B * x * fabsf(x) + C * x;
73    return 0.2215f * (y * fabsf(y) - y) + y;
74}
75
76
77static float SC_randf(float max)
78{
79    float r = (float)rand();
80    return r / RAND_MAX * max;
81}
82
83static float SC_randf2(float min, float max)
84{
85    float r = (float)rand();
86    return r / RAND_MAX * (max - min) + min;
87}
88
89static int SC_randi(int max)
90{
91    return (int)SC_randf(max);
92}
93
94static int SC_randi2(int min, int max)
95{
96    return (int)SC_randf2(min, max);
97}
98
99static float SC_frac(float v)
100{
101    int i = (int)floor(v);
102    return fmin(v - i, 0x1.fffffep-1f);
103}
104
105//////////////////////////////////////////////////////////////////////////////
106// Time routines
107//////////////////////////////////////////////////////////////////////////////
108
109static int32_t SC_second()
110{
111    GET_TLS();
112
113    time_t rawtime;
114    time(&rawtime);
115
116    struct tm *timeinfo;
117    timeinfo = localtime(&rawtime);
118    return timeinfo->tm_sec;
119}
120
121static int32_t SC_minute()
122{
123    GET_TLS();
124
125    time_t rawtime;
126    time(&rawtime);
127
128    struct tm *timeinfo;
129    timeinfo = localtime(&rawtime);
130    return timeinfo->tm_min;
131}
132
133static int32_t SC_hour()
134{
135    GET_TLS();
136
137    time_t rawtime;
138    time(&rawtime);
139
140    struct tm *timeinfo;
141    timeinfo = localtime(&rawtime);
142    return timeinfo->tm_hour;
143}
144
145static int32_t SC_day()
146{
147    GET_TLS();
148
149    time_t rawtime;
150    time(&rawtime);
151
152    struct tm *timeinfo;
153    timeinfo = localtime(&rawtime);
154    return timeinfo->tm_mday;
155}
156
157static int32_t SC_month()
158{
159    GET_TLS();
160
161    time_t rawtime;
162    time(&rawtime);
163
164    struct tm *timeinfo;
165    timeinfo = localtime(&rawtime);
166    return timeinfo->tm_mon;
167}
168
169static int32_t SC_year()
170{
171    GET_TLS();
172
173    time_t rawtime;
174    time(&rawtime);
175
176    struct tm *timeinfo;
177    timeinfo = localtime(&rawtime);
178    return timeinfo->tm_year;
179}
180
181static int64_t SC_uptimeMillis()
182{
183    return nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
184}
185
186static int64_t SC_uptimeNanos()
187{
188    return systemTime(SYSTEM_TIME_MONOTONIC);
189}
190
191static float SC_getDt()
192{
193    GET_TLS();
194    int64_t l = sc->mEnviroment.mLastDtTime;
195    sc->mEnviroment.mLastDtTime = systemTime(SYSTEM_TIME_MONOTONIC);
196    return ((float)(sc->mEnviroment.mLastDtTime - l)) / 1.0e9;
197}
198
199
200//////////////////////////////////////////////////////////////////////////////
201//
202//////////////////////////////////////////////////////////////////////////////
203
204static uint32_t SC_allocGetDimX(RsAllocation va)
205{
206    const Allocation *a = static_cast<const Allocation *>(va);
207    CHECK_OBJ(a);
208    //LOGE("SC_allocGetDimX a=%p  type=%p", a, a->getType());
209    return a->getType()->getDimX();
210}
211
212static uint32_t SC_allocGetDimY(RsAllocation va)
213{
214    const Allocation *a = static_cast<const Allocation *>(va);
215    CHECK_OBJ(a);
216    return a->getType()->getDimY();
217}
218
219static uint32_t SC_allocGetDimZ(RsAllocation va)
220{
221    const Allocation *a = static_cast<const Allocation *>(va);
222    CHECK_OBJ(a);
223    return a->getType()->getDimZ();
224}
225
226static uint32_t SC_allocGetDimLOD(RsAllocation va)
227{
228    const Allocation *a = static_cast<const Allocation *>(va);
229    CHECK_OBJ(a);
230    return a->getType()->getDimLOD();
231}
232
233static uint32_t SC_allocGetDimFaces(RsAllocation va)
234{
235    const Allocation *a = static_cast<const Allocation *>(va);
236    CHECK_OBJ(a);
237    return a->getType()->getDimFaces();
238}
239
240static const void * SC_getElementAtX(RsAllocation va, uint32_t x)
241{
242    const Allocation *a = static_cast<const Allocation *>(va);
243    CHECK_OBJ(a);
244    const Type *t = a->getType();
245    CHECK_OBJ(t);
246    const uint8_t *p = (const uint8_t *)a->getPtr();
247    return &p[t->getElementSizeBytes() * x];
248}
249
250static const void * SC_getElementAtXY(RsAllocation va, uint32_t x, uint32_t y)
251{
252    const Allocation *a = static_cast<const Allocation *>(va);
253    CHECK_OBJ(a);
254    const Type *t = a->getType();
255    CHECK_OBJ(t);
256    const uint8_t *p = (const uint8_t *)a->getPtr();
257    return &p[t->getElementSizeBytes() * (x + y*t->getDimX())];
258}
259
260static const void * SC_getElementAtXYZ(RsAllocation va, uint32_t x, uint32_t y, uint32_t z)
261{
262    const Allocation *a = static_cast<const Allocation *>(va);
263    CHECK_OBJ(a);
264    const Type *t = a->getType();
265    CHECK_OBJ(t);
266    const uint8_t *p = (const uint8_t *)a->getPtr();
267    return &p[t->getElementSizeBytes() * (x + y*t->getDimX())];
268}
269
270static void SC_setObject(void **vdst, void * vsrc) {
271    //LOGE("SC_setObject  %p,%p  %p", vdst, *vdst, vsrc);
272    if (vsrc) {
273        CHECK_OBJ(vsrc);
274        static_cast<ObjectBase *>(vsrc)->incSysRef();
275    }
276    if (vdst[0]) {
277        CHECK_OBJ(vdst[0]);
278        static_cast<ObjectBase *>(vdst[0])->decSysRef();
279    }
280    *vdst = vsrc;
281    //LOGE("SC_setObject *");
282}
283static void SC_clearObject(void **vdst) {
284    //LOGE("SC_clearObject  %p,%p", vdst, *vdst);
285    if (vdst[0]) {
286        CHECK_OBJ(vdst[0]);
287        static_cast<ObjectBase *>(vdst[0])->decSysRef();
288    }
289    *vdst = NULL;
290    //LOGE("SC_clearObject *");
291}
292static bool SC_isObject(RsAllocation vsrc) {
293    return vsrc != NULL;
294}
295
296
297
298static void SC_debugF(const char *s, float f) {
299    LOGE("%s %f, 0x%08x", s, f, *((int *) (&f)));
300}
301static void SC_debugFv2(const char *s, float f1, float f2) {
302    LOGE("%s {%f, %f}", s, f1, f2);
303}
304static void SC_debugFv3(const char *s, float f1, float f2, float f3) {
305    LOGE("%s {%f, %f, %f}", s, f1, f2, f3);
306}
307static void SC_debugFv4(const char *s, float f1, float f2, float f3, float f4) {
308    LOGE("%s {%f, %f, %f, %f}", s, f1, f2, f3, f4);
309}
310static void SC_debugD(const char *s, double d) {
311    LOGE("%s %f, 0x%08llx", s, d, *((long long *) (&d)));
312}
313static void SC_debugFM4v4(const char *s, const float *f) {
314    LOGE("%s {%f, %f, %f, %f", s, f[0], f[4], f[8], f[12]);
315    LOGE("%s  %f, %f, %f, %f", s, f[1], f[5], f[9], f[13]);
316    LOGE("%s  %f, %f, %f, %f", s, f[2], f[6], f[10], f[14]);
317    LOGE("%s  %f, %f, %f, %f}", s, f[3], f[7], f[11], f[15]);
318}
319static void SC_debugFM3v3(const char *s, const float *f) {
320    LOGE("%s {%f, %f, %f", s, f[0], f[3], f[6]);
321    LOGE("%s  %f, %f, %f", s, f[1], f[4], f[7]);
322    LOGE("%s  %f, %f, %f}",s, f[2], f[5], f[8]);
323}
324static void SC_debugFM2v2(const char *s, const float *f) {
325    LOGE("%s {%f, %f", s, f[0], f[2]);
326    LOGE("%s  %f, %f}",s, f[1], f[3]);
327}
328
329static void SC_debugI32(const char *s, int32_t i) {
330    LOGE("%s %i  0x%x", s, i, i);
331}
332static void SC_debugU32(const char *s, uint32_t i) {
333    LOGE("%s %u  0x%x", s, i, i);
334}
335static void SC_debugLL64(const char *s, long long ll) {
336    LOGE("%s %lld  0x%llx", s, ll, ll);
337}
338static void SC_debugULL64(const char *s, unsigned long long ll) {
339    LOGE("%s %llu  0x%llx", s, ll, ll);
340}
341
342static void SC_debugP(const char *s, const void *p) {
343    LOGE("%s %p", s, p);
344}
345
346static uint32_t SC_toClient2(int cmdID, void *data, int len)
347{
348    GET_TLS();
349    //LOGE("SC_toClient %i %i %i", cmdID, len);
350    return rsc->sendMessageToClient(data, cmdID, len, false);
351}
352
353static uint32_t SC_toClient(int cmdID)
354{
355    GET_TLS();
356    //LOGE("SC_toClient %i", cmdID);
357    return rsc->sendMessageToClient(NULL, cmdID, 0, false);
358}
359
360static uint32_t SC_toClientBlocking2(int cmdID, void *data, int len)
361{
362    GET_TLS();
363    //LOGE("SC_toClientBlocking %i %i", cmdID, len);
364    return rsc->sendMessageToClient(data, cmdID, len, true);
365}
366
367static uint32_t SC_toClientBlocking(int cmdID)
368{
369    GET_TLS();
370    //LOGE("SC_toClientBlocking %i", cmdID);
371    return rsc->sendMessageToClient(NULL, cmdID, 0, true);
372}
373
374int SC_divsi3(int a, int b)
375{
376    return a / b;
377}
378
379int SC_getAllocation(const void *ptr)
380{
381    GET_TLS();
382    const Allocation *alloc = sc->ptrToAllocation(ptr);
383    return (int)alloc;
384}
385
386void SC_allocationMarkDirty(RsAllocation a)
387{
388    Allocation *alloc = static_cast<Allocation *>(a);
389    alloc->sendDirty();
390}
391
392void SC_ForEach(RsScript vs,
393                RsAllocation vin,
394                RsAllocation vout,
395                const void *usr)
396{
397    GET_TLS();
398    const Allocation *ain = static_cast<const Allocation *>(vin);
399    Allocation *aout = static_cast<Allocation *>(vout);
400    Script *s = static_cast<Script *>(vs);
401    s->runForEach(rsc, ain, aout, usr);
402}
403
404void SC_ForEach2(RsScript vs,
405                RsAllocation vin,
406                RsAllocation vout,
407                const void *usr,
408                const RsScriptCall *call)
409{
410    GET_TLS();
411    const Allocation *ain = static_cast<const Allocation *>(vin);
412    Allocation *aout = static_cast<Allocation *>(vout);
413    Script *s = static_cast<Script *>(vs);
414    s->runForEach(rsc, ain, aout, usr, call);
415}
416
417//////////////////////////////////////////////////////////////////////////////
418// Class implementation
419//////////////////////////////////////////////////////////////////////////////
420
421// llvm name mangling ref
422//  <builtin-type> ::= v  # void
423//                 ::= b  # bool
424//                 ::= c  # char
425//                 ::= a  # signed char
426//                 ::= h  # unsigned char
427//                 ::= s  # short
428//                 ::= t  # unsigned short
429//                 ::= i  # int
430//                 ::= j  # unsigned int
431//                 ::= l  # long
432//                 ::= m  # unsigned long
433//                 ::= x  # long long, __int64
434//                 ::= y  # unsigned long long, __int64
435//                 ::= f  # float
436//                 ::= d  # double
437
438static ScriptCState::SymbolTable_t gSyms[] = {
439    { "__divsi3", (void *)&SC_divsi3 },
440
441    // allocation
442    { "_Z19rsAllocationGetDimX13rs_allocation", (void *)&SC_allocGetDimX },
443    { "_Z19rsAllocationGetDimY13rs_allocation", (void *)&SC_allocGetDimY },
444    { "_Z19rsAllocationGetDimZ13rs_allocation", (void *)&SC_allocGetDimZ },
445    { "_Z21rsAllocationGetDimLOD13rs_allocation", (void *)&SC_allocGetDimLOD },
446    { "_Z23rsAllocationGetDimFaces13rs_allocation", (void *)&SC_allocGetDimFaces },
447    { "_Z15rsGetAllocationPKv", (void *)&SC_getAllocation },
448
449    { "_Z14rsGetElementAt13rs_allocationj", (void *)&SC_getElementAtX },
450    { "_Z14rsGetElementAt13rs_allocationjj", (void *)&SC_getElementAtXY },
451    { "_Z14rsGetElementAt13rs_allocationjjj", (void *)&SC_getElementAtXYZ },
452
453    { "_Z11rsSetObjectP10rs_elementS_", (void *)&SC_setObject },
454    { "_Z13rsClearObjectP10rs_element", (void *)&SC_clearObject },
455    { "_Z10rsIsObject10rs_element", (void *)&SC_isObject },
456
457    { "_Z11rsSetObjectP7rs_typeS_", (void *)&SC_setObject },
458    { "_Z13rsClearObjectP7rs_type", (void *)&SC_clearObject },
459    { "_Z10rsIsObject7rs_type", (void *)&SC_isObject },
460
461    { "_Z11rsSetObjectP13rs_allocationS_", (void *)&SC_setObject },
462    { "_Z13rsClearObjectP13rs_allocation", (void *)&SC_clearObject },
463    { "_Z10rsIsObject13rs_allocation", (void *)&SC_isObject },
464
465    { "_Z11rsSetObjectP10rs_samplerS_", (void *)&SC_setObject },
466    { "_Z13rsClearObjectP10rs_sampler", (void *)&SC_clearObject },
467    { "_Z10rsIsObject10rs_sampler", (void *)&SC_isObject },
468
469    { "_Z11rsSetObjectP9rs_scriptS_", (void *)&SC_setObject },
470    { "_Z13rsClearObjectP9rs_script", (void *)&SC_clearObject },
471    { "_Z10rsIsObject9rs_script", (void *)&SC_isObject },
472
473    { "_Z11rsSetObjectP7rs_meshS_", (void *)&SC_setObject },
474    { "_Z13rsClearObjectP7rs_mesh", (void *)&SC_clearObject },
475    { "_Z10rsIsObject7rs_mesh", (void *)&SC_isObject },
476
477    { "_Z11rsSetObjectP19rs_program_fragmentS_", (void *)&SC_setObject },
478    { "_Z13rsClearObjectP19rs_program_fragment", (void *)&SC_clearObject },
479    { "_Z10rsIsObject19rs_program_fragment", (void *)&SC_isObject },
480
481    { "_Z11rsSetObjectP17rs_program_vertexS_", (void *)&SC_setObject },
482    { "_Z13rsClearObjectP17rs_program_vertex", (void *)&SC_clearObject },
483    { "_Z10rsIsObject17rs_program_vertex", (void *)&SC_isObject },
484
485    { "_Z11rsSetObjectP17rs_program_rasterS_", (void *)&SC_setObject },
486    { "_Z13rsClearObjectP17rs_program_raster", (void *)&SC_clearObject },
487    { "_Z10rsIsObject17rs_program_raster", (void *)&SC_isObject },
488
489    { "_Z11rsSetObjectP16rs_program_storeS_", (void *)&SC_setObject },
490    { "_Z13rsClearObjectP16rs_program_store", (void *)&SC_clearObject },
491    { "_Z10rsIsObject16rs_program_store", (void *)&SC_isObject },
492
493    { "_Z11rsSetObjectP7rs_fontS_", (void *)&SC_setObject },
494    { "_Z13rsClearObjectP7rs_font", (void *)&SC_clearObject },
495    { "_Z10rsIsObject7rs_font", (void *)&SC_isObject },
496
497
498    { "_Z21rsAllocationMarkDirty13rs_allocation", (void *)&SC_allocationMarkDirty },
499
500
501    // Debug
502    { "_Z7rsDebugPKcf", (void *)&SC_debugF },
503    { "_Z7rsDebugPKcff", (void *)&SC_debugFv2 },
504    { "_Z7rsDebugPKcfff", (void *)&SC_debugFv3 },
505    { "_Z7rsDebugPKcffff", (void *)&SC_debugFv4 },
506    { "_Z7rsDebugPKcd", (void *)&SC_debugD },
507    { "_Z7rsDebugPKcPK12rs_matrix4x4", (void *)&SC_debugFM4v4 },
508    { "_Z7rsDebugPKcPK12rs_matrix3x3", (void *)&SC_debugFM3v3 },
509    { "_Z7rsDebugPKcPK12rs_matrix2x2", (void *)&SC_debugFM2v2 },
510    { "_Z7rsDebugPKci", (void *)&SC_debugI32 },
511    { "_Z7rsDebugPKcj", (void *)&SC_debugU32 },
512    // Both "long" and "unsigned long" need to be redirected to their
513    // 64-bit counterparts, since we have hacked Slang to use 64-bit
514    // for "long" on Arm (to be similar to Java).
515    { "_Z7rsDebugPKcl", (void *)&SC_debugLL64 },
516    { "_Z7rsDebugPKcm", (void *)&SC_debugULL64 },
517    { "_Z7rsDebugPKcx", (void *)&SC_debugLL64 },
518    { "_Z7rsDebugPKcy", (void *)&SC_debugULL64 },
519    { "_Z7rsDebugPKcPKv", (void *)&SC_debugP },
520
521    // RS Math
522    { "_Z6rsRandi", (void *)&SC_randi },
523    { "_Z6rsRandii", (void *)&SC_randi2 },
524    { "_Z6rsRandf", (void *)&SC_randf },
525    { "_Z6rsRandff", (void *)&SC_randf2 },
526    { "_Z6rsFracf", (void *)&SC_frac },
527
528    // time
529    { "_Z8rsSecondv", (void *)&SC_second },
530    { "_Z8rsMinutev", (void *)&SC_minute },
531    { "_Z6rsHourv", (void *)&SC_hour },
532    { "_Z5rsDayv", (void *)&SC_day },
533    { "_Z7rsMonthv", (void *)&SC_month },
534    { "_Z6rsYearv", (void *)&SC_year },
535    { "_Z14rsUptimeMillisv", (void*)&SC_uptimeMillis },
536    { "_Z13rsUptimeNanosv", (void*)&SC_uptimeNanos },
537    { "_Z7rsGetDtv", (void*)&SC_getDt },
538
539    { "_Z14rsSendToClienti", (void *)&SC_toClient },
540    { "_Z14rsSendToClientiPKvj", (void *)&SC_toClient2 },
541    { "_Z22rsSendToClientBlockingi", (void *)&SC_toClientBlocking },
542    { "_Z22rsSendToClientBlockingiPKvj", (void *)&SC_toClientBlocking2 },
543
544    { "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach },
545    //{ "_Z9rsForEach9rs_script13rs_allocationS0_PKv", (void *)&SC_ForEach2 },
546
547////////////////////////////////////////////////////////////////////
548
549    //{ "sinf_fast", (void *)&SC_sinf_fast },
550    //{ "cosf_fast", (void *)&SC_cosf_fast },
551
552    { NULL, NULL }
553};
554
555const ScriptCState::SymbolTable_t * ScriptCState::lookupSymbol(const char *sym)
556{
557    ScriptCState::SymbolTable_t *syms = gSyms;
558
559    while (syms->mPtr) {
560        if (!strcmp(syms->mName, sym)) {
561            return syms;
562        }
563        syms++;
564    }
565    return NULL;
566}
567
568