Home | History | Annotate | Download | only in driver
      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 "rsdProgramStore.h"
     22 #include "rsdProgramRaster.h"
     23 #include "rsdProgramVertex.h"
     24 #include "rsdProgramFragment.h"
     25 #include "rsdMesh.h"
     26 #include "rsdSampler.h"
     27 #include "rsdFrameBuffer.h"
     28 
     29 #include <malloc.h>
     30 #include "rsContext.h"
     31 
     32 #include <sys/types.h>
     33 #include <sys/resource.h>
     34 #include <sched.h>
     35 #include <cutils/properties.h>
     36 #include <cutils/sched_policy.h>
     37 #include <sys/syscall.h>
     38 #include <string.h>
     39 #include <bcc/bcc.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 static void initForEach(outer_foreach_t* forEachLaunch);
     47 
     48 static RsdHalFunctions FunctionTable = {
     49     rsdGLInit,
     50     rsdGLShutdown,
     51     rsdGLSetSurface,
     52     rsdGLSwap,
     53 
     54     Shutdown,
     55     NULL,
     56     SetPriority,
     57     {
     58         rsdScriptInit,
     59         rsdScriptInvokeFunction,
     60         rsdScriptInvokeRoot,
     61         rsdScriptInvokeForEach,
     62         rsdScriptInvokeInit,
     63         rsdScriptInvokeFreeChildren,
     64         rsdScriptSetGlobalVar,
     65         rsdScriptSetGlobalBind,
     66         rsdScriptSetGlobalObj,
     67         rsdScriptDestroy
     68     },
     69 
     70     {
     71         rsdAllocationInit,
     72         rsdAllocationDestroy,
     73         rsdAllocationResize,
     74         rsdAllocationSyncAll,
     75         rsdAllocationMarkDirty,
     76         rsdAllocationData1D,
     77         rsdAllocationData2D,
     78         rsdAllocationData3D,
     79         rsdAllocationData1D_alloc,
     80         rsdAllocationData2D_alloc,
     81         rsdAllocationData3D_alloc,
     82         rsdAllocationElementData1D,
     83         rsdAllocationElementData2D
     84     },
     85 
     86 
     87     {
     88         rsdProgramStoreInit,
     89         rsdProgramStoreSetActive,
     90         rsdProgramStoreDestroy
     91     },
     92 
     93     {
     94         rsdProgramRasterInit,
     95         rsdProgramRasterSetActive,
     96         rsdProgramRasterDestroy
     97     },
     98 
     99     {
    100         rsdProgramVertexInit,
    101         rsdProgramVertexSetActive,
    102         rsdProgramVertexDestroy
    103     },
    104 
    105     {
    106         rsdProgramFragmentInit,
    107         rsdProgramFragmentSetActive,
    108         rsdProgramFragmentDestroy
    109     },
    110 
    111     {
    112         rsdMeshInit,
    113         rsdMeshDraw,
    114         rsdMeshDestroy
    115     },
    116 
    117     {
    118         rsdSamplerInit,
    119         rsdSamplerDestroy
    120     },
    121 
    122     {
    123         rsdFrameBufferInit,
    124         rsdFrameBufferSetActive,
    125         rsdFrameBufferDestroy
    126     },
    127 
    128 };
    129 
    130 pthread_key_t rsdgThreadTLSKey = 0;
    131 uint32_t rsdgThreadTLSKeyCount = 0;
    132 pthread_mutex_t rsdgInitMutex = PTHREAD_MUTEX_INITIALIZER;
    133 
    134 
    135 static void * HelperThreadProc(void *vrsc) {
    136     Context *rsc = static_cast<Context *>(vrsc);
    137     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    138 
    139 
    140     uint32_t idx = (uint32_t)android_atomic_inc(&dc->mWorkers.mLaunchCount);
    141 
    142     //LOGV("RS helperThread starting %p idx=%i", rsc, idx);
    143 
    144     dc->mWorkers.mLaunchSignals[idx].init();
    145     dc->mWorkers.mNativeThreadId[idx] = gettid();
    146 
    147     int status = pthread_setspecific(rsdgThreadTLSKey, &dc->mTlsStruct);
    148     if (status) {
    149         LOGE("pthread_setspecific %i", status);
    150     }
    151 
    152 #if 0
    153     typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t;
    154     cpu_set_t cpuset;
    155     memset(&cpuset, 0, sizeof(cpuset));
    156     cpuset.bits[idx / 64] |= 1ULL << (idx % 64);
    157     int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx],
    158               sizeof(cpuset), &cpuset);
    159     LOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret));
    160 #endif
    161 
    162     while (!dc->mExit) {
    163         dc->mWorkers.mLaunchSignals[idx].wait();
    164         if (dc->mWorkers.mLaunchCallback) {
    165            dc->mWorkers.mLaunchCallback(dc->mWorkers.mLaunchData, idx);
    166         }
    167         android_atomic_dec(&dc->mWorkers.mRunningCount);
    168         dc->mWorkers.mCompleteSignal.set();
    169     }
    170 
    171     //LOGV("RS helperThread exited %p idx=%i", rsc, idx);
    172     return NULL;
    173 }
    174 
    175 void 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 
    189 bool 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 
    260 void 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 
    267 void 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 
    294 static void rsdForEach17(const void *vRoot,
    295         const android::renderscript::RsForEachStubParamStruct *p) {
    296     typedef void (*fe)(const void *, uint32_t);
    297     (*(fe*)vRoot)(p->in, p->y);
    298 }
    299 
    300 static void rsdForEach18(const void *vRoot,
    301         const android::renderscript::RsForEachStubParamStruct *p) {
    302     typedef void (*fe)(void *, uint32_t);
    303     (*(fe*)vRoot)(p->out, p->y);
    304 }
    305 
    306 static void rsdForEach19(const void *vRoot,
    307         const android::renderscript::RsForEachStubParamStruct *p) {
    308     typedef void (*fe)(const void *, void *, uint32_t);
    309     (*(fe*)vRoot)(p->in, p->out, p->y);
    310 }
    311 
    312 static void rsdForEach21(const void *vRoot,
    313         const android::renderscript::RsForEachStubParamStruct *p) {
    314     typedef void (*fe)(const void *, const void *, uint32_t);
    315     (*(fe*)vRoot)(p->in, p->usr, p->y);
    316 }
    317 
    318 static void rsdForEach22(const void *vRoot,
    319         const android::renderscript::RsForEachStubParamStruct *p) {
    320     typedef void (*fe)(void *, const void *, uint32_t);
    321     (*(fe*)vRoot)(p->out, p->usr, p->y);
    322 }
    323 
    324 static void rsdForEach23(const void *vRoot,
    325         const android::renderscript::RsForEachStubParamStruct *p) {
    326     typedef void (*fe)(const void *, void *, const void *, uint32_t);
    327     (*(fe*)vRoot)(p->in, p->out, p->usr, p->y);
    328 }
    329 
    330 static void rsdForEach25(const void *vRoot,
    331         const android::renderscript::RsForEachStubParamStruct *p) {
    332     typedef void (*fe)(const void *, uint32_t, uint32_t);
    333     (*(fe*)vRoot)(p->in, p->x, p->y);
    334 }
    335 
    336 static void rsdForEach26(const void *vRoot,
    337         const android::renderscript::RsForEachStubParamStruct *p) {
    338     typedef void (*fe)(void *, uint32_t, uint32_t);
    339     (*(fe*)vRoot)(p->out, p->x, p->y);
    340 }
    341 
    342 static void rsdForEach27(const void *vRoot,
    343         const android::renderscript::RsForEachStubParamStruct *p) {
    344     typedef void (*fe)(const void *, void *, uint32_t, uint32_t);
    345     (*(fe*)vRoot)(p->in, p->out, p->x, p->y);
    346 }
    347 
    348 static void rsdForEach29(const void *vRoot,
    349         const android::renderscript::RsForEachStubParamStruct *p) {
    350     typedef void (*fe)(const void *, const void *, uint32_t, uint32_t);
    351     (*(fe*)vRoot)(p->in, p->usr, p->x, p->y);
    352 }
    353 
    354 static void rsdForEach30(const void *vRoot,
    355         const android::renderscript::RsForEachStubParamStruct *p) {
    356     typedef void (*fe)(void *, const void *, uint32_t, uint32_t);
    357     (*(fe*)vRoot)(p->out, p->usr, p->x, p->y);
    358 }
    359 
    360 static void rsdForEach31(const void *vRoot,
    361         const android::renderscript::RsForEachStubParamStruct *p) {
    362     typedef void (*fe)(const void *, void *, const void *, uint32_t, uint32_t);
    363     (*(fe*)vRoot)(p->in, p->out, p->usr, p->x, p->y);
    364 }
    365 
    366 
    367 static void initForEach(outer_foreach_t* forEachLaunch) {
    368     rsAssert(forEachLaunch);
    369     forEachLaunch[0x00] = NULL;
    370     forEachLaunch[0x01] = rsdForEach31; // in
    371     forEachLaunch[0x02] = rsdForEach30; //     out
    372     forEachLaunch[0x03] = rsdForEach31; // in, out
    373     forEachLaunch[0x04] = NULL;
    374     forEachLaunch[0x05] = rsdForEach29;  // in,      usr
    375     forEachLaunch[0x06] = rsdForEach30; //     out, usr
    376     forEachLaunch[0x07] = rsdForEach31; // in, out, usr
    377     forEachLaunch[0x08] = NULL;
    378     forEachLaunch[0x09] = rsdForEach25; // in,           x
    379     forEachLaunch[0x0a] = rsdForEach26; //     out,      x
    380     forEachLaunch[0x0b] = rsdForEach27; // in, out,      x
    381     forEachLaunch[0x0c] = NULL;
    382     forEachLaunch[0x0d] = rsdForEach29; // in,      usr, x
    383     forEachLaunch[0x0e] = rsdForEach30; //     out, usr, x
    384     forEachLaunch[0x0f] = rsdForEach31; // in, out, usr, x
    385     forEachLaunch[0x10] = NULL;
    386     forEachLaunch[0x11] = rsdForEach17; // in               y
    387     forEachLaunch[0x12] = rsdForEach18; //     out,         y
    388     forEachLaunch[0x13] = rsdForEach19; // in, out,         y
    389     forEachLaunch[0x14] = NULL;
    390     forEachLaunch[0x15] = rsdForEach21; // in,      usr,    y
    391     forEachLaunch[0x16] = rsdForEach22; //     out, usr,    y
    392     forEachLaunch[0x17] = rsdForEach23; // in, out, usr,    y
    393     forEachLaunch[0x18] = NULL;
    394     forEachLaunch[0x19] = rsdForEach25; // in,           x, y
    395     forEachLaunch[0x1a] = rsdForEach26; //     out,      x, y
    396     forEachLaunch[0x1b] = rsdForEach27; // in, out,      x, y
    397     forEachLaunch[0x1c] = NULL;
    398     forEachLaunch[0x1d] = rsdForEach29; // in,      usr, x, y
    399     forEachLaunch[0x1e] = rsdForEach30; //     out, usr, x, y
    400     forEachLaunch[0x1f] = rsdForEach31; // in, out, usr, x, y
    401 }
    402 
    403