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 "rs.h" 18 #include "rsDevice.h" 19 #include "rsContext.h" 20 #include "rsThreadIO.h" 21 22 #ifndef RS_COMPATIBILITY_LIB 23 #include "rsMesh.h" 24 #include <ui/FramebufferNativeWindow.h> 25 #include <gui/DisplayEventReceiver.h> 26 #endif 27 28 #include <sys/types.h> 29 #include <sys/resource.h> 30 #include <sched.h> 31 32 #include <sys/syscall.h> 33 #include <string.h> 34 #include <dlfcn.h> 35 #include <unistd.h> 36 37 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB) && \ 38 defined(HAVE_ANDROID_OS) 39 #include <cutils/properties.h> 40 #endif 41 42 #ifdef RS_COMPATIBILITY_LIB 43 #include "rsCompatibilityLib.h" 44 #endif 45 46 #ifdef RS_SERVER 47 // Android exposes gettid(), standard Linux does not 48 static pid_t gettid() { 49 return syscall(SYS_gettid); 50 } 51 #endif 52 53 using namespace android; 54 using namespace android::renderscript; 55 56 pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER; 57 pthread_mutex_t Context::gMessageMutex = PTHREAD_MUTEX_INITIALIZER; 58 pthread_mutex_t Context::gLibMutex = PTHREAD_MUTEX_INITIALIZER; 59 60 bool Context::initGLThread() { 61 pthread_mutex_lock(&gInitMutex); 62 63 if (!mHal.funcs.initGraphics(this)) { 64 pthread_mutex_unlock(&gInitMutex); 65 ALOGE("%p initGraphics failed", this); 66 return false; 67 } 68 69 pthread_mutex_unlock(&gInitMutex); 70 return true; 71 } 72 73 void Context::deinitEGL() { 74 #ifndef RS_COMPATIBILITY_LIB 75 mHal.funcs.shutdownGraphics(this); 76 #endif 77 } 78 79 Context::PushState::PushState(Context *con) { 80 mRsc = con; 81 #ifndef RS_COMPATIBILITY_LIB 82 if (con->mIsGraphicsContext) { 83 mFragment.set(con->getProgramFragment()); 84 mVertex.set(con->getProgramVertex()); 85 mStore.set(con->getProgramStore()); 86 mRaster.set(con->getProgramRaster()); 87 mFont.set(con->getFont()); 88 } 89 #endif 90 } 91 92 Context::PushState::~PushState() { 93 #ifndef RS_COMPATIBILITY_LIB 94 if (mRsc->mIsGraphicsContext) { 95 mRsc->setProgramFragment(mFragment.get()); 96 mRsc->setProgramVertex(mVertex.get()); 97 mRsc->setProgramStore(mStore.get()); 98 mRsc->setProgramRaster(mRaster.get()); 99 mRsc->setFont(mFont.get()); 100 } 101 #endif 102 } 103 104 105 uint32_t Context::runScript(Script *s) { 106 PushState ps(this); 107 108 uint32_t ret = s->run(this); 109 return ret; 110 } 111 112 uint32_t Context::runRootScript() { 113 timerSet(RS_TIMER_SCRIPT); 114 #ifndef RS_COMPATIBILITY_LIB 115 mStateFragmentStore.mLast.clear(); 116 #endif 117 watchdog.inRoot = true; 118 uint32_t ret = runScript(mRootScript.get()); 119 watchdog.inRoot = false; 120 121 return ret; 122 } 123 124 uint64_t Context::getTime() const { 125 #ifndef ANDROID_RS_SERIALIZE 126 struct timespec t; 127 clock_gettime(CLOCK_MONOTONIC, &t); 128 return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000); 129 #else 130 return 0; 131 #endif //ANDROID_RS_SERIALIZE 132 } 133 134 void Context::timerReset() { 135 for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) { 136 mTimers[ct] = 0; 137 } 138 } 139 140 void Context::timerInit() { 141 mTimeLast = getTime(); 142 mTimeFrame = mTimeLast; 143 mTimeLastFrame = mTimeLast; 144 mTimerActive = RS_TIMER_INTERNAL; 145 mAverageFPSFrameCount = 0; 146 mAverageFPSStartTime = mTimeLast; 147 mAverageFPS = 0; 148 timerReset(); 149 } 150 151 void Context::timerFrame() { 152 mTimeLastFrame = mTimeFrame; 153 mTimeFrame = getTime(); 154 // Update average fps 155 const uint64_t averageFramerateInterval = 1000 * 1000000; 156 mAverageFPSFrameCount ++; 157 uint64_t inverval = mTimeFrame - mAverageFPSStartTime; 158 if (inverval >= averageFramerateInterval) { 159 inverval = inverval / 1000000; 160 mAverageFPS = (mAverageFPSFrameCount * 1000) / inverval; 161 mAverageFPSFrameCount = 0; 162 mAverageFPSStartTime = mTimeFrame; 163 } 164 } 165 166 void Context::timerSet(Timers tm) { 167 uint64_t last = mTimeLast; 168 mTimeLast = getTime(); 169 mTimers[mTimerActive] += mTimeLast - last; 170 mTimerActive = tm; 171 } 172 173 void Context::timerPrint() { 174 double total = 0; 175 for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) { 176 total += mTimers[ct]; 177 } 178 uint64_t frame = mTimeFrame - mTimeLastFrame; 179 mTimeMSLastFrame = frame / 1000000; 180 mTimeMSLastScript = mTimers[RS_TIMER_SCRIPT] / 1000000; 181 mTimeMSLastSwap = mTimers[RS_TIMER_CLEAR_SWAP] / 1000000; 182 183 184 if (props.mLogTimes) { 185 ALOGV("RS: Frame (%i), Script %2.1f%% (%i), Swap %2.1f%% (%i), Idle %2.1f%% (%lli), Internal %2.1f%% (%lli), Avg fps: %u", 186 mTimeMSLastFrame, 187 100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimeMSLastScript, 188 100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimeMSLastSwap, 189 100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000, 190 100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000, 191 mAverageFPS); 192 } 193 } 194 195 bool Context::setupCheck() { 196 #ifndef RS_COMPATIBILITY_LIB 197 mFragmentStore->setup(this, &mStateFragmentStore); 198 mFragment->setup(this, &mStateFragment); 199 mRaster->setup(this, &mStateRaster); 200 mVertex->setup(this, &mStateVertex); 201 mFBOCache.setup(this); 202 #endif 203 return true; 204 } 205 206 #ifndef RS_COMPATIBILITY_LIB 207 void Context::setupProgramStore() { 208 mFragmentStore->setup(this, &mStateFragmentStore); 209 } 210 #endif 211 212 static uint32_t getProp(const char *str) { 213 #if !defined(RS_SERVER) && defined(HAVE_ANDROID_OS) 214 char buf[PROPERTY_VALUE_MAX]; 215 property_get(str, buf, "0"); 216 return atoi(buf); 217 #else 218 return 0; 219 #endif 220 } 221 222 void Context::displayDebugStats() { 223 #ifndef RS_COMPATIBILITY_LIB 224 char buffer[128]; 225 sprintf(buffer, "Avg fps %u, Frame %i ms, Script %i ms", mAverageFPS, mTimeMSLastFrame, mTimeMSLastScript); 226 float oldR, oldG, oldB, oldA; 227 mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA); 228 uint32_t bufferLen = strlen(buffer); 229 230 ObjectBaseRef<Font> lastFont(getFont()); 231 setFont(NULL); 232 float shadowCol = 0.1f; 233 mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f); 234 mStateFont.renderText(buffer, bufferLen, 5, getHeight() - 6); 235 236 mStateFont.setFontColor(1.0f, 0.7f, 0.0f, 1.0f); 237 mStateFont.renderText(buffer, bufferLen, 4, getHeight() - 7); 238 239 setFont(lastFont.get()); 240 mStateFont.setFontColor(oldR, oldG, oldB, oldA); 241 #endif 242 } 243 244 bool Context::loadRuntime(const char* filename, Context* rsc) { 245 246 // TODO: store the driverSO somewhere so we can dlclose later 247 void *driverSO = NULL; 248 249 driverSO = dlopen(filename, RTLD_LAZY); 250 if (driverSO == NULL) { 251 ALOGE("Failed loading RS driver: %s", dlerror()); 252 return false; 253 } 254 255 // Need to call dlerror() to clear buffer before using it for dlsym(). 256 (void) dlerror(); 257 typedef bool (*HalSig)(Context*, uint32_t, uint32_t); 258 HalSig halInit = (HalSig) dlsym(driverSO, "rsdHalInit"); 259 260 // If we can't find the C variant, we go looking for the C++ version. 261 if (halInit == NULL) { 262 ALOGW("Falling back to find C++ rsdHalInit: %s", dlerror()); 263 halInit = (HalSig) dlsym(driverSO, 264 "_Z10rsdHalInitPN7android12renderscript7ContextEjj"); 265 } 266 267 if (halInit == NULL) { 268 dlclose(driverSO); 269 ALOGE("Failed to find rsdHalInit: %s", dlerror()); 270 return false; 271 } 272 273 if (!(*halInit)(rsc, 0, 0)) { 274 dlclose(driverSO); 275 ALOGE("Hal init failed"); 276 return false; 277 } 278 279 //validate HAL struct 280 281 282 return true; 283 } 284 285 extern "C" bool rsdHalInit(RsContext c, uint32_t version_major, uint32_t version_minor); 286 287 void * Context::threadProc(void *vrsc) { 288 Context *rsc = static_cast<Context *>(vrsc); 289 #ifndef ANDROID_RS_SERIALIZE 290 rsc->mNativeThreadId = gettid(); 291 #ifndef RS_COMPATIBILITY_LIB 292 if (!rsc->isSynchronous()) { 293 setpriority(PRIO_PROCESS, rsc->mNativeThreadId, ANDROID_PRIORITY_DISPLAY); 294 } 295 rsc->mThreadPriority = ANDROID_PRIORITY_DISPLAY; 296 #else 297 if (!rsc->isSynchronous()) { 298 setpriority(PRIO_PROCESS, rsc->mNativeThreadId, -4); 299 } 300 rsc->mThreadPriority = -4; 301 #endif 302 #endif //ANDROID_RS_SERIALIZE 303 rsc->props.mLogTimes = getProp("debug.rs.profile") != 0; 304 rsc->props.mLogScripts = getProp("debug.rs.script") != 0; 305 rsc->props.mLogObjects = getProp("debug.rs.object") != 0; 306 rsc->props.mLogShaders = getProp("debug.rs.shader") != 0; 307 rsc->props.mLogShadersAttr = getProp("debug.rs.shader.attributes") != 0; 308 rsc->props.mLogShadersUniforms = getProp("debug.rs.shader.uniforms") != 0; 309 rsc->props.mLogVisual = getProp("debug.rs.visual") != 0; 310 rsc->props.mDebugMaxThreads = getProp("debug.rs.max-threads"); 311 312 bool loadDefault = true; 313 314 // Provide a mechanism for dropping in a different RS driver. 315 #ifndef RS_COMPATIBILITY_LIB 316 #ifdef OVERRIDE_RS_DRIVER 317 #define XSTR(S) #S 318 #define STR(S) XSTR(S) 319 #define OVERRIDE_RS_DRIVER_STRING STR(OVERRIDE_RS_DRIVER) 320 321 if (getProp("debug.rs.default-CPU-driver") != 0) { 322 ALOGE("Skipping override driver and loading default CPU driver"); 323 } else if (rsc->mForceCpu) { 324 ALOGV("Application requested CPU execution"); 325 } else if (rsc->getContextType() == RS_CONTEXT_TYPE_DEBUG) { 326 ALOGV("Application requested debug context"); 327 } else { 328 if (loadRuntime(OVERRIDE_RS_DRIVER_STRING, rsc)) { 329 ALOGE("Successfully loaded runtime: %s", OVERRIDE_RS_DRIVER_STRING); 330 loadDefault = false; 331 } else { 332 ALOGE("Failed to load runtime %s, loading default", OVERRIDE_RS_DRIVER_STRING); 333 } 334 } 335 336 #undef XSTR 337 #undef STR 338 #endif // OVERRIDE_RS_DRIVER 339 340 if (loadDefault) { 341 if (!loadRuntime("libRSDriver.so", rsc)) { 342 ALOGE("Failed to load default runtime!"); 343 rsc->setError(RS_ERROR_FATAL_DRIVER, "Failed loading RS driver"); 344 return NULL; 345 } 346 } 347 #else // RS_COMPATIBILITY_LIB 348 if (rsdHalInit(rsc, 0, 0) != true) { 349 return NULL; 350 } 351 #endif 352 353 354 rsc->mHal.funcs.setPriority(rsc, rsc->mThreadPriority); 355 356 #ifndef RS_COMPATIBILITY_LIB 357 if (rsc->mIsGraphicsContext) { 358 if (!rsc->initGLThread()) { 359 rsc->setError(RS_ERROR_OUT_OF_MEMORY, "Failed initializing GL"); 360 return NULL; 361 } 362 363 rsc->mStateRaster.init(rsc); 364 rsc->setProgramRaster(NULL); 365 rsc->mStateVertex.init(rsc); 366 rsc->setProgramVertex(NULL); 367 rsc->mStateFragment.init(rsc); 368 rsc->setProgramFragment(NULL); 369 rsc->mStateFragmentStore.init(rsc); 370 rsc->setProgramStore(NULL); 371 rsc->mStateFont.init(rsc); 372 rsc->setFont(NULL); 373 rsc->mStateSampler.init(rsc); 374 rsc->mFBOCache.init(rsc); 375 } 376 #endif 377 378 rsc->mRunning = true; 379 380 if (rsc->isSynchronous()) { 381 return NULL; 382 } 383 384 if (!rsc->mIsGraphicsContext) { 385 while (!rsc->mExit) { 386 rsc->mIO.playCoreCommands(rsc, -1); 387 } 388 #ifndef RS_COMPATIBILITY_LIB 389 } else { 390 #ifndef ANDROID_RS_SERIALIZE 391 DisplayEventReceiver displayEvent; 392 DisplayEventReceiver::Event eventBuffer[1]; 393 #endif 394 int vsyncRate = 0; 395 int targetRate = 0; 396 397 bool drawOnce = false; 398 while (!rsc->mExit) { 399 rsc->timerSet(RS_TIMER_IDLE); 400 401 #ifndef ANDROID_RS_SERIALIZE 402 if (!rsc->mRootScript.get() || !rsc->mHasSurface || rsc->mPaused) { 403 targetRate = 0; 404 } 405 406 if (vsyncRate != targetRate) { 407 displayEvent.setVsyncRate(targetRate); 408 vsyncRate = targetRate; 409 } 410 if (targetRate) { 411 drawOnce |= rsc->mIO.playCoreCommands(rsc, displayEvent.getFd()); 412 while (displayEvent.getEvents(eventBuffer, 1) != 0) { 413 //ALOGE("vs2 time past %lld", (rsc->getTime() - eventBuffer[0].header.timestamp) / 1000000); 414 } 415 } else 416 #endif 417 { 418 drawOnce |= rsc->mIO.playCoreCommands(rsc, -1); 419 } 420 421 if ((rsc->mRootScript.get() != NULL) && rsc->mHasSurface && 422 (targetRate || drawOnce) && !rsc->mPaused) { 423 424 drawOnce = false; 425 targetRate = ((rsc->runRootScript() + 15) / 16); 426 427 if (rsc->props.mLogVisual) { 428 rsc->displayDebugStats(); 429 } 430 431 rsc->timerSet(RS_TIMER_CLEAR_SWAP); 432 rsc->mHal.funcs.swap(rsc); 433 rsc->timerFrame(); 434 rsc->timerSet(RS_TIMER_INTERNAL); 435 rsc->timerPrint(); 436 rsc->timerReset(); 437 } 438 } 439 #endif 440 } 441 442 //ALOGV("%p RS Thread exiting", rsc); 443 444 #ifndef RS_COMPATIBILITY_LIB 445 if (rsc->mIsGraphicsContext) { 446 pthread_mutex_lock(&gInitMutex); 447 rsc->deinitEGL(); 448 pthread_mutex_unlock(&gInitMutex); 449 } 450 #endif 451 452 //ALOGV("%p RS Thread exited", rsc); 453 return NULL; 454 } 455 456 void Context::destroyWorkerThreadResources() { 457 //ALOGV("destroyWorkerThreadResources 1"); 458 ObjectBase::zeroAllUserRef(this); 459 #ifndef RS_COMPATIBILITY_LIB 460 if (mIsGraphicsContext) { 461 mRaster.clear(); 462 mFragment.clear(); 463 mVertex.clear(); 464 mFragmentStore.clear(); 465 mFont.clear(); 466 mRootScript.clear(); 467 mStateRaster.deinit(this); 468 mStateVertex.deinit(this); 469 mStateFragment.deinit(this); 470 mStateFragmentStore.deinit(this); 471 mStateFont.deinit(this); 472 mStateSampler.deinit(this); 473 mFBOCache.deinit(this); 474 } 475 #endif 476 ObjectBase::freeAllChildren(this); 477 mExit = true; 478 //ALOGV("destroyWorkerThreadResources 2"); 479 } 480 481 void Context::printWatchdogInfo(void *ctx) { 482 Context *rsc = (Context *)ctx; 483 if (rsc->watchdog.command && rsc->watchdog.file) { 484 ALOGE("RS watchdog timeout: %i %s line %i %s", rsc->watchdog.inRoot, 485 rsc->watchdog.command, rsc->watchdog.line, rsc->watchdog.file); 486 } else { 487 ALOGE("RS watchdog timeout: %i", rsc->watchdog.inRoot); 488 } 489 } 490 491 492 void Context::setPriority(int32_t p) { 493 // Note: If we put this in the proper "background" policy 494 // the wallpapers can become completly unresponsive at times. 495 // This is probably not what we want for something the user is actively 496 // looking at. 497 mThreadPriority = p; 498 setpriority(PRIO_PROCESS, mNativeThreadId, p); 499 mHal.funcs.setPriority(this, mThreadPriority); 500 } 501 502 Context::Context() { 503 mDev = NULL; 504 mRunning = false; 505 mExit = false; 506 mPaused = false; 507 mObjHead = NULL; 508 mError = RS_ERROR_NONE; 509 mTargetSdkVersion = 14; 510 mDPI = 96; 511 mIsContextLite = false; 512 memset(&watchdog, 0, sizeof(watchdog)); 513 mForceCpu = false; 514 mContextType = RS_CONTEXT_TYPE_NORMAL; 515 mSynchronous = false; 516 } 517 518 Context * Context::createContext(Device *dev, const RsSurfaceConfig *sc, 519 RsContextType ct, uint32_t flags) { 520 Context * rsc = new Context(); 521 522 if (flags & RS_CONTEXT_LOW_LATENCY) { 523 rsc->mForceCpu = true; 524 } 525 if (flags & RS_CONTEXT_SYNCHRONOUS) { 526 rsc->mSynchronous = true; 527 } 528 rsc->mContextType = ct; 529 530 if (!rsc->initContext(dev, sc)) { 531 delete rsc; 532 return NULL; 533 } 534 return rsc; 535 } 536 537 Context * Context::createContextLite() { 538 Context * rsc = new Context(); 539 rsc->mIsContextLite = true; 540 return rsc; 541 } 542 543 bool Context::initContext(Device *dev, const RsSurfaceConfig *sc) { 544 pthread_mutex_lock(&gInitMutex); 545 546 mIO.init(); 547 mIO.setTimeoutCallback(printWatchdogInfo, this, 2e9); 548 549 dev->addContext(this); 550 mDev = dev; 551 if (sc) { 552 mUserSurfaceConfig = *sc; 553 } else { 554 memset(&mUserSurfaceConfig, 0, sizeof(mUserSurfaceConfig)); 555 } 556 557 mIsGraphicsContext = sc != NULL; 558 559 int status; 560 pthread_attr_t threadAttr; 561 562 pthread_mutex_unlock(&gInitMutex); 563 564 // Global init done at this point. 565 566 status = pthread_attr_init(&threadAttr); 567 if (status) { 568 ALOGE("Failed to init thread attribute."); 569 return false; 570 } 571 572 mHasSurface = false; 573 574 timerInit(); 575 timerSet(RS_TIMER_INTERNAL); 576 if (mSynchronous) { 577 threadProc(this); 578 } else { 579 status = pthread_create(&mThreadId, &threadAttr, threadProc, this); 580 if (status) { 581 ALOGE("Failed to start rs context thread."); 582 return false; 583 } 584 while (!mRunning && (mError == RS_ERROR_NONE)) { 585 usleep(100); 586 } 587 588 if (mError != RS_ERROR_NONE) { 589 ALOGE("Errors during thread init"); 590 return false; 591 } 592 593 pthread_attr_destroy(&threadAttr); 594 } 595 return true; 596 } 597 598 Context::~Context() { 599 //ALOGV("%p Context::~Context", this); 600 601 if (!mIsContextLite) { 602 mPaused = false; 603 void *res; 604 605 mIO.shutdown(); 606 int status = pthread_join(mThreadId, &res); 607 rsAssert(mExit); 608 609 if (mHal.funcs.shutdownDriver) { 610 mHal.funcs.shutdownDriver(this); 611 } 612 613 // Global structure cleanup. 614 pthread_mutex_lock(&gInitMutex); 615 if (mDev) { 616 mDev->removeContext(this); 617 mDev = NULL; 618 } 619 pthread_mutex_unlock(&gInitMutex); 620 } 621 //ALOGV("%p Context::~Context done", this); 622 } 623 624 #ifndef RS_COMPATIBILITY_LIB 625 void Context::setSurface(uint32_t w, uint32_t h, RsNativeWindow sur) { 626 rsAssert(mIsGraphicsContext); 627 mHal.funcs.setSurface(this, w, h, sur); 628 629 mHasSurface = sur != NULL; 630 mWidth = w; 631 mHeight = h; 632 633 if (mWidth && mHeight) { 634 mStateVertex.updateSize(this); 635 mFBOCache.updateSize(); 636 } 637 } 638 639 uint32_t Context::getCurrentSurfaceWidth() const { 640 for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) { 641 if (mFBOCache.mHal.state.colorTargets[i] != NULL) { 642 return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimX(); 643 } 644 } 645 if (mFBOCache.mHal.state.depthTarget != NULL) { 646 return mFBOCache.mHal.state.depthTarget->getType()->getDimX(); 647 } 648 return mWidth; 649 } 650 651 uint32_t Context::getCurrentSurfaceHeight() const { 652 for (uint32_t i = 0; i < mFBOCache.mHal.state.colorTargetsCount; i ++) { 653 if (mFBOCache.mHal.state.colorTargets[i] != NULL) { 654 return mFBOCache.mHal.state.colorTargets[i]->getType()->getDimY(); 655 } 656 } 657 if (mFBOCache.mHal.state.depthTarget != NULL) { 658 return mFBOCache.mHal.state.depthTarget->getType()->getDimY(); 659 } 660 return mHeight; 661 } 662 663 void Context::pause() { 664 rsAssert(mIsGraphicsContext); 665 mPaused = true; 666 } 667 668 void Context::resume() { 669 rsAssert(mIsGraphicsContext); 670 mPaused = false; 671 } 672 673 void Context::setRootScript(Script *s) { 674 rsAssert(mIsGraphicsContext); 675 mRootScript.set(s); 676 } 677 678 void Context::setProgramStore(ProgramStore *pfs) { 679 rsAssert(mIsGraphicsContext); 680 if (pfs == NULL) { 681 mFragmentStore.set(mStateFragmentStore.mDefault); 682 } else { 683 mFragmentStore.set(pfs); 684 } 685 } 686 687 void Context::setProgramFragment(ProgramFragment *pf) { 688 rsAssert(mIsGraphicsContext); 689 if (pf == NULL) { 690 mFragment.set(mStateFragment.mDefault); 691 } else { 692 mFragment.set(pf); 693 } 694 } 695 696 void Context::setProgramRaster(ProgramRaster *pr) { 697 rsAssert(mIsGraphicsContext); 698 if (pr == NULL) { 699 mRaster.set(mStateRaster.mDefault); 700 } else { 701 mRaster.set(pr); 702 } 703 } 704 705 void Context::setProgramVertex(ProgramVertex *pv) { 706 rsAssert(mIsGraphicsContext); 707 if (pv == NULL) { 708 mVertex.set(mStateVertex.mDefault); 709 } else { 710 mVertex.set(pv); 711 } 712 } 713 714 void Context::setFont(Font *f) { 715 rsAssert(mIsGraphicsContext); 716 if (f == NULL) { 717 mFont.set(mStateFont.mDefault); 718 } else { 719 mFont.set(f); 720 } 721 } 722 #endif 723 724 void Context::assignName(ObjectBase *obj, const char *name, uint32_t len) { 725 rsAssert(!obj->getName()); 726 obj->setName(name, len); 727 mNames.add(obj); 728 } 729 730 void Context::removeName(ObjectBase *obj) { 731 for (size_t ct=0; ct < mNames.size(); ct++) { 732 if (obj == mNames[ct]) { 733 mNames.removeAt(ct); 734 return; 735 } 736 } 737 } 738 739 RsMessageToClientType Context::peekMessageToClient(size_t *receiveLen, uint32_t *subID) { 740 return (RsMessageToClientType)mIO.getClientHeader(receiveLen, subID); 741 } 742 743 RsMessageToClientType Context::getMessageToClient(void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen) { 744 return (RsMessageToClientType)mIO.getClientPayload(data, receiveLen, subID, bufferLen); 745 } 746 747 bool Context::sendMessageToClient(const void *data, RsMessageToClientType cmdID, 748 uint32_t subID, size_t len, bool waitForSpace) const { 749 750 pthread_mutex_lock(&gMessageMutex); 751 bool ret = mIO.sendToClient(cmdID, subID, data, len, waitForSpace); 752 pthread_mutex_unlock(&gMessageMutex); 753 return ret; 754 } 755 756 void Context::initToClient() { 757 while (!mRunning) { 758 usleep(100); 759 } 760 } 761 762 void Context::deinitToClient() { 763 mIO.clientShutdown(); 764 } 765 766 void Context::setError(RsError e, const char *msg) const { 767 mError = e; 768 sendMessageToClient(msg, RS_MESSAGE_TO_CLIENT_ERROR, e, strlen(msg) + 1, true); 769 } 770 771 772 void Context::dumpDebug() const { 773 ALOGE("RS Context debug %p", this); 774 ALOGE("RS Context debug"); 775 776 ALOGE(" RS width %i, height %i", mWidth, mHeight); 777 ALOGE(" RS running %i, exit %i, paused %i", mRunning, mExit, mPaused); 778 ALOGE(" RS pThreadID %li, nativeThreadID %i", (long int)mThreadId, mNativeThreadId); 779 } 780 781 /////////////////////////////////////////////////////////////////////////////////////////// 782 // 783 784 namespace android { 785 namespace renderscript { 786 787 void rsi_ContextFinish(Context *rsc) { 788 } 789 790 void rsi_ContextBindRootScript(Context *rsc, RsScript vs) { 791 #ifndef RS_COMPATIBILITY_LIB 792 Script *s = static_cast<Script *>(vs); 793 rsc->setRootScript(s); 794 #endif 795 } 796 797 void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs) { 798 Sampler *s = static_cast<Sampler *>(vs); 799 800 if (slot > RS_MAX_SAMPLER_SLOT) { 801 ALOGE("Invalid sampler slot"); 802 return; 803 } 804 805 s->bindToContext(&rsc->mStateSampler, slot); 806 } 807 808 #ifndef RS_COMPATIBILITY_LIB 809 void rsi_ContextBindProgramStore(Context *rsc, RsProgramStore vpfs) { 810 ProgramStore *pfs = static_cast<ProgramStore *>(vpfs); 811 rsc->setProgramStore(pfs); 812 } 813 814 void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf) { 815 ProgramFragment *pf = static_cast<ProgramFragment *>(vpf); 816 rsc->setProgramFragment(pf); 817 } 818 819 void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr) { 820 ProgramRaster *pr = static_cast<ProgramRaster *>(vpr); 821 rsc->setProgramRaster(pr); 822 } 823 824 void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv) { 825 ProgramVertex *pv = static_cast<ProgramVertex *>(vpv); 826 rsc->setProgramVertex(pv); 827 } 828 829 void rsi_ContextBindFont(Context *rsc, RsFont vfont) { 830 Font *font = static_cast<Font *>(vfont); 831 rsc->setFont(font); 832 } 833 #endif 834 835 void rsi_AssignName(Context *rsc, RsObjectBase obj, const char *name, size_t name_length) { 836 ObjectBase *ob = static_cast<ObjectBase *>(obj); 837 rsc->assignName(ob, name, name_length); 838 } 839 840 void rsi_ObjDestroy(Context *rsc, void *optr) { 841 ObjectBase *ob = static_cast<ObjectBase *>(optr); 842 rsc->removeName(ob); 843 ob->decUserRef(); 844 } 845 846 #ifndef RS_COMPATIBILITY_LIB 847 void rsi_ContextPause(Context *rsc) { 848 rsc->pause(); 849 } 850 851 void rsi_ContextResume(Context *rsc) { 852 rsc->resume(); 853 } 854 855 void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) { 856 rsc->setSurface(w, h, sur); 857 } 858 #endif 859 860 void rsi_ContextSetPriority(Context *rsc, int32_t p) { 861 rsc->setPriority(p); 862 } 863 864 void rsi_ContextDump(Context *rsc, int32_t bits) { 865 ObjectBase::dumpAll(rsc); 866 } 867 868 void rsi_ContextDestroyWorker(Context *rsc) { 869 rsc->destroyWorkerThreadResources(); 870 } 871 872 void rsi_ContextDestroy(Context *rsc) { 873 //ALOGV("%p rsContextDestroy", rsc); 874 rsContextDestroyWorker(rsc); 875 delete rsc; 876 //ALOGV("%p rsContextDestroy done", rsc); 877 } 878 879 RsMessageToClientType rsi_ContextPeekMessage(Context *rsc, 880 size_t * receiveLen, size_t receiveLen_length, 881 uint32_t * subID, size_t subID_length) { 882 return rsc->peekMessageToClient(receiveLen, subID); 883 } 884 885 RsMessageToClientType rsi_ContextGetMessage(Context *rsc, void * data, size_t data_length, 886 size_t * receiveLen, size_t receiveLen_length, 887 uint32_t * subID, size_t subID_length) { 888 rsAssert(subID_length == sizeof(uint32_t)); 889 rsAssert(receiveLen_length == sizeof(size_t)); 890 return rsc->getMessageToClient(data, receiveLen, subID, data_length); 891 } 892 893 void rsi_ContextInitToClient(Context *rsc) { 894 rsc->initToClient(); 895 } 896 897 void rsi_ContextDeinitToClient(Context *rsc) { 898 rsc->deinitToClient(); 899 } 900 901 void rsi_ContextSendMessage(Context *rsc, uint32_t id, const uint8_t *data, size_t len) { 902 rsc->sendMessageToClient(data, RS_MESSAGE_TO_CLIENT_USER, id, len, true); 903 } 904 905 } 906 } 907 908 extern "C" RsContext rsContextCreate(RsDevice vdev, uint32_t version, uint32_t sdkVersion, 909 RsContextType ct, uint32_t flags) { 910 //ALOGV("rsContextCreate dev=%p", vdev); 911 Device * dev = static_cast<Device *>(vdev); 912 Context *rsc = Context::createContext(dev, NULL, ct, flags); 913 if (rsc) { 914 rsc->setTargetSdkVersion(sdkVersion); 915 } 916 return rsc; 917 } 918 919 #ifndef RS_COMPATIBILITY_LIB 920 RsContext rsContextCreateGL(RsDevice vdev, uint32_t version, 921 uint32_t sdkVersion, RsSurfaceConfig sc, 922 uint32_t dpi) { 923 //ALOGV("rsContextCreateGL dev=%p", vdev); 924 Device * dev = static_cast<Device *>(vdev); 925 Context *rsc = Context::createContext(dev, &sc); 926 if (rsc) { 927 rsc->setTargetSdkVersion(sdkVersion); 928 rsc->setDPI(dpi); 929 } 930 //ALOGV("%p rsContextCreateGL ret", rsc); 931 return rsc; 932 } 933 #endif 934 935 // Only to be called at a3d load time, before object is visible to user 936 // not thread safe 937 void rsaGetName(RsContext con, void * obj, const char **name) { 938 ObjectBase *ob = static_cast<ObjectBase *>(obj); 939 (*name) = ob->getName(); 940 } 941