rsContext.cpp revision fb03a22ad2adadc1ff50a8b50d43ad7fcc3fa6ed
1/* 2 * Copyright (C) 2009 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 "rsDevice.h" 18#include "rsContext.h" 19#include "rsThreadIO.h" 20#include <ui/FramebufferNativeWindow.h> 21#include <ui/EGLUtils.h> 22 23#include <cutils/properties.h> 24 25#include <GLES/gl.h> 26#include <GLES/glext.h> 27 28using namespace android; 29using namespace android::renderscript; 30 31pthread_key_t Context::gThreadTLSKey = 0; 32uint32_t Context::gThreadTLSKeyCount = 0; 33pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER; 34 35void Context::initEGL() 36{ 37 mEGL.mNumConfigs = -1; 38 EGLint configAttribs[128]; 39 EGLint *configAttribsPtr = configAttribs; 40 41 memset(configAttribs, 0, sizeof(configAttribs)); 42 43 configAttribsPtr[0] = EGL_SURFACE_TYPE; 44 configAttribsPtr[1] = EGL_WINDOW_BIT; 45 configAttribsPtr += 2; 46 47 if (mUseDepth) { 48 configAttribsPtr[0] = EGL_DEPTH_SIZE; 49 configAttribsPtr[1] = 16; 50 configAttribsPtr += 2; 51 } 52 53 if (mDev->mForceSW) { 54 configAttribsPtr[0] = EGL_CONFIG_CAVEAT; 55 configAttribsPtr[1] = EGL_SLOW_CONFIG; 56 configAttribsPtr += 2; 57 } 58 59 configAttribsPtr[0] = EGL_NONE; 60 rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint)))); 61 62 LOGV("initEGL start"); 63 mEGL.mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 64 eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion); 65 66 status_t err = EGLUtils::selectConfigForNativeWindow(mEGL.mDisplay, configAttribs, mWndSurface, &mEGL.mConfig); 67 if (err) { 68 LOGE("couldn't find an EGLConfig matching the screen format\n"); 69 } 70 //eglChooseConfig(mEGL.mDisplay, configAttribs, &mEGL.mConfig, 1, &mEGL.mNumConfigs); 71 72 if (mWndSurface) { 73 mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL); 74 } else { 75 mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, 76 android_createDisplaySurface(), 77 NULL); 78 } 79 80 mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, NULL, NULL); 81 eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext); 82 eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth); 83 eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight); 84 85 86 mGL.mVersion = glGetString(GL_VERSION); 87 mGL.mVendor = glGetString(GL_VENDOR); 88 mGL.mRenderer = glGetString(GL_RENDERER); 89 mGL.mExtensions = glGetString(GL_EXTENSIONS); 90 91 LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); 92 LOGV("GL Version %s", mGL.mVersion); 93 LOGV("GL Vendor %s", mGL.mVendor); 94 LOGV("GL Renderer %s", mGL.mRenderer); 95 LOGV("GL Extensions %s", mGL.mExtensions); 96 97 if ((strlen((const char *)mGL.mVersion) < 12) || memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) { 98 LOGE("Error, OpenGL ES Lite not supported"); 99 } else { 100 sscanf((const char *)mGL.mVersion + 13, "%i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion); 101 } 102} 103 104bool Context::runScript(Script *s, uint32_t launchID) 105{ 106 ObjectBaseRef<ProgramFragment> frag(mFragment); 107 ObjectBaseRef<ProgramVertex> vtx(mVertex); 108 ObjectBaseRef<ProgramFragmentStore> store(mFragmentStore); 109 ObjectBaseRef<ProgramRaster> raster(mRaster); 110 111 bool ret = s->run(this, launchID); 112 113 mFragment.set(frag); 114 mVertex.set(vtx); 115 mFragmentStore.set(store); 116 mRaster.set(raster); 117 return ret; 118} 119 120 121bool Context::runRootScript() 122{ 123 if (props.mLogTimes) { 124 timerSet(RS_TIMER_CLEAR_SWAP); 125 } 126 rsAssert(mRootScript->mEnviroment.mIsRoot); 127 128 eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth); 129 eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight); 130 glViewport(0, 0, mEGL.mWidth, mEGL.mHeight); 131 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 132 133 glClearColor(mRootScript->mEnviroment.mClearColor[0], 134 mRootScript->mEnviroment.mClearColor[1], 135 mRootScript->mEnviroment.mClearColor[2], 136 mRootScript->mEnviroment.mClearColor[3]); 137 if (mUseDepth) { 138 glDepthMask(GL_TRUE); 139 glClearDepthf(mRootScript->mEnviroment.mClearDepth); 140 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 141 } else { 142 glClear(GL_COLOR_BUFFER_BIT); 143 } 144 145 if (this->props.mLogTimes) { 146 timerSet(RS_TIMER_SCRIPT); 147 } 148 mStateFragmentStore.mLast.clear(); 149 bool ret = runScript(mRootScript.get(), 0); 150 151 GLenum err = glGetError(); 152 if (err != GL_NO_ERROR) { 153 LOGE("Pending GL Error, 0x%x", err); 154 } 155 156 return ret; 157} 158 159uint64_t Context::getTime() const 160{ 161 struct timespec t; 162 clock_gettime(CLOCK_MONOTONIC, &t); 163 return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000); 164} 165 166void Context::timerReset() 167{ 168 for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) { 169 mTimers[ct] = 0; 170 } 171} 172 173void Context::timerInit() 174{ 175 mTimeLast = getTime(); 176 mTimeFrame = mTimeLast; 177 mTimeLastFrame = mTimeLast; 178 mTimerActive = RS_TIMER_INTERNAL; 179 timerReset(); 180} 181 182void Context::timerFrame() 183{ 184 mTimeLastFrame = mTimeFrame; 185 mTimeFrame = getTime(); 186} 187 188void Context::timerSet(Timers tm) 189{ 190 uint64_t last = mTimeLast; 191 mTimeLast = getTime(); 192 mTimers[mTimerActive] += mTimeLast - last; 193 mTimerActive = tm; 194} 195 196void Context::timerPrint() 197{ 198 double total = 0; 199 for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) { 200 total += mTimers[ct]; 201 } 202 uint64_t frame = mTimeFrame - mTimeLastFrame; 203 204 LOGV("RS: Frame (%lli), Script %2.1f (%lli), Clear & Swap %2.1f (%lli), Idle %2.1f (%lli), Internal %2.1f (%lli)", 205 frame / 1000000, 206 100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimers[RS_TIMER_SCRIPT] / 1000000, 207 100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimers[RS_TIMER_CLEAR_SWAP] / 1000000, 208 100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000, 209 100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000); 210} 211 212void Context::setupCheck() 213{ 214 mFragmentStore->setupGL(this, &mStateFragmentStore); 215 mFragment->setupGL(this, &mStateFragment); 216 mRaster->setupGL(this, &mStateRaster); 217 mVertex->setupGL(this, &mStateVertex); 218} 219 220static bool getProp(const char *str) 221{ 222 char buf[PROPERTY_VALUE_MAX]; 223 property_get(str, buf, "0"); 224 return 0 != strcmp(buf, "0"); 225} 226 227void * Context::threadProc(void *vrsc) 228{ 229 Context *rsc = static_cast<Context *>(vrsc); 230 231 rsc->props.mLogTimes = getProp("debug.rs.profile"); 232 rsc->props.mLogScripts = getProp("debug.rs.script"); 233 rsc->props.mLogObjects = getProp("debug.rs.objects"); 234 235 rsc->initEGL(); 236 237 ScriptTLSStruct *tlsStruct = new ScriptTLSStruct; 238 if (!tlsStruct) { 239 LOGE("Error allocating tls storage"); 240 return NULL; 241 } 242 tlsStruct->mContext = rsc; 243 tlsStruct->mScript = NULL; 244 int status = pthread_setspecific(rsc->gThreadTLSKey, tlsStruct); 245 if (status) { 246 LOGE("pthread_setspecific %i", status); 247 } 248 249 rsc->mStateRaster.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight); 250 rsc->setRaster(NULL); 251 rsc->mStateVertex.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight); 252 rsc->setVertex(NULL); 253 rsc->mStateFragment.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight); 254 rsc->setFragment(NULL); 255 rsc->mStateFragmentStore.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight); 256 rsc->setFragmentStore(NULL); 257 258 rsc->mRunning = true; 259 bool mDraw = true; 260 while (!rsc->mExit) { 261 mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw); 262 mDraw &= (rsc->mRootScript.get() != NULL); 263 264 if (mDraw) { 265 mDraw = rsc->runRootScript() && !rsc->mPaused; 266 if (rsc->props.mLogTimes) { 267 rsc->timerSet(RS_TIMER_CLEAR_SWAP); 268 } 269 eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface); 270 if (rsc->props.mLogTimes) { 271 rsc->timerFrame(); 272 rsc->timerSet(RS_TIMER_INTERNAL); 273 rsc->timerPrint(); 274 rsc->timerReset(); 275 } 276 } 277 if (rsc->mObjDestroy.mNeedToEmpty) { 278 rsc->objDestroyOOBRun(); 279 } 280 } 281 282 LOGV("RS Thread exiting"); 283 rsc->mRaster.clear(); 284 rsc->mFragment.clear(); 285 rsc->mVertex.clear(); 286 rsc->mFragmentStore.clear(); 287 rsc->mRootScript.clear(); 288 rsc->mStateRaster.deinit(rsc); 289 rsc->mStateVertex.deinit(rsc); 290 rsc->mStateFragment.deinit(rsc); 291 rsc->mStateFragmentStore.deinit(rsc); 292 ObjectBase::zeroAllUserRef(rsc); 293 294 glClearColor(0,0,0,0); 295 glClear(GL_COLOR_BUFFER_BIT); 296 eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface); 297 eglTerminate(rsc->mEGL.mDisplay); 298 rsc->objDestroyOOBRun(); 299 LOGV("RS Thread exited"); 300 return NULL; 301} 302 303Context::Context(Device *dev, Surface *sur, bool useDepth) 304{ 305 pthread_mutex_lock(&gInitMutex); 306 307 dev->addContext(this); 308 mDev = dev; 309 mRunning = false; 310 mExit = false; 311 mUseDepth = useDepth; 312 mPaused = false; 313 mObjHead = NULL; 314 315 int status; 316 pthread_attr_t threadAttr; 317 318 if (!gThreadTLSKeyCount) { 319 status = pthread_key_create(&gThreadTLSKey, NULL); 320 if (status) { 321 LOGE("Failed to init thread tls key."); 322 pthread_mutex_unlock(&gInitMutex); 323 return; 324 } 325 } 326 gThreadTLSKeyCount++; 327 pthread_mutex_unlock(&gInitMutex); 328 329 // Global init done at this point. 330 331 status = pthread_attr_init(&threadAttr); 332 if (status) { 333 LOGE("Failed to init thread attribute."); 334 return; 335 } 336 337 sched_param sparam; 338 sparam.sched_priority = ANDROID_PRIORITY_DISPLAY; 339 pthread_attr_setschedparam(&threadAttr, &sparam); 340 341 mWndSurface = sur; 342 343 objDestroyOOBInit(); 344 timerInit(); 345 timerSet(RS_TIMER_INTERNAL); 346 347 LOGV("RS Launching thread"); 348 status = pthread_create(&mThreadId, &threadAttr, threadProc, this); 349 if (status) { 350 LOGE("Failed to start rs context thread."); 351 } 352 353 while(!mRunning) { 354 usleep(100); 355 } 356 357 pthread_attr_destroy(&threadAttr); 358} 359 360Context::~Context() 361{ 362 LOGV("Context::~Context"); 363 mExit = true; 364 mPaused = false; 365 void *res; 366 367 mIO.shutdown(); 368 int status = pthread_join(mThreadId, &res); 369 objDestroyOOBRun(); 370 371 // Global structure cleanup. 372 pthread_mutex_lock(&gInitMutex); 373 if (mDev) { 374 mDev->removeContext(this); 375 --gThreadTLSKeyCount; 376 if (!gThreadTLSKeyCount) { 377 pthread_key_delete(gThreadTLSKey); 378 } 379 } 380 pthread_mutex_unlock(&gInitMutex); 381 382 objDestroyOOBDestroy(); 383} 384 385void Context::pause() 386{ 387 mPaused = true; 388} 389 390void Context::resume() 391{ 392 mPaused = false; 393} 394 395void Context::setRootScript(Script *s) 396{ 397 mRootScript.set(s); 398} 399 400void Context::setFragmentStore(ProgramFragmentStore *pfs) 401{ 402 if (pfs == NULL) { 403 mFragmentStore.set(mStateFragmentStore.mDefault); 404 } else { 405 mFragmentStore.set(pfs); 406 } 407} 408 409void Context::setFragment(ProgramFragment *pf) 410{ 411 if (pf == NULL) { 412 mFragment.set(mStateFragment.mDefault); 413 } else { 414 mFragment.set(pf); 415 } 416} 417 418void Context::setRaster(ProgramRaster *pr) 419{ 420 if (pr == NULL) { 421 mRaster.set(mStateRaster.mDefault); 422 } else { 423 mRaster.set(pr); 424 } 425} 426 427void Context::allocationCheck(const Allocation *a) 428{ 429 mVertex->checkUpdatedAllocation(a); 430 mFragment->checkUpdatedAllocation(a); 431 mFragmentStore->checkUpdatedAllocation(a); 432} 433 434void Context::setVertex(ProgramVertex *pv) 435{ 436 if (pv == NULL) { 437 mVertex.set(mStateVertex.mDefault); 438 } else { 439 mVertex.set(pv); 440 } 441} 442 443void Context::assignName(ObjectBase *obj, const char *name, uint32_t len) 444{ 445 rsAssert(!obj->getName()); 446 obj->setName(name, len); 447 mNames.add(obj); 448} 449 450void Context::removeName(ObjectBase *obj) 451{ 452 for(size_t ct=0; ct < mNames.size(); ct++) { 453 if (obj == mNames[ct]) { 454 mNames.removeAt(ct); 455 return; 456 } 457 } 458} 459 460ObjectBase * Context::lookupName(const char *name) const 461{ 462 for(size_t ct=0; ct < mNames.size(); ct++) { 463 if (!strcmp(name, mNames[ct]->getName())) { 464 return mNames[ct]; 465 } 466 } 467 return NULL; 468} 469 470void Context::appendNameDefines(String8 *str) const 471{ 472 char buf[256]; 473 for (size_t ct=0; ct < mNames.size(); ct++) { 474 str->append("#define NAMED_"); 475 str->append(mNames[ct]->getName()); 476 str->append(" "); 477 sprintf(buf, "%i\n", (int)mNames[ct]); 478 str->append(buf); 479 } 480} 481 482void Context::appendVarDefines(String8 *str) const 483{ 484 char buf[256]; 485 for (size_t ct=0; ct < mInt32Defines.size(); ct++) { 486 str->append("#define "); 487 str->append(mInt32Defines.keyAt(ct)); 488 str->append(" "); 489 sprintf(buf, "%i\n", (int)mInt32Defines.valueAt(ct)); 490 str->append(buf); 491 492 } 493 for (size_t ct=0; ct < mFloatDefines.size(); ct++) { 494 str->append("#define "); 495 str->append(mFloatDefines.keyAt(ct)); 496 str->append(" "); 497 sprintf(buf, "%ff\n", mFloatDefines.valueAt(ct)); 498 str->append(buf); 499 } 500} 501 502bool Context::objDestroyOOBInit() 503{ 504 int status = pthread_mutex_init(&mObjDestroy.mMutex, NULL); 505 if (status) { 506 LOGE("Context::ObjDestroyOOBInit mutex init failure"); 507 return false; 508 } 509 return true; 510} 511 512void Context::objDestroyOOBRun() 513{ 514 if (mObjDestroy.mNeedToEmpty) { 515 int status = pthread_mutex_lock(&mObjDestroy.mMutex); 516 if (status) { 517 LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status); 518 return; 519 } 520 521 for (size_t ct = 0; ct < mObjDestroy.mDestroyList.size(); ct++) { 522 mObjDestroy.mDestroyList[ct]->decUserRef(); 523 } 524 mObjDestroy.mDestroyList.clear(); 525 mObjDestroy.mNeedToEmpty = false; 526 527 status = pthread_mutex_unlock(&mObjDestroy.mMutex); 528 if (status) { 529 LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status); 530 } 531 } 532} 533 534void Context::objDestroyOOBDestroy() 535{ 536 rsAssert(!mObjDestroy.mNeedToEmpty); 537 pthread_mutex_destroy(&mObjDestroy.mMutex); 538} 539 540void Context::objDestroyAdd(ObjectBase *obj) 541{ 542 int status = pthread_mutex_lock(&mObjDestroy.mMutex); 543 if (status) { 544 LOGE("Context::ObjDestroyOOBRun: error %i locking for OOBRun.", status); 545 return; 546 } 547 548 mObjDestroy.mNeedToEmpty = true; 549 mObjDestroy.mDestroyList.add(obj); 550 551 status = pthread_mutex_unlock(&mObjDestroy.mMutex); 552 if (status) { 553 LOGE("Context::ObjDestroyOOBRun: error %i unlocking for set condition.", status); 554 } 555} 556 557uint32_t Context::getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait) 558{ 559 //LOGE("getMessageToClient %i %i", bufferLen, wait); 560 if (!wait) { 561 if (mIO.mToClient.isEmpty()) { 562 // No message to get and not going to wait for one. 563 receiveLen = 0; 564 return 0; 565 } 566 } 567 568 //LOGE("getMessageToClient 2 con=%p", this); 569 uint32_t bytesData = 0; 570 uint32_t commandID = 0; 571 const void *d = mIO.mToClient.get(&commandID, &bytesData); 572 //LOGE("getMessageToClient 3 %i %i", commandID, bytesData); 573 574 *receiveLen = bytesData; 575 if (bufferLen >= bytesData) { 576 memcpy(data, d, bytesData); 577 mIO.mToClient.next(); 578 return commandID; 579 } 580 return 0; 581} 582 583bool Context::sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace) 584{ 585 //LOGE("sendMessageToClient %i %i %i", cmdID, len, waitForSpace); 586 if (cmdID == 0) { 587 LOGE("Attempting to send invalid command 0 to client."); 588 return false; 589 } 590 if (!waitForSpace) { 591 if (mIO.mToClient.getFreeSpace() < len) { 592 // Not enough room, and not waiting. 593 return false; 594 } 595 } 596 //LOGE("sendMessageToClient 2"); 597 void *p = mIO.mToClient.reserve(len); 598 memcpy(p, data, len); 599 mIO.mToClient.commit(cmdID, len); 600 //LOGE("sendMessageToClient 3"); 601 return true; 602} 603 604void Context::initToClient() 605{ 606 while(!mRunning) { 607 usleep(100); 608 } 609} 610 611void Context::deinitToClient() 612{ 613 mIO.mToClient.shutdown(); 614} 615 616 617/////////////////////////////////////////////////////////////////////////////////////////// 618// 619 620namespace android { 621namespace renderscript { 622 623 624void rsi_ContextBindRootScript(Context *rsc, RsScript vs) 625{ 626 Script *s = static_cast<Script *>(vs); 627 rsc->setRootScript(s); 628} 629 630void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs) 631{ 632 Sampler *s = static_cast<Sampler *>(vs); 633 634 if (slot > RS_MAX_SAMPLER_SLOT) { 635 LOGE("Invalid sampler slot"); 636 return; 637 } 638 639 s->bindToContext(&rsc->mStateSampler, slot); 640} 641 642void rsi_ContextBindProgramFragmentStore(Context *rsc, RsProgramFragmentStore vpfs) 643{ 644 ProgramFragmentStore *pfs = static_cast<ProgramFragmentStore *>(vpfs); 645 rsc->setFragmentStore(pfs); 646} 647 648void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf) 649{ 650 ProgramFragment *pf = static_cast<ProgramFragment *>(vpf); 651 rsc->setFragment(pf); 652} 653 654void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr) 655{ 656 ProgramRaster *pr = static_cast<ProgramRaster *>(vpr); 657 rsc->setRaster(pr); 658} 659 660void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv) 661{ 662 ProgramVertex *pv = static_cast<ProgramVertex *>(vpv); 663 rsc->setVertex(pv); 664} 665 666void rsi_AssignName(Context *rsc, void * obj, const char *name, uint32_t len) 667{ 668 ObjectBase *ob = static_cast<ObjectBase *>(obj); 669 rsc->assignName(ob, name, len); 670} 671 672void rsi_ObjDestroy(Context *rsc, void *obj) 673{ 674 ObjectBase *ob = static_cast<ObjectBase *>(obj); 675 rsc->removeName(ob); 676 ob->decUserRef(); 677} 678 679void rsi_ContextSetDefineF(Context *rsc, const char* name, float value) 680{ 681 rsc->addInt32Define(name, value); 682} 683 684void rsi_ContextSetDefineI32(Context *rsc, const char* name, int32_t value) 685{ 686 rsc->addFloatDefine(name, value); 687} 688 689void rsi_ContextPause(Context *rsc) 690{ 691 rsc->pause(); 692} 693 694void rsi_ContextResume(Context *rsc) 695{ 696 rsc->resume(); 697} 698 699} 700} 701 702 703RsContext rsContextCreate(RsDevice vdev, void *sur, uint32_t version, bool useDepth) 704{ 705 Device * dev = static_cast<Device *>(vdev); 706 Context *rsc = new Context(dev, (Surface *)sur, useDepth); 707 return rsc; 708} 709 710void rsContextDestroy(RsContext vrsc) 711{ 712 Context * rsc = static_cast<Context *>(vrsc); 713 delete rsc; 714} 715 716void rsObjDestroyOOB(RsContext vrsc, void *obj) 717{ 718 Context * rsc = static_cast<Context *>(vrsc); 719 rsc->objDestroyAdd(static_cast<ObjectBase *>(obj)); 720} 721 722uint32_t rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, size_t bufferLen, bool wait) 723{ 724 Context * rsc = static_cast<Context *>(vrsc); 725 return rsc->getMessageToClient(data, receiveLen, bufferLen, wait); 726} 727 728void rsContextInitToClient(RsContext vrsc) 729{ 730 Context * rsc = static_cast<Context *>(vrsc); 731 rsc->initToClient(); 732} 733 734void rsContextDeinitToClient(RsContext vrsc) 735{ 736 Context * rsc = static_cast<Context *>(vrsc); 737 rsc->deinitToClient(); 738} 739 740