rsdCore.cpp revision 9719bd4a0187c400ba868712612fe66da4635aac
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    if (dc->mHasGraphics) {
274        rsdGLSetPriority(rsc, priority);
275    }
276}
277
278void Shutdown(Context *rsc) {
279    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
280
281    dc->mExit = true;
282    dc->mWorkers.mLaunchData = NULL;
283    dc->mWorkers.mLaunchCallback = NULL;
284    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
285    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
286        dc->mWorkers.mLaunchSignals[ct].set();
287    }
288    int status;
289    void *res;
290    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
291        status = pthread_join(dc->mWorkers.mThreadId[ct], &res);
292    }
293    rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0);
294
295    // Global structure cleanup.
296    pthread_mutex_lock(&rsdgInitMutex);
297    --rsdgThreadTLSKeyCount;
298    if (!rsdgThreadTLSKeyCount) {
299        pthread_key_delete(rsdgThreadTLSKey);
300    }
301    pthread_mutex_unlock(&rsdgInitMutex);
302
303}
304
305static void rsdForEach17(const void *vRoot,
306        const android::renderscript::RsForEachStubParamStruct *p,
307                                uint32_t x1, uint32_t x2,
308                                uint32_t instep, uint32_t outstep) {
309    typedef void (*fe)(const void *, uint32_t);
310    (*(fe*)vRoot)(p->in, p->y);
311}
312
313static void rsdForEach18(const void *vRoot,
314        const android::renderscript::RsForEachStubParamStruct *p,
315                                uint32_t x1, uint32_t x2,
316                                uint32_t instep, uint32_t outstep) {
317    typedef void (*fe)(void *, uint32_t);
318    (*(fe*)vRoot)(p->out, p->y);
319}
320
321static void rsdForEach19(const void *vRoot,
322        const android::renderscript::RsForEachStubParamStruct *p,
323                                uint32_t x1, uint32_t x2,
324                                uint32_t instep, uint32_t outstep) {
325    typedef void (*fe)(const void *, void *, uint32_t);
326    (*(fe*)vRoot)(p->in, p->out, p->y);
327}
328
329static void rsdForEach21(const void *vRoot,
330        const android::renderscript::RsForEachStubParamStruct *p,
331                                uint32_t x1, uint32_t x2,
332                                uint32_t instep, uint32_t outstep) {
333    typedef void (*fe)(const void *, const void *, uint32_t);
334    (*(fe*)vRoot)(p->in, p->usr, p->y);
335}
336
337static void rsdForEach22(const void *vRoot,
338        const android::renderscript::RsForEachStubParamStruct *p,
339                                uint32_t x1, uint32_t x2,
340                                uint32_t instep, uint32_t outstep) {
341    typedef void (*fe)(void *, const void *, uint32_t);
342    (*(fe*)vRoot)(p->out, p->usr, p->y);
343}
344
345static void rsdForEach23(const void *vRoot,
346        const android::renderscript::RsForEachStubParamStruct *p,
347                                uint32_t x1, uint32_t x2,
348                                uint32_t instep, uint32_t outstep) {
349    typedef void (*fe)(const void *, void *, const void *, uint32_t);
350    (*(fe*)vRoot)(p->in, p->out, p->usr, p->y);
351}
352
353static void rsdForEach25(const void *vRoot,
354        const android::renderscript::RsForEachStubParamStruct *p,
355                                uint32_t x1, uint32_t x2,
356                                uint32_t instep, uint32_t outstep) {
357    typedef void (*fe)(const void *, uint32_t, uint32_t);
358    const uint8_t *pin = (const uint8_t *)p->in;
359    uint32_t y = p->y;
360    for (uint32_t x = x1; x < x2; x++) {
361        (*(fe*)vRoot)(pin, x, y);
362        pin += instep;
363    }
364}
365
366static void rsdForEach26(const void *vRoot,
367        const android::renderscript::RsForEachStubParamStruct *p,
368                                uint32_t x1, uint32_t x2,
369                                uint32_t instep, uint32_t outstep) {
370    typedef void (*fe)(void *, uint32_t, uint32_t);
371    uint8_t *pout = (uint8_t *)p->out;
372    uint32_t y = p->y;
373    for (uint32_t x = x1; x < x2; x++) {
374        (*(fe*)vRoot)(pout, x, y);
375        pout += outstep;
376    }
377}
378
379static void rsdForEach27(const void *vRoot,
380        const android::renderscript::RsForEachStubParamStruct *p,
381                                uint32_t x1, uint32_t x2,
382                                uint32_t instep, uint32_t outstep) {
383    typedef void (*fe)(const void *, void *, uint32_t, uint32_t);
384    uint8_t *pout = (uint8_t *)p->out;
385    const uint8_t *pin = (const uint8_t *)p->in;
386    uint32_t y = p->y;
387    for (uint32_t x = x1; x < x2; x++) {
388        (*(fe*)vRoot)(pin, pout, x, y);
389        pin += instep;
390        pout += outstep;
391    }
392}
393
394static void rsdForEach29(const void *vRoot,
395        const android::renderscript::RsForEachStubParamStruct *p,
396                                uint32_t x1, uint32_t x2,
397                                uint32_t instep, uint32_t outstep) {
398    typedef void (*fe)(const void *, const void *, uint32_t, uint32_t);
399    const uint8_t *pin = (const uint8_t *)p->in;
400    const void *usr = p->usr;
401    const uint32_t y = p->y;
402    for (uint32_t x = x1; x < x2; x++) {
403        (*(fe*)vRoot)(pin, usr, x, y);
404        pin += instep;
405    }
406}
407
408static void rsdForEach30(const void *vRoot,
409        const android::renderscript::RsForEachStubParamStruct *p,
410                                uint32_t x1, uint32_t x2,
411                                uint32_t instep, uint32_t outstep) {
412    typedef void (*fe)(void *, const void *, uint32_t, uint32_t);
413    uint8_t *pout = (uint8_t *)p->out;
414    const void *usr = p->usr;
415    const uint32_t y = p->y;
416    for (uint32_t x = x1; x < x2; x++) {
417        (*(fe*)vRoot)(pout, usr, x, y);
418        pout += outstep;
419    }
420}
421
422static void rsdForEach31(const void *vRoot,
423        const android::renderscript::RsForEachStubParamStruct *p,
424                                uint32_t x1, uint32_t x2,
425                                uint32_t instep, uint32_t outstep) {
426    typedef void (*fe)(const void *, void *, const void *, uint32_t, uint32_t);
427    uint8_t *pout = (uint8_t *)p->out;
428    const uint8_t *pin = (const uint8_t *)p->in;
429    const void *usr = p->usr;
430    const uint32_t y = p->y;
431    for (uint32_t x = x1; x < x2; x++) {
432        (*(fe*)vRoot)(pin, pout, usr, x, y);
433        pin += instep;
434        pout += outstep;
435    }
436}
437
438
439static void initForEach(outer_foreach_t* forEachLaunch) {
440    rsAssert(forEachLaunch);
441    forEachLaunch[0x00] = NULL;
442    forEachLaunch[0x01] = rsdForEach31; // in
443    forEachLaunch[0x02] = rsdForEach30; //     out
444    forEachLaunch[0x03] = rsdForEach31; // in, out
445    forEachLaunch[0x04] = NULL;
446    forEachLaunch[0x05] = rsdForEach29;  // in,      usr
447    forEachLaunch[0x06] = rsdForEach30; //     out, usr
448    forEachLaunch[0x07] = rsdForEach31; // in, out, usr
449    forEachLaunch[0x08] = NULL;
450    forEachLaunch[0x09] = rsdForEach25; // in,           x
451    forEachLaunch[0x0a] = rsdForEach26; //     out,      x
452    forEachLaunch[0x0b] = rsdForEach27; // in, out,      x
453    forEachLaunch[0x0c] = NULL;
454    forEachLaunch[0x0d] = rsdForEach29; // in,      usr, x
455    forEachLaunch[0x0e] = rsdForEach30; //     out, usr, x
456    forEachLaunch[0x0f] = rsdForEach31; // in, out, usr, x
457    forEachLaunch[0x10] = NULL;
458    forEachLaunch[0x11] = rsdForEach17; // in               y
459    forEachLaunch[0x12] = rsdForEach18; //     out,         y
460    forEachLaunch[0x13] = rsdForEach19; // in, out,         y
461    forEachLaunch[0x14] = NULL;
462    forEachLaunch[0x15] = rsdForEach21; // in,      usr,    y
463    forEachLaunch[0x16] = rsdForEach22; //     out, usr,    y
464    forEachLaunch[0x17] = rsdForEach23; // in, out, usr,    y
465    forEachLaunch[0x18] = NULL;
466    forEachLaunch[0x19] = rsdForEach25; // in,           x, y
467    forEachLaunch[0x1a] = rsdForEach26; //     out,      x, y
468    forEachLaunch[0x1b] = rsdForEach27; // in, out,      x, y
469    forEachLaunch[0x1c] = NULL;
470    forEachLaunch[0x1d] = rsdForEach29; // in,      usr, x, y
471    forEachLaunch[0x1e] = rsdForEach30; //     out, usr, x, y
472    forEachLaunch[0x1f] = rsdForEach31; // in, out, usr, x, y
473}
474
475