rsdCore.cpp revision 70415115431f3c52e1da44ba838962ff3b22eb69
1edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/*
2edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Copyright (C) 2011 The Android Open Source Project
3edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
4edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * you may not use this file except in compliance with the License.
6edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * You may obtain a copy of the License at
7edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
8edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project *
10edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * See the License for the specific language governing permissions and
14edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * limitations under the License.
15edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */
16edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
17d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian#include "rsdCore.h"
18d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian#include "rsdAllocation.h"
19edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "rsdBcc.h"
20edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "rsdGL.h"
21edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "rsdProgramStore.h"
22edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "rsdProgramRaster.h"
23edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "rsdProgramVertex.h"
24edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "rsdProgramFragment.h"
25edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "rsdMesh.h"
26076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian#include "rsdSampler.h"
27076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian#include "rsdFrameBuffer.h"
288630320433bd15aca239522e54e711ef6372ab07Mathias Agopian
298630320433bd15aca239522e54e711ef6372ab07Mathias Agopian#include <malloc.h>
308630320433bd15aca239522e54e711ef6372ab07Mathias Agopian#include "rsContext.h"
311b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian
321f7bec634f19c123410a5155c8d282e177c01930Mathias Agopian#include <sys/types.h>
33edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <sys/resource.h>
34edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <sched.h>
35c666cae2d5995097ec49a87e375e2afdd92802b7Mathias Agopian#include <cutils/properties.h>
363e87601170141229d661df93e2f59e1ced73474bMathias Agopian#include <cutils/sched_policy.h>
378630320433bd15aca239522e54e711ef6372ab07Mathias Agopian#include <sys/syscall.h>
388630320433bd15aca239522e54e711ef6372ab07Mathias Agopian#include <string.h>
39a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian#include <bcc/bcc.h>
40edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
41d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopianusing namespace android;
42edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectusing namespace android::renderscript;
43edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
4487baae104a3e4c2059990b01c393476065c558b0Mathias Agopianstatic void Shutdown(Context *rsc);
4587baae104a3e4c2059990b01c393476065c558b0Mathias Agopianstatic void SetPriority(const Context *rsc, int32_t priority);
4687baae104a3e4c2059990b01c393476065c558b0Mathias Agopianstatic void initForEach(outer_foreach_t* forEachLaunch);
4787baae104a3e4c2059990b01c393476065c558b0Mathias Agopian
4887baae104a3e4c2059990b01c393476065c558b0Mathias Agopianstatic RsdHalFunctions FunctionTable = {
4987baae104a3e4c2059990b01c393476065c558b0Mathias Agopian    rsdGLInit,
503eb38cb33e41ce40dd1094bdec850f0fca9f8a53Mathias Agopian    rsdGLShutdown,
51edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    rsdGLSetSurface,
5287baae104a3e4c2059990b01c393476065c558b0Mathias Agopian    rsdGLSwap,
5387baae104a3e4c2059990b01c393476065c558b0Mathias Agopian
54edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    Shutdown,
55edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    NULL,
560f2f5ff75b7b48ceb64270655ee6b62d09bf4d00Mathias Agopian    SetPriority,
57edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    {
58a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian        rsdScriptInit,
59a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian        rsdScriptInvokeFunction,
60a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian        rsdScriptInvokeRoot,
61edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdScriptInvokeForEach,
62d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian        rsdScriptInvokeInit,
63edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdScriptInvokeFreeChildren,
64edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdScriptSetGlobalVar,
65edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdScriptSetGlobalBind,
66edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdScriptSetGlobalObj,
67edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdScriptDestroy
68edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    },
69edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
70edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    {
71edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdAllocationInit,
72edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdAllocationDestroy,
73edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdAllocationResize,
74edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdAllocationSyncAll,
75edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdAllocationMarkDirty,
7682d7ab6c7e0cf971e515134ccf072682dd1a2cdbMathias Agopian        rsdAllocationData1D,
77c666cae2d5995097ec49a87e375e2afdd92802b7Mathias Agopian        rsdAllocationData2D,
783eb38cb33e41ce40dd1094bdec850f0fca9f8a53Mathias Agopian        rsdAllocationData3D,
79a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian        rsdAllocationData1D_alloc,
803b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian        rsdAllocationData2D_alloc,
813b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian        rsdAllocationData3D_alloc,
823b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian        rsdAllocationElementData1D,
833b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian        rsdAllocationElementData2D
843b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian    },
851b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian
861b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian
871b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    {
8887baae104a3e4c2059990b01c393476065c558b0Mathias Agopian        rsdProgramStoreInit,
8987baae104a3e4c2059990b01c393476065c558b0Mathias Agopian        rsdProgramStoreSetActive,
9074faca212e2675aa55a30235c77cb6403471a4b9Mathias Agopian        rsdProgramStoreDestroy
9174faca212e2675aa55a30235c77cb6403471a4b9Mathias Agopian    },
929c6e297271ec9af9d974242d89cfa08cb6ceaa0aMathias Agopian
931b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    {
94edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdProgramRasterInit,
959c6e297271ec9af9d974242d89cfa08cb6ceaa0aMathias Agopian        rsdProgramRasterSetActive,
96edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdProgramRasterDestroy
970f2f5ff75b7b48ceb64270655ee6b62d09bf4d00Mathias Agopian    },
9852bbb1ae239c8a4d05543a23fa8c08467d09c3b2Mathias Agopian
99d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    {
100d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian        rsdProgramVertexInit,
101d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian        rsdProgramVertexSetActive,
102d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian        rsdProgramVertexDestroy
103d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    },
104d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian
105d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    {
106d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian        rsdProgramFragmentInit,
107d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian        rsdProgramFragmentSetActive,
108d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian        rsdProgramFragmentDestroy
109d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    },
110d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian
111d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    {
112d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian        rsdMeshInit,
113d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian        rsdMeshDraw,
114edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        rsdMeshDestroy
115a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian    },
116a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian
117a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian    {
118a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian        rsdSamplerInit,
119a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian        rsdSamplerDestroy
120c7d14e247117392fbd44aa454622778a25c076aeMathias Agopian    },
121a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian
122d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    {
123a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian        rsdFrameBufferInit,
124a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian        rsdFrameBufferSetActive,
125d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian        rsdFrameBufferDestroy
126a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian    },
127a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian
128a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian};
129edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
130edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectpthread_key_t rsdgThreadTLSKey = 0;
131edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectuint32_t rsdgThreadTLSKeyCount = 0;
132edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectpthread_mutex_t rsdgInitMutex = PTHREAD_MUTEX_INITIALIZER;
133edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
134edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
135edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatic void * HelperThreadProc(void *vrsc) {
1361b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    Context *rsc = static_cast<Context *>(vrsc);
1371b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
138edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
139edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project
140076b1cc3a9b90aa5b381a1ed268ca0b548444c9bMathias Agopian    uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount);
141d0566bc26fcf6ca396118701fa11900b627f2c09Mathias Agopian
14203e407270c7ad76632f982c886d0776bed9e9b4cMathias Agopian    //LOGV("RS helperThread starting %p idx=%i", rsc, idx);
143a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian
144a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian    dc->mWorkers.mLaunchSignals[idx].init();
145a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian    dc->mWorkers.mNativeThreadId[idx] = gettid();
146a49126087b4494f4ef50873f3a3f6727265f6621Mathias Agopian
147d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
1483b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian    if (status) {
1493b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian        LOGE("pthread_setspecific %i", status);
150d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    }
1513b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian
1523b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian#if 0
1533b1d2b6b2bbfb5df46b1059ec52360974e6f1428Mathias Agopian    typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t;
154d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    cpu_set_t cpuset;
155d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    memset(&cpuset, 0, sizeof(cpuset));
156d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    cpuset.bits[idx / 64] |= 1ULL << (idx % 64);
157a350ff98692b3a50cad5cc93f9f83221242ca86aMathias Agopian    int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx],
158d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian              sizeof(cpuset), &cpuset);
159d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian    LOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret));
160d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian#endif
1611b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian
1621b03149f3533db04e72e088d3fdd09d0087ca594Mathias Agopian    while (!dc->mExit) {
16398a121aa916eb7acbf11df0e3e31a6fede6fc9ddMathias Agopian        dc->mWorkers.mLaunchSignals[idx].wait();
16498a121aa916eb7acbf11df0e3e31a6fede6fc9ddMathias Agopian        if (dc->mWorkers.mLaunchCallback) {
16587baae104a3e4c2059990b01c393476065c558b0Mathias Agopian           dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx);
166edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        }
167edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        android_atomic_dec(&dc->mWorkers.mRunningCount);
168edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project        dc->mWorkers.mCompleteSignal.set();
169edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project    }
170d3ee231eddce0b69ec5e35188dbd0f4a2c3b9ac3Mathias Agopian
171    //LOGV("RS helperThread exited %p idx=%i", rsc, idx);
172    return NULL;
173}
174
175void rsdLaunchThreads(Context *rsc, WorkerCallback_t cbk, void *data) {
176    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
177
178    dc->mWorkers.mLaunchData = data;
179    dc->mWorkers.mLaunchCallback = cbk;
180    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
181    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
182        dc->mWorkers.mLaunchSignals[ct].set();
183    }
184    while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
185        dc->mWorkers.mCompleteSignal.wait();
186    }
187}
188
189bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) {
190    rsc->mHal.funcs = FunctionTable;
191
192    RsdHal *dc = (RsdHal *)calloc(1, sizeof(RsdHal));
193    if (!dc) {
194        LOGE("Calloc for driver hal failed.");
195        return false;
196    }
197    rsc->mHal.drv = dc;
198
199    pthread_mutex_lock(&rsdgInitMutex);
200    if (!rsdgThreadTLSKeyCount) {
201        int status = pthread_key_create(&rsdgThreadTLSKey, NULL);
202        if (status) {
203            LOGE("Failed to init thread tls key.");
204            pthread_mutex_unlock(&rsdgInitMutex);
205            return false;
206        }
207    }
208    rsdgThreadTLSKeyCount++;
209    pthread_mutex_unlock(&rsdgInitMutex);
210
211    initForEach(dc->mForEachLaunch);
212
213    dc->mTlsStruct.mContext = rsc;
214    dc->mTlsStruct.mScript = NULL;
215    int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
216    if (status) {
217        LOGE("pthread_setspecific %i", status);
218    }
219
220
221    int cpu = sysconf(_SC_NPROCESSORS_ONLN);
222    LOGV("%p Launching thread(s), CPUs %i", rsc, cpu);
223    if (cpu < 2) cpu = 0;
224
225    dc->mWorkers.mCount = (uint32_t)cpu;
226    dc->mWorkers.mThreadId = (pthread_t *) calloc(dc->mWorkers.mCount, sizeof(pthread_t));
227    dc->mWorkers.mNativeThreadId = (pid_t *) calloc(dc->mWorkers.mCount, sizeof(pid_t));
228    dc->mWorkers.mLaunchSignals = new Signal[dc->mWorkers.mCount];
229    dc->mWorkers.mLaunchCallback = NULL;
230
231    dc->mWorkers.mCompleteSignal.init();
232
233    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
234    android_atomic_release_store(0, &dc->mWorkers.mLaunchCount);
235
236    pthread_attr_t threadAttr;
237    status = pthread_attr_init(&threadAttr);
238    if (status) {
239        LOGE("Failed to init thread attribute.");
240        return false;
241    }
242
243    for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
244        status = pthread_create(&dc->mWorkers.mThreadId[ct], &threadAttr, HelperThreadProc, rsc);
245        if (status) {
246            dc->mWorkers.mCount = ct;
247            LOGE("Created fewer than expected number of RS threads.");
248            break;
249        }
250    }
251    while (android_atomic_acquire_load(&dc->mWorkers.mRunningCount) != 0) {
252        usleep(100);
253    }
254
255    pthread_attr_destroy(&threadAttr);
256    return true;
257}
258
259
260void SetPriority(const Context *rsc, int32_t priority) {
261    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
262    for (uint32_t ct=0; ct < dc->mWorkers.mCount; ct++) {
263        setpriority(PRIO_PROCESS, dc->mWorkers.mNativeThreadId[ct], priority);
264    }
265}
266
267void Shutdown(Context *rsc) {
268    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
269
270    dc->mExit = true;
271    dc->mWorkers.mLaunchData = NULL;
272    dc->mWorkers.mLaunchCallback = NULL;
273    android_atomic_release_store(dc->mWorkers.mCount, &dc->mWorkers.mRunningCount);
274    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
275        dc->mWorkers.mLaunchSignals[ct].set();
276    }
277    int status;
278    void *res;
279    for (uint32_t ct = 0; ct < dc->mWorkers.mCount; ct++) {
280        status = pthread_join(dc->mWorkers.mThreadId[ct], &res);
281    }
282    rsAssert(android_atomic_acquire_load(&dc->mWorkers.mRunningCount) == 0);
283
284    // Global structure cleanup.
285    pthread_mutex_lock(&rsdgInitMutex);
286    --rsdgThreadTLSKeyCount;
287    if (!rsdgThreadTLSKeyCount) {
288        pthread_key_delete(rsdgThreadTLSKey);
289    }
290    pthread_mutex_unlock(&rsdgInitMutex);
291
292}
293
294static void rsdForEach17(const void *vRoot,
295        const android::renderscript::RsForEachStubParamStruct *p,
296                                uint32_t x1, uint32_t x2,
297                                uint32_t instep, uint32_t outstep) {
298    typedef void (*fe)(const void *, uint32_t);
299    (*(fe*)vRoot)(p->in, p->y);
300}
301
302static void rsdForEach18(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)(void *, uint32_t);
307    (*(fe*)vRoot)(p->out, p->y);
308}
309
310static void rsdForEach19(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)(const void *, void *, uint32_t);
315    (*(fe*)vRoot)(p->in, p->out, p->y);
316}
317
318static void rsdForEach21(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 *, const void *, uint32_t);
323    (*(fe*)vRoot)(p->in, p->usr, p->y);
324}
325
326static void rsdForEach22(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)(void *, const void *, uint32_t);
331    (*(fe*)vRoot)(p->out, p->usr, p->y);
332}
333
334static void rsdForEach23(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)(const void *, void *, const void *, uint32_t);
339    (*(fe*)vRoot)(p->in, p->out, p->usr, p->y);
340}
341
342static void rsdForEach25(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 *, uint32_t, uint32_t);
347    const uint8_t *pin = (const uint8_t *)p->in;
348    uint32_t y = p->y;
349    for (uint32_t x = x1; x < x2; x++) {
350        (*(fe*)vRoot)(pin, x, y);
351        pin += instep;
352    }
353}
354
355static void rsdForEach26(const void *vRoot,
356        const android::renderscript::RsForEachStubParamStruct *p,
357                                uint32_t x1, uint32_t x2,
358                                uint32_t instep, uint32_t outstep) {
359    typedef void (*fe)(void *, uint32_t, uint32_t);
360    uint8_t *pout = (uint8_t *)p->out;
361    uint32_t y = p->y;
362    for (uint32_t x = x1; x < x2; x++) {
363        (*(fe*)vRoot)(pout, x, y);
364        pout += outstep;
365    }
366}
367
368static void rsdForEach27(const void *vRoot,
369        const android::renderscript::RsForEachStubParamStruct *p,
370                                uint32_t x1, uint32_t x2,
371                                uint32_t instep, uint32_t outstep) {
372    typedef void (*fe)(const void *, void *, uint32_t, uint32_t);
373    uint8_t *pout = (uint8_t *)p->out;
374    const uint8_t *pin = (const uint8_t *)p->in;
375    uint32_t y = p->y;
376    for (uint32_t x = x1; x < x2; x++) {
377        (*(fe*)vRoot)(pin, pout, x, y);
378        pin += instep;
379        pout += outstep;
380    }
381}
382
383static void rsdForEach29(const void *vRoot,
384        const android::renderscript::RsForEachStubParamStruct *p,
385                                uint32_t x1, uint32_t x2,
386                                uint32_t instep, uint32_t outstep) {
387    typedef void (*fe)(const void *, const void *, uint32_t, uint32_t);
388    const uint8_t *pin = (const uint8_t *)p->in;
389    const void *usr = p->usr;
390    const uint32_t y = p->y;
391    for (uint32_t x = x1; x < x2; x++) {
392        (*(fe*)vRoot)(pin, usr, x, y);
393        pin += instep;
394    }
395}
396
397static void rsdForEach30(const void *vRoot,
398        const android::renderscript::RsForEachStubParamStruct *p,
399                                uint32_t x1, uint32_t x2,
400                                uint32_t instep, uint32_t outstep) {
401    typedef void (*fe)(void *, const void *, uint32_t, uint32_t);
402    uint8_t *pout = (uint8_t *)p->out;
403    const void *usr = p->usr;
404    const uint32_t y = p->y;
405    for (uint32_t x = x1; x < x2; x++) {
406        (*(fe*)vRoot)(pout, usr, x, y);
407        pout += outstep;
408    }
409}
410
411static void rsdForEach31(const void *vRoot,
412        const android::renderscript::RsForEachStubParamStruct *p,
413                                uint32_t x1, uint32_t x2,
414                                uint32_t instep, uint32_t outstep) {
415    typedef void (*fe)(const void *, void *, const void *, uint32_t, uint32_t);
416    uint8_t *pout = (uint8_t *)p->out;
417    const uint8_t *pin = (const uint8_t *)p->in;
418    const void *usr = p->usr;
419    const uint32_t y = p->y;
420    for (uint32_t x = x1; x < x2; x++) {
421        (*(fe*)vRoot)(pin, pout, usr, x, y);
422        pin += instep;
423        pout += outstep;
424    }
425}
426
427
428static void initForEach(outer_foreach_t* forEachLaunch) {
429    rsAssert(forEachLaunch);
430    forEachLaunch[0x00] = NULL;
431    forEachLaunch[0x01] = rsdForEach31; // in
432    forEachLaunch[0x02] = rsdForEach30; //     out
433    forEachLaunch[0x03] = rsdForEach31; // in, out
434    forEachLaunch[0x04] = NULL;
435    forEachLaunch[0x05] = rsdForEach29;  // in,      usr
436    forEachLaunch[0x06] = rsdForEach30; //     out, usr
437    forEachLaunch[0x07] = rsdForEach31; // in, out, usr
438    forEachLaunch[0x08] = NULL;
439    forEachLaunch[0x09] = rsdForEach25; // in,           x
440    forEachLaunch[0x0a] = rsdForEach26; //     out,      x
441    forEachLaunch[0x0b] = rsdForEach27; // in, out,      x
442    forEachLaunch[0x0c] = NULL;
443    forEachLaunch[0x0d] = rsdForEach29; // in,      usr, x
444    forEachLaunch[0x0e] = rsdForEach30; //     out, usr, x
445    forEachLaunch[0x0f] = rsdForEach31; // in, out, usr, x
446    forEachLaunch[0x10] = NULL;
447    forEachLaunch[0x11] = rsdForEach17; // in               y
448    forEachLaunch[0x12] = rsdForEach18; //     out,         y
449    forEachLaunch[0x13] = rsdForEach19; // in, out,         y
450    forEachLaunch[0x14] = NULL;
451    forEachLaunch[0x15] = rsdForEach21; // in,      usr,    y
452    forEachLaunch[0x16] = rsdForEach22; //     out, usr,    y
453    forEachLaunch[0x17] = rsdForEach23; // in, out, usr,    y
454    forEachLaunch[0x18] = NULL;
455    forEachLaunch[0x19] = rsdForEach25; // in,           x, y
456    forEachLaunch[0x1a] = rsdForEach26; //     out,      x, y
457    forEachLaunch[0x1b] = rsdForEach27; // in, out,      x, y
458    forEachLaunch[0x1c] = NULL;
459    forEachLaunch[0x1d] = rsdForEach29; // in,      usr, x, y
460    forEachLaunch[0x1e] = rsdForEach30; //     out, usr, x, y
461    forEachLaunch[0x1f] = rsdForEach31; // in, out, usr, x, y
462}
463
464