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 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 302 static 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 310 static 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 318 static 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 326 static 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 334 static 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 342 static 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 355 static 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 368 static 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 383 static 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 397 static 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 411 static 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 428 static 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