rsdCore.cpp revision 03f1910431433f3a35f1445aa0bba2b00417f0cc
1/*
2 * Copyright (C) 2011 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 "rsdCore.h"
18#include "rsdAllocation.h"
19#include "rsdBcc.h"
20#include "rsdGL.h"
21#include "rsdPath.h"
22#include "rsdProgramStore.h"
23#include "rsdProgramRaster.h"
24#include "rsdProgramVertex.h"
25#include "rsdProgramFragment.h"
26#include "rsdMesh.h"
27#include "rsdSampler.h"
28#include "rsdFrameBuffer.h"
29
30#include <malloc.h>
31#include "rsContext.h"
32
33#include <sys/types.h>
34#include <sys/resource.h>
35#include <sched.h>
36#include <cutils/properties.h>
37#include <cutils/sched_policy.h>
38#include <sys/syscall.h>
39#include <string.h>
40#include <bcc/bcc.h>
41
42using namespace android;
43using namespace android::renderscript;
44
45static void Shutdown(Context *rsc);
46static void SetPriority(const Context *rsc, int32_t priority);
47static void initForEach(outer_foreach_t* forEachLaunch);
48
49static RsdHalFunctions FunctionTable = {
50    rsdGLInit,
51    rsdGLShutdown,
52    rsdGLSetSurface,
53    rsdGLSwap,
54
55    Shutdown,
56    NULL,
57    SetPriority,
58    {
59        rsdScriptInit,
60        rsdScriptInvokeFunction,
61        rsdScriptInvokeRoot,
62        rsdScriptInvokeForEach,
63        rsdScriptInvokeInit,
64        rsdScriptInvokeFreeChildren,
65        rsdScriptSetGlobalVar,
66        rsdScriptSetGlobalBind,
67        rsdScriptSetGlobalObj,
68        rsdScriptDestroy
69    },
70
71    {
72        rsdAllocationInit,
73        rsdAllocationDestroy,
74        rsdAllocationResize,
75        rsdAllocationSyncAll,
76        rsdAllocationMarkDirty,
77        rsdAllocationData1D,
78        rsdAllocationData2D,
79        rsdAllocationData3D,
80        rsdAllocationData1D_alloc,
81        rsdAllocationData2D_alloc,
82        rsdAllocationData3D_alloc,
83        rsdAllocationElementData1D,
84        rsdAllocationElementData2D
85    },
86
87
88    {
89        rsdProgramStoreInit,
90        rsdProgramStoreSetActive,
91        rsdProgramStoreDestroy
92    },
93
94    {
95        rsdProgramRasterInit,
96        rsdProgramRasterSetActive,
97        rsdProgramRasterDestroy
98    },
99
100    {
101        rsdProgramVertexInit,
102        rsdProgramVertexSetActive,
103        rsdProgramVertexDestroy
104    },
105
106    {
107        rsdProgramFragmentInit,
108        rsdProgramFragmentSetActive,
109        rsdProgramFragmentDestroy
110    },
111
112    {
113        rsdMeshInit,
114        rsdMeshDraw,
115        rsdMeshDestroy
116    },
117
118    {
119        rsdPathInitStatic,
120        rsdPathInitDynamic,
121        rsdPathDraw,
122        rsdPathDestroy
123    },
124
125    {
126        rsdSamplerInit,
127        rsdSamplerDestroy
128    },
129
130    {
131        rsdFrameBufferInit,
132        rsdFrameBufferSetActive,
133        rsdFrameBufferDestroy
134    },
135
136};
137
138pthread_key_t rsdgThreadTLSKey = 0;
139uint32_t rsdgThreadTLSKeyCount = 0;
140pthread_mutex_t rsdgInitMutex = PTHREAD_MUTEX_INITIALIZER;
141
142
143static void * HelperThreadProc(void *vrsc) {
144    Context *rsc = static_cast<Context *>(vrsc);
145    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
146
147
148    uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount);
149
150    //ALOGV("RS helperThread starting %p idx=%i", rsc, idx);
151
152    dc->mWorkers.mLaunchSignals[idx].init();
153    dc->mWorkers.mNativeThreadId[idx] = gettid();
154
155    int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
156    if (status) {
157        ALOGE("pthread_setspecific %i", status);
158    }
159
160#if 0
161    typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t;
162    cpu_set_t cpuset;
163    memset(&cpuset, 0, sizeof(cpuset));
164    cpuset.bits[idx / 64] |= 1ULL << (idx % 64);
165    int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx],
166              sizeof(cpuset), &cpuset);
167    ALOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret));
168#endif
169
170    while (!dc->mExit) {
171        dc->mWorkers.mLaunchSignals[idx].wait();
172        if (dc->mWorkers.mLaunchCallback) {
173           dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx);
174        }
175        android_atomic_dec(&dc->mWorkers.mRunningCount);
176        dc->mWorkers.mCompleteSignal.set();
177    }
178
179    //ALOGV("RS helperThread exited %p idx=%i", rsc, idx);
180    return NULL;
181}
182
183void rsdLaunchThreads(Context *rsc, WorkerCallback_t cbk, void *data) {
184    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
185
186    dc->mWorkers.mLaunchData = data;
187    dc->mWorkers.mLaunchCallback = cbk;
188    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
189    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
190        dc->mWorkers.mLaunchSignals[ct].set();
191    }
192    while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
193        dc->mWorkers.mCompleteSignal.wait();
194    }
195}
196
197bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) {
198    rsc->mHal.funcs = FunctionTable;
199
200    RsdHal *dc = (RsdHal *)calloc(1, sizeof(RsdHal));
201    if (!dc) {
202        ALOGE("Calloc for driver hal failed.");
203        return false;
204    }
205    rsc->mHal.drv = dc;
206
207    pthread_mutex_lock(&rsdgInitMutex);
208    if (!rsdgThreadTLSKeyCount) {
209        int status = pthread_key_create(&rsdgThreadTLSKey, NULL);
210        if (status) {
211            ALOGE("Failed to init thread tls key.");
212            pthread_mutex_unlock(&rsdgInitMutex);
213            return false;
214        }
215    }
216    rsdgThreadTLSKeyCount++;
217    pthread_mutex_unlock(&rsdgInitMutex);
218
219    initForEach(dc->mForEachLaunch);
220
221    dc->mTlsStruct.mContext = rsc;
222    dc->mTlsStruct.mScript = NULL;
223    int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
224    if (status) {
225        ALOGE("pthread_setspecific %i", status);
226    }
227
228
229    int cpu = sysconf(_SC_NPROCESSORS_ONLN);
230    ALOGV("%p Launching thread(s), CPUs %i", rsc, cpu);
231    if (cpu < 2) cpu = 0;
232
233    dc->mWorkers.mCount = (uint32_t)cpu;
234    dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t));
235    dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t));
236    dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount];
237    dc->mWorkers.mLaunchCallback = NULL;
238
239    dc->mWorkers.mCompleteSignal.init();
240
241    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
242    android_atomic_release_store(0, &dc->mWorkers.mLaunchCount);
243
244    pthread_attr_t threadAttr;
245    status = pthread_attr_init(&threadAttr);
246    if (status) {
247        ALOGE("Failed to init thread attribute.");
248        return false;
249    }
250
251    for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
252        status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc);
253        if (status) {
254            dc->mWorkers.mCount = ct;
255            ALOGE("Created fewer than expected number of RS threads.");
256            break;
257        }
258    }
259    while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
260        usleep(100);
261    }
262
263    pthread_attr_destroy(&threadAttr);
264    return true;
265}
266
267
268void SetPriority(const Context *rsc, int32_t priority) {
269    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
270    for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
271        setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority);
272    }
273}
274
275void Shutdown(Context *rsc) {
276    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
277
278    dc->mExit = true;
279    dc->mWorkers.mLaunchData = NULL;
280    dc->mWorkers.mLaunchCallback = NULL;
281    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
282    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
283        dc->mWorkers.mLaunchSignals[ct].set();
284    }
285    int status;
286    void *res;
287    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
288        status = pthread_join(dc->mWorkers.mThreadId[ct], &res);
289    }
290    rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0);
291
292    // Global structure cleanup.
293    pthread_mutex_lock(&rsdgInitMutex);
294    --rsdgThreadTLSKeyCount;
295    if (!rsdgThreadTLSKeyCount) {
296        pthread_key_delete(rsdgThreadTLSKey);
297    }
298    pthread_mutex_unlock(&rsdgInitMutex);
299
300}
301
302static void rsdForEach17(const void *vRoot,
303        const android::renderscript::RsForEachStubParamStruct *p,
304                                uint32_t x1, uint32_t x2,
305                                uint32_t instep, uint32_t outstep) {
306    typedef void (*fe)(const void *, uint32_t);
307    (*(fe*)vRoot)(p->in, p->y);
308}
309
310static void rsdForEach18(const void *vRoot,
311        const android::renderscript::RsForEachStubParamStruct *p,
312                                uint32_t x1, uint32_t x2,
313                                uint32_t instep, uint32_t outstep) {
314    typedef void (*fe)(void *, uint32_t);
315    (*(fe*)vRoot)(p->out, p->y);
316}
317
318static void rsdForEach19(const void *vRoot,
319        const android::renderscript::RsForEachStubParamStruct *p,
320                                uint32_t x1, uint32_t x2,
321                                uint32_t instep, uint32_t outstep) {
322    typedef void (*fe)(const void *, void *, uint32_t);
323    (*(fe*)vRoot)(p->in, p->out, p->y);
324}
325
326static void rsdForEach21(const void *vRoot,
327        const android::renderscript::RsForEachStubParamStruct *p,
328                                uint32_t x1, uint32_t x2,
329                                uint32_t instep, uint32_t outstep) {
330    typedef void (*fe)(const void *, const void *, uint32_t);
331    (*(fe*)vRoot)(p->in, p->usr, p->y);
332}
333
334static void rsdForEach22(const void *vRoot,
335        const android::renderscript::RsForEachStubParamStruct *p,
336                                uint32_t x1, uint32_t x2,
337                                uint32_t instep, uint32_t outstep) {
338    typedef void (*fe)(void *, const void *, uint32_t);
339    (*(fe*)vRoot)(p->out, p->usr, p->y);
340}
341
342static void rsdForEach23(const void *vRoot,
343        const android::renderscript::RsForEachStubParamStruct *p,
344                                uint32_t x1, uint32_t x2,
345                                uint32_t instep, uint32_t outstep) {
346    typedef void (*fe)(const void *, void *, const void *, uint32_t);
347    (*(fe*)vRoot)(p->in, p->out, p->usr, p->y);
348}
349
350static void rsdForEach25(const void *vRoot,
351        const android::renderscript::RsForEachStubParamStruct *p,
352                                uint32_t x1, uint32_t x2,
353                                uint32_t instep, uint32_t outstep) {
354    typedef void (*fe)(const void *, uint32_t, uint32_t);
355    const uint8_t *pin = (const uint8_t *)p->in;
356    uint32_t y = p->y;
357    for (uint32_t x = x1; x < x2; x++) {
358        (*(fe*)vRoot)(pin, x, y);
359        pin += instep;
360    }
361}
362
363static void rsdForEach26(const void *vRoot,
364        const android::renderscript::RsForEachStubParamStruct *p,
365                                uint32_t x1, uint32_t x2,
366                                uint32_t instep, uint32_t outstep) {
367    typedef void (*fe)(void *, uint32_t, uint32_t);
368    uint8_t *pout = (uint8_t *)p->out;
369    uint32_t y = p->y;
370    for (uint32_t x = x1; x < x2; x++) {
371        (*(fe*)vRoot)(pout, x, y);
372        pout += outstep;
373    }
374}
375
376static void rsdForEach27(const void *vRoot,
377        const android::renderscript::RsForEachStubParamStruct *p,
378                                uint32_t x1, uint32_t x2,
379                                uint32_t instep, uint32_t outstep) {
380    typedef void (*fe)(const void *, void *, uint32_t, uint32_t);
381    uint8_t *pout = (uint8_t *)p->out;
382    const uint8_t *pin = (const uint8_t *)p->in;
383    uint32_t y = p->y;
384    for (uint32_t x = x1; x < x2; x++) {
385        (*(fe*)vRoot)(pin, pout, x, y);
386        pin += instep;
387        pout += outstep;
388    }
389}
390
391static void rsdForEach29(const void *vRoot,
392        const android::renderscript::RsForEachStubParamStruct *p,
393                                uint32_t x1, uint32_t x2,
394                                uint32_t instep, uint32_t outstep) {
395    typedef void (*fe)(const void *, const void *, uint32_t, uint32_t);
396    const uint8_t *pin = (const uint8_t *)p->in;
397    const void *usr = p->usr;
398    const uint32_t y = p->y;
399    for (uint32_t x = x1; x < x2; x++) {
400        (*(fe*)vRoot)(pin, usr, x, y);
401        pin += instep;
402    }
403}
404
405static void rsdForEach30(const void *vRoot,
406        const android::renderscript::RsForEachStubParamStruct *p,
407                                uint32_t x1, uint32_t x2,
408                                uint32_t instep, uint32_t outstep) {
409    typedef void (*fe)(void *, const void *, uint32_t, uint32_t);
410    uint8_t *pout = (uint8_t *)p->out;
411    const void *usr = p->usr;
412    const uint32_t y = p->y;
413    for (uint32_t x = x1; x < x2; x++) {
414        (*(fe*)vRoot)(pout, usr, x, y);
415        pout += outstep;
416    }
417}
418
419static void rsdForEach31(const void *vRoot,
420        const android::renderscript::RsForEachStubParamStruct *p,
421                                uint32_t x1, uint32_t x2,
422                                uint32_t instep, uint32_t outstep) {
423    typedef void (*fe)(const void *, void *, const void *, uint32_t, uint32_t);
424    uint8_t *pout = (uint8_t *)p->out;
425    const uint8_t *pin = (const uint8_t *)p->in;
426    const void *usr = p->usr;
427    const uint32_t y = p->y;
428    for (uint32_t x = x1; x < x2; x++) {
429        (*(fe*)vRoot)(pin, pout, usr, x, y);
430        pin += instep;
431        pout += outstep;
432    }
433}
434
435
436static void initForEach(outer_foreach_t* forEachLaunch) {
437    rsAssert(forEachLaunch);
438    forEachLaunch[0x00] = NULL;
439    forEachLaunch[0x01] = rsdForEach31; // in
440    forEachLaunch[0x02] = rsdForEach30; //     out
441    forEachLaunch[0x03] = rsdForEach31; // in, out
442    forEachLaunch[0x04] = NULL;
443    forEachLaunch[0x05] = rsdForEach29;  // in,      usr
444    forEachLaunch[0x06] = rsdForEach30; //     out, usr
445    forEachLaunch[0x07] = rsdForEach31; // in, out, usr
446    forEachLaunch[0x08] = NULL;
447    forEachLaunch[0x09] = rsdForEach25; // in,           x
448    forEachLaunch[0x0a] = rsdForEach26; //     out,      x
449    forEachLaunch[0x0b] = rsdForEach27; // in, out,      x
450    forEachLaunch[0x0c] = NULL;
451    forEachLaunch[0x0d] = rsdForEach29; // in,      usr, x
452    forEachLaunch[0x0e] = rsdForEach30; //     out, usr, x
453    forEachLaunch[0x0f] = rsdForEach31; // in, out, usr, x
454    forEachLaunch[0x10] = NULL;
455    forEachLaunch[0x11] = rsdForEach17; // in               y
456    forEachLaunch[0x12] = rsdForEach18; //     out,         y
457    forEachLaunch[0x13] = rsdForEach19; // in, out,         y
458    forEachLaunch[0x14] = NULL;
459    forEachLaunch[0x15] = rsdForEach21; // in,      usr,    y
460    forEachLaunch[0x16] = rsdForEach22; //     out, usr,    y
461    forEachLaunch[0x17] = rsdForEach23; // in, out, usr,    y
462    forEachLaunch[0x18] = NULL;
463    forEachLaunch[0x19] = rsdForEach25; // in,           x, y
464    forEachLaunch[0x1a] = rsdForEach26; //     out,      x, y
465    forEachLaunch[0x1b] = rsdForEach27; // in, out,      x, y
466    forEachLaunch[0x1c] = NULL;
467    forEachLaunch[0x1d] = rsdForEach29; // in,      usr, x, y
468    forEachLaunch[0x1e] = rsdForEach30; //     out, usr, x, y
469    forEachLaunch[0x1f] = rsdForEach31; // in, out, usr, x, y
470}
471
472