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