rsdCore.cpp revision abd6d04992e4b7c903ed2c1278d744e73ac74334
1/*
2 * Copyright (C) 2011-2012 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 <sys/syscall.h>
38#include <string.h>
39
40using namespace android;
41using namespace android::renderscript;
42
43static void Shutdown(Context *rsc);
44static void SetPriority(const Context *rsc, int32_t priority);
45
46static RsdHalFunctions FunctionTable = {
47    rsdGLInit,
48    rsdGLShutdown,
49    rsdGLSetSurface,
50    rsdGLSwap,
51
52    Shutdown,
53    NULL,
54    SetPriority,
55    {
56        rsdScriptInit,
57        rsdScriptInvokeFunction,
58        rsdScriptInvokeRoot,
59        rsdScriptInvokeForEach,
60        rsdScriptInvokeInit,
61        rsdScriptInvokeFreeChildren,
62        rsdScriptSetGlobalVar,
63        rsdScriptSetGlobalVarWithElemDims,
64        rsdScriptSetGlobalBind,
65        rsdScriptSetGlobalObj,
66        rsdScriptDestroy
67    },
68
69    {
70        rsdAllocationInit,
71        rsdAllocationDestroy,
72        rsdAllocationResize,
73        rsdAllocationSyncAll,
74        rsdAllocationMarkDirty,
75        rsdAllocationInitSurfaceTexture,
76        rsdAllocationSetSurfaceTexture,
77        rsdAllocationIoSend,
78        rsdAllocationIoReceive,
79        rsdAllocationData1D,
80        rsdAllocationData2D,
81        rsdAllocationData3D,
82        rsdAllocationRead1D,
83        rsdAllocationRead2D,
84        rsdAllocationRead3D,
85        rsdAllocationLock1D,
86        rsdAllocationUnlock1D,
87        rsdAllocationData1D_alloc,
88        rsdAllocationData2D_alloc,
89        rsdAllocationData3D_alloc,
90        rsdAllocationElementData1D,
91        rsdAllocationElementData2D,
92        rsdAllocationGenerateMipmaps
93    },
94
95
96    {
97        rsdProgramStoreInit,
98        rsdProgramStoreSetActive,
99        rsdProgramStoreDestroy
100    },
101
102    {
103        rsdProgramRasterInit,
104        rsdProgramRasterSetActive,
105        rsdProgramRasterDestroy
106    },
107
108    {
109        rsdProgramVertexInit,
110        rsdProgramVertexSetActive,
111        rsdProgramVertexDestroy
112    },
113
114    {
115        rsdProgramFragmentInit,
116        rsdProgramFragmentSetActive,
117        rsdProgramFragmentDestroy
118    },
119
120    {
121        rsdMeshInit,
122        rsdMeshDraw,
123        rsdMeshDestroy
124    },
125
126    {
127        rsdPathInitStatic,
128        rsdPathInitDynamic,
129        rsdPathDraw,
130        rsdPathDestroy
131    },
132
133    {
134        rsdSamplerInit,
135        rsdSamplerDestroy
136    },
137
138    {
139        rsdFrameBufferInit,
140        rsdFrameBufferSetActive,
141        rsdFrameBufferDestroy
142    },
143
144};
145
146pthread_key_t rsdgThreadTLSKey = 0;
147uint32_t rsdgThreadTLSKeyCount = 0;
148pthread_mutex_t rsdgInitMutex = PTHREAD_MUTEX_INITIALIZER;
149
150
151static void * HelperThreadProc(void *vrsc) {
152    Context *rsc = static_cast<Context *>(vrsc);
153    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
154
155
156    uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount);
157
158    //ALOGV("RS helperThread starting %p idx=%i", rsc, idx);
159
160    dc->mWorkers.mLaunchSignals[idx].init();
161    dc->mWorkers.mNativeThreadId[idx] = gettid();
162
163    int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
164    if (status) {
165        ALOGE("pthread_setspecific %i", status);
166    }
167
168#if 0
169    typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t;
170    cpu_set_t cpuset;
171    memset(&cpuset, 0, sizeof(cpuset));
172    cpuset.bits[idx / 64] |= 1ULL << (idx % 64);
173    int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx],
174              sizeof(cpuset), &cpuset);
175    ALOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret));
176#endif
177
178    while (!dc->mExit) {
179        dc->mWorkers.mLaunchSignals[idx].wait();
180        if (dc->mWorkers.mLaunchCallback) {
181           dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx);
182        }
183        android_atomic_dec(&dc->mWorkers.mRunningCount);
184        dc->mWorkers.mCompleteSignal.set();
185    }
186
187    //ALOGV("RS helperThread exited %p idx=%i", rsc, idx);
188    return NULL;
189}
190
191void rsdLaunchThreads(Context *rsc, WorkerCallback_t cbk, void *data) {
192    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
193
194    dc->mWorkers.mLaunchData = data;
195    dc->mWorkers.mLaunchCallback = cbk;
196    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
197    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
198        dc->mWorkers.mLaunchSignals[ct].set();
199    }
200    while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
201        dc->mWorkers.mCompleteSignal.wait();
202    }
203}
204
205bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) {
206    rsc->mHal.funcs = FunctionTable;
207
208    RsdHal *dc = (RsdHal *)calloc(1, sizeof(RsdHal));
209    if (!dc) {
210        ALOGE("Calloc for driver hal failed.");
211        return false;
212    }
213    rsc->mHal.drv = dc;
214
215    pthread_mutex_lock(&rsdgInitMutex);
216    if (!rsdgThreadTLSKeyCount) {
217        int status = pthread_key_create(&rsdgThreadTLSKey, NULL);
218        if (status) {
219            ALOGE("Failed to init thread tls key.");
220            pthread_mutex_unlock(&rsdgInitMutex);
221            return false;
222        }
223    }
224    rsdgThreadTLSKeyCount++;
225    pthread_mutex_unlock(&rsdgInitMutex);
226
227    dc->mTlsStruct.mContext = rsc;
228    dc->mTlsStruct.mScript = NULL;
229    int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
230    if (status) {
231        ALOGE("pthread_setspecific %i", status);
232    }
233
234
235    int cpu = sysconf(_SC_NPROCESSORS_ONLN);
236    if(rsc->props.mDebugMaxThreads) {
237        cpu = rsc->props.mDebugMaxThreads;
238    }
239    if (cpu < 2) {
240        cpu = 0;
241    }
242    ALOGV("%p Launching thread(s), CPUs %i", rsc, cpu);
243
244    dc->mWorkers.mCount = (uint32_t)cpu;
245    dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t));
246    dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t));
247    dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount];
248    dc->mWorkers.mLaunchCallback = NULL;
249
250    dc->mWorkers.mCompleteSignal.init();
251
252    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
253    android_atomic_release_store(0, &dc->mWorkers.mLaunchCount);
254
255    pthread_attr_t threadAttr;
256    status = pthread_attr_init(&threadAttr);
257    if (status) {
258        ALOGE("Failed to init thread attribute.");
259        return false;
260    }
261
262    for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
263        status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc);
264        if (status) {
265            dc->mWorkers.mCount = ct;
266            ALOGE("Created fewer than expected number of RS threads.");
267            break;
268        }
269    }
270    while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
271        usleep(100);
272    }
273
274    pthread_attr_destroy(&threadAttr);
275    return true;
276}
277
278
279void SetPriority(const Context *rsc, int32_t priority) {
280    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
281    for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
282        setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority);
283    }
284    if (dc->mHasGraphics) {
285        rsdGLSetPriority(rsc, priority);
286    }
287}
288
289void Shutdown(Context *rsc) {
290    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
291
292    dc->mExit = true;
293    dc->mWorkers.mLaunchData = NULL;
294    dc->mWorkers.mLaunchCallback = NULL;
295    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
296    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
297        dc->mWorkers.mLaunchSignals[ct].set();
298    }
299    void *res;
300    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
301        pthread_join(dc->mWorkers.mThreadId[ct], &res);
302    }
303    rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0);
304
305    // Global structure cleanup.
306    pthread_mutex_lock(&rsdgInitMutex);
307    --rsdgThreadTLSKeyCount;
308    if (!rsdgThreadTLSKeyCount) {
309        pthread_key_delete(rsdgThreadTLSKey);
310    }
311    pthread_mutex_unlock(&rsdgInitMutex);
312
313}
314
315