rsContext.cpp revision 900f1616bf33c7ba13cf2a737832a95bcd176388
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#include <ui/egl/android_natives.h> 23 24#include <sys/types.h> 25#include <sys/resource.h> 26#include <sched.h> 27 28#include <cutils/properties.h> 29 30#include <GLES/gl.h> 31#include <GLES/glext.h> 32#include <GLES2/gl2.h> 33#include <GLES2/gl2ext.h> 34 35#include <cutils/sched_policy.h> 36 37using namespace android; 38using namespace android::renderscript; 39 40pthread_key_t Context::gThreadTLSKey = 0; 41uint32_t Context::gThreadTLSKeyCount = 0; 42uint32_t Context::gGLContextCount = 0; 43pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER; 44 45static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) { 46 if (returnVal != EGL_TRUE) { 47 fprintf(stderr, "%s() returned %d\n", op, returnVal); 48 } 49 50 for (EGLint error = eglGetError(); error != EGL_SUCCESS; error 51 = eglGetError()) { 52 fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error), 53 error); 54 } 55} 56 57void Context::initEGL(bool useGL2) 58{ 59 mEGL.mNumConfigs = -1; 60 EGLint configAttribs[128]; 61 EGLint *configAttribsPtr = configAttribs; 62 EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 63 64 memset(configAttribs, 0, sizeof(configAttribs)); 65 66 configAttribsPtr[0] = EGL_SURFACE_TYPE; 67 configAttribsPtr[1] = EGL_WINDOW_BIT; 68 configAttribsPtr += 2; 69 70 if (useGL2) { 71 configAttribsPtr[0] = EGL_RENDERABLE_TYPE; 72 configAttribsPtr[1] = EGL_OPENGL_ES2_BIT; 73 configAttribsPtr += 2; 74 } 75 76 if (mUseDepth) { 77 configAttribsPtr[0] = EGL_DEPTH_SIZE; 78 configAttribsPtr[1] = 16; 79 configAttribsPtr += 2; 80 } 81 82 if (mDev->mForceSW) { 83 configAttribsPtr[0] = EGL_CONFIG_CAVEAT; 84 configAttribsPtr[1] = EGL_SLOW_CONFIG; 85 configAttribsPtr += 2; 86 } 87 88 configAttribsPtr[0] = EGL_NONE; 89 rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint)))); 90 91 LOGV("%p initEGL start", this); 92 mEGL.mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 93 checkEglError("eglGetDisplay"); 94 95 eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion); 96 checkEglError("eglInitialize"); 97 98 status_t err = EGLUtils::selectConfigForNativeWindow(mEGL.mDisplay, configAttribs, mWndSurface, &mEGL.mConfig); 99 if (err) { 100 LOGE("%p, couldn't find an EGLConfig matching the screen format\n", this); 101 } 102 //eglChooseConfig(mEGL.mDisplay, configAttribs, &mEGL.mConfig, 1, &mEGL.mNumConfigs); 103 104 105 if (useGL2) { 106 mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, context_attribs2); 107 } else { 108 mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, NULL); 109 } 110 checkEglError("eglCreateContext"); 111 if (mEGL.mContext == EGL_NO_CONTEXT) { 112 LOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", this); 113 } 114 gGLContextCount++; 115} 116 117void Context::deinitEGL() 118{ 119 LOGV("%p, deinitEGL", this); 120 setSurface(0, 0, NULL); 121 eglDestroyContext(mEGL.mDisplay, mEGL.mContext); 122 checkEglError("eglDestroyContext"); 123 124 gGLContextCount--; 125 if (!gGLContextCount) { 126 eglTerminate(mEGL.mDisplay); 127 } 128} 129 130 131uint32_t Context::runScript(Script *s) 132{ 133 ObjectBaseRef<ProgramFragment> frag(mFragment); 134 ObjectBaseRef<ProgramVertex> vtx(mVertex); 135 ObjectBaseRef<ProgramStore> store(mFragmentStore); 136 ObjectBaseRef<ProgramRaster> raster(mRaster); 137 ObjectBaseRef<Font> font(mFont); 138 139 uint32_t ret = s->run(this); 140 141 mFragment.set(frag); 142 mVertex.set(vtx); 143 mFragmentStore.set(store); 144 mRaster.set(raster); 145 mFont.set(font); 146 return ret; 147} 148 149void Context::checkError(const char *msg) const 150{ 151 GLenum err = glGetError(); 152 if (err != GL_NO_ERROR) { 153 LOGE("%p, GL Error, 0x%x, from %s", this, err, msg); 154 } 155} 156 157uint32_t Context::runRootScript() 158{ 159 glViewport(0, 0, mWidth, mHeight); 160 161 timerSet(RS_TIMER_SCRIPT); 162 mStateFragmentStore.mLast.clear(); 163 uint32_t ret = runScript(mRootScript.get()); 164 165 checkError("runRootScript"); 166 if (mError != RS_ERROR_NONE) { 167 // If we have an error condition we stop rendering until 168 // somthing changes that might fix it. 169 ret = 0; 170 } 171 return ret; 172} 173 174uint64_t Context::getTime() const 175{ 176 struct timespec t; 177 clock_gettime(CLOCK_MONOTONIC, &t); 178 return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000); 179} 180 181void Context::timerReset() 182{ 183 for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) { 184 mTimers[ct] = 0; 185 } 186} 187 188void Context::timerInit() 189{ 190 mTimeLast = getTime(); 191 mTimeFrame = mTimeLast; 192 mTimeLastFrame = mTimeLast; 193 mTimerActive = RS_TIMER_INTERNAL; 194 timerReset(); 195} 196 197void Context::timerFrame() 198{ 199 mTimeLastFrame = mTimeFrame; 200 mTimeFrame = getTime(); 201} 202 203void Context::timerSet(Timers tm) 204{ 205 uint64_t last = mTimeLast; 206 mTimeLast = getTime(); 207 mTimers[mTimerActive] += mTimeLast - last; 208 mTimerActive = tm; 209} 210 211void Context::timerPrint() 212{ 213 double total = 0; 214 for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) { 215 total += mTimers[ct]; 216 } 217 uint64_t frame = mTimeFrame - mTimeLastFrame; 218 mTimeMSLastFrame = frame / 1000000; 219 mTimeMSLastScript = mTimers[RS_TIMER_SCRIPT] / 1000000; 220 mTimeMSLastSwap = mTimers[RS_TIMER_CLEAR_SWAP] / 1000000; 221 222 223 if (props.mLogTimes) { 224 LOGV("RS: Frame (%i), Script %2.1f (%i), Clear & Swap %2.1f (%i), Idle %2.1f (%lli), Internal %2.1f (%lli)", 225 mTimeMSLastFrame, 226 100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimeMSLastScript, 227 100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimeMSLastSwap, 228 100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000, 229 100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000); 230 } 231} 232 233bool Context::setupCheck() 234{ 235 if (!mShaderCache.lookup(this, mVertex.get(), mFragment.get())) { 236 LOGE("Context::setupCheck() 1 fail"); 237 return false; 238 } 239 240 mFragmentStore->setupGL2(this, &mStateFragmentStore); 241 mFragment->setupGL2(this, &mStateFragment, &mShaderCache); 242 mRaster->setupGL2(this, &mStateRaster); 243 mVertex->setupGL2(this, &mStateVertex, &mShaderCache); 244 return true; 245} 246 247static bool getProp(const char *str) 248{ 249 char buf[PROPERTY_VALUE_MAX]; 250 property_get(str, buf, "0"); 251 return 0 != strcmp(buf, "0"); 252} 253 254void Context::displayDebugStats() 255{ 256 char buffer[128]; 257 sprintf(buffer, "Frame %i ms, Script %i ms", mTimeMSLastFrame, mTimeMSLastScript); 258 float oldR, oldG, oldB, oldA; 259 mStateFont.getFontColor(&oldR, &oldG, &oldB, &oldA); 260 261 float shadowCol = 0.2f; 262 mStateFont.setFontColor(shadowCol, shadowCol, shadowCol, 1.0f); 263 mStateFont.renderText(buffer, 5, getHeight() - 5); 264 265 float textCol = 0.9f; 266 mStateFont.setFontColor(textCol, textCol, textCol, 1.0f); 267 mStateFont.renderText(buffer, 4, getHeight() - 6); 268 269 mStateFont.setFontColor(oldR, oldG, oldB, oldA); 270} 271 272void * Context::threadProc(void *vrsc) 273{ 274 Context *rsc = static_cast<Context *>(vrsc); 275 rsc->mNativeThreadId = gettid(); 276 277 setpriority(PRIO_PROCESS, rsc->mNativeThreadId, ANDROID_PRIORITY_DISPLAY); 278 rsc->mThreadPriority = ANDROID_PRIORITY_DISPLAY; 279 280 rsc->props.mLogTimes = getProp("debug.rs.profile"); 281 rsc->props.mLogScripts = getProp("debug.rs.script"); 282 rsc->props.mLogObjects = getProp("debug.rs.object"); 283 rsc->props.mLogShaders = getProp("debug.rs.shader"); 284 rsc->props.mLogVisual = getProp("debug.rs.visual"); 285 286 ScriptTLSStruct *tlsStruct = new ScriptTLSStruct; 287 if (!tlsStruct) { 288 LOGE("Error allocating tls storage"); 289 return NULL; 290 } 291 tlsStruct->mContext = rsc; 292 tlsStruct->mScript = NULL; 293 int status = pthread_setspecific(rsc->gThreadTLSKey, tlsStruct); 294 if (status) { 295 LOGE("pthread_setspecific %i", status); 296 } 297 298 if (rsc->mIsGraphicsContext) { 299 rsc->mStateRaster.init(rsc); 300 rsc->setRaster(NULL); 301 rsc->mStateVertex.init(rsc); 302 rsc->setVertex(NULL); 303 rsc->mStateFragment.init(rsc); 304 rsc->setFragment(NULL); 305 rsc->mStateFragmentStore.init(rsc); 306 rsc->setFragmentStore(NULL); 307 rsc->mStateFont.init(rsc); 308 rsc->setFont(NULL); 309 rsc->mStateVertexArray.init(rsc); 310 } 311 312 rsc->mRunning = true; 313 bool mDraw = true; 314 while (!rsc->mExit) { 315 mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw); 316 mDraw &= (rsc->mRootScript.get() != NULL); 317 mDraw &= (rsc->mWndSurface != NULL); 318 319 uint32_t targetTime = 0; 320 if (mDraw && rsc->mIsGraphicsContext) { 321 targetTime = rsc->runRootScript(); 322 323 if(rsc->props.mLogVisual) { 324 rsc->displayDebugStats(); 325 } 326 327 mDraw = targetTime && !rsc->mPaused; 328 rsc->timerSet(RS_TIMER_CLEAR_SWAP); 329 eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface); 330 rsc->timerFrame(); 331 rsc->timerSet(RS_TIMER_INTERNAL); 332 rsc->timerPrint(); 333 rsc->timerReset(); 334 } 335 if (rsc->mThreadPriority > 0 && targetTime) { 336 int32_t t = (targetTime - (int32_t)(rsc->mTimeMSLastScript + rsc->mTimeMSLastSwap)) * 1000; 337 if (t > 0) { 338 usleep(t); 339 } 340 } 341 } 342 343 LOGV("%p, RS Thread exiting", rsc); 344 if (rsc->mIsGraphicsContext) { 345 rsc->mRaster.clear(); 346 rsc->mFragment.clear(); 347 rsc->mVertex.clear(); 348 rsc->mFragmentStore.clear(); 349 rsc->mFont.clear(); 350 rsc->mRootScript.clear(); 351 rsc->mStateRaster.deinit(rsc); 352 rsc->mStateVertex.deinit(rsc); 353 rsc->mStateFragment.deinit(rsc); 354 rsc->mStateFragmentStore.deinit(rsc); 355 rsc->mStateFont.deinit(rsc); 356 } 357 ObjectBase::zeroAllUserRef(rsc); 358 359 if (rsc->mIsGraphicsContext) { 360 pthread_mutex_lock(&gInitMutex); 361 rsc->deinitEGL(); 362 pthread_mutex_unlock(&gInitMutex); 363 } 364 365 LOGV("%p, RS Thread exited", rsc); 366 return NULL; 367} 368 369void * Context::helperThreadProc(void *vrsc) 370{ 371 Context *rsc = static_cast<Context *>(vrsc); 372 uint32_t idx = (uint32_t)android_atomic_inc(&rsc->mWorkers.mLaunchCount); 373 374 LOGV("RS helperThread starting %p idx=%i", rsc, idx); 375 376 rsc->mWorkers.mLaunchSignals[idx].init(); 377 rsc->mWorkers.mNativeThreadId[idx] = gettid(); 378 379 //cpu_set_t cpset[16]; 380 //int ret = sched_getaffinity(rsc->mWorkers.mNativeThreadId[idx], sizeof(cpset), &cpset); 381 //LOGE("ret = %i", ret); 382 383//sched_setaffinity 384 385 setpriority(PRIO_PROCESS, rsc->mWorkers.mNativeThreadId[idx], rsc->mThreadPriority); 386 while(rsc->mRunning) { 387 rsc->mWorkers.mLaunchSignals[idx].wait(); 388 if (rsc->mWorkers.mLaunchCallback) { 389 rsc->mWorkers.mLaunchCallback(rsc->mWorkers.mLaunchData, idx); 390 } 391 android_atomic_dec(&rsc->mWorkers.mRunningCount); 392 rsc->mWorkers.mCompleteSignal.set(); 393 } 394 395 LOGV("RS helperThread exiting %p idx=%i", rsc, idx); 396 return NULL; 397} 398 399void Context::launchThreads(WorkerCallback_t cbk, void *data) 400{ 401 mWorkers.mLaunchData = data; 402 mWorkers.mLaunchCallback = cbk; 403 mWorkers.mRunningCount = (int)mWorkers.mCount; 404 for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) { 405 mWorkers.mLaunchSignals[ct].set(); 406 } 407 while(mWorkers.mRunningCount) { 408 mWorkers.mCompleteSignal.wait(); 409 } 410} 411 412void Context::setPriority(int32_t p) 413{ 414 // Note: If we put this in the proper "background" policy 415 // the wallpapers can become completly unresponsive at times. 416 // This is probably not what we want for something the user is actively 417 // looking at. 418 mThreadPriority = p; 419#if 0 420 SchedPolicy pol = SP_FOREGROUND; 421 if (p > 0) { 422 pol = SP_BACKGROUND; 423 } 424 if (!set_sched_policy(mNativeThreadId, pol)) { 425 // success; reset the priority as well 426 } 427#else 428 setpriority(PRIO_PROCESS, mNativeThreadId, p); 429 for (uint32_t ct=0; ct < mWorkers.mCount; ct++) { 430 setpriority(PRIO_PROCESS, mWorkers.mNativeThreadId[ct], p); 431 } 432#endif 433} 434 435Context::Context(Device *dev, bool isGraphics, bool useDepth) 436{ 437 pthread_mutex_lock(&gInitMutex); 438 439 dev->addContext(this); 440 mDev = dev; 441 mRunning = false; 442 mExit = false; 443 mUseDepth = useDepth; 444 mPaused = false; 445 mObjHead = NULL; 446 mError = RS_ERROR_NONE; 447 mErrorMsg = NULL; 448 449 memset(&mEGL, 0, sizeof(mEGL)); 450 memset(&mGL, 0, sizeof(mGL)); 451 mIsGraphicsContext = isGraphics; 452 453 int status; 454 pthread_attr_t threadAttr; 455 456 if (!gThreadTLSKeyCount) { 457 status = pthread_key_create(&gThreadTLSKey, NULL); 458 if (status) { 459 LOGE("Failed to init thread tls key."); 460 pthread_mutex_unlock(&gInitMutex); 461 return; 462 } 463 } 464 gThreadTLSKeyCount++; 465 pthread_mutex_unlock(&gInitMutex); 466 467 // Global init done at this point. 468 469 status = pthread_attr_init(&threadAttr); 470 if (status) { 471 LOGE("Failed to init thread attribute."); 472 return; 473 } 474 475 mWndSurface = NULL; 476 477 timerInit(); 478 timerSet(RS_TIMER_INTERNAL); 479 480 int cpu = sysconf(_SC_NPROCESSORS_ONLN); 481 LOGV("RS Launching thread(s), reported CPU count %i", cpu); 482 if (cpu < 2) cpu = 0; 483 484 mWorkers.mCount = (uint32_t)cpu; 485 mWorkers.mThreadId = (pthread_t *) calloc(mWorkers.mCount, sizeof(pthread_t)); 486 mWorkers.mNativeThreadId = (pid_t *) calloc(mWorkers.mCount, sizeof(pid_t)); 487 mWorkers.mLaunchSignals = new Signal[mWorkers.mCount]; 488 mWorkers.mLaunchCallback = NULL; 489 status = pthread_create(&mThreadId, &threadAttr, threadProc, this); 490 if (status) { 491 LOGE("Failed to start rs context thread."); 492 return; 493 } 494 while(!mRunning) { 495 usleep(100); 496 } 497 498 mWorkers.mRunningCount = 0; 499 mWorkers.mLaunchCount = 0; 500 for (uint32_t ct=0; ct < mWorkers.mCount; ct++) { 501 status = pthread_create(&mWorkers.mThreadId[ct], &threadAttr, helperThreadProc, this); 502 if (status) { 503 mWorkers.mCount = ct; 504 LOGE("Created fewer than expected number of RS threads."); 505 break; 506 } 507 } 508 509 510 pthread_attr_destroy(&threadAttr); 511} 512 513Context::~Context() 514{ 515 LOGV("Context::~Context"); 516 mExit = true; 517 mPaused = false; 518 void *res; 519 520 mIO.shutdown(); 521 int status = pthread_join(mThreadId, &res); 522 523 // Global structure cleanup. 524 pthread_mutex_lock(&gInitMutex); 525 if (mDev) { 526 mDev->removeContext(this); 527 --gThreadTLSKeyCount; 528 if (!gThreadTLSKeyCount) { 529 pthread_key_delete(gThreadTLSKey); 530 } 531 mDev = NULL; 532 } 533 pthread_mutex_unlock(&gInitMutex); 534} 535 536void Context::setSurface(uint32_t w, uint32_t h, ANativeWindow *sur) 537{ 538 rsAssert(mIsGraphicsContext); 539 540 EGLBoolean ret; 541 if (mEGL.mSurface != NULL) { 542 ret = eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 543 checkEglError("eglMakeCurrent", ret); 544 545 ret = eglDestroySurface(mEGL.mDisplay, mEGL.mSurface); 546 checkEglError("eglDestroySurface", ret); 547 548 mEGL.mSurface = NULL; 549 mWidth = 0; 550 mHeight = 0; 551 } 552 553 mWndSurface = sur; 554 if (mWndSurface != NULL) { 555 mWidth = w; 556 mHeight = h; 557 bool first = false; 558 if (!mEGL.mContext) { 559 first = true; 560 pthread_mutex_lock(&gInitMutex); 561 initEGL(true); 562 pthread_mutex_unlock(&gInitMutex); 563 } 564 565 mEGL.mSurface = eglCreateWindowSurface(mEGL.mDisplay, mEGL.mConfig, mWndSurface, NULL); 566 checkEglError("eglCreateWindowSurface"); 567 if (mEGL.mSurface == EGL_NO_SURFACE) { 568 LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE"); 569 } 570 571 ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext); 572 checkEglError("eglMakeCurrent", ret); 573 574 mStateVertex.updateSize(this); 575 576 if (first) { 577 mGL.mVersion = glGetString(GL_VERSION); 578 mGL.mVendor = glGetString(GL_VENDOR); 579 mGL.mRenderer = glGetString(GL_RENDERER); 580 mGL.mExtensions = glGetString(GL_EXTENSIONS); 581 582 //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); 583 LOGV("GL Version %s", mGL.mVersion); 584 //LOGV("GL Vendor %s", mGL.mVendor); 585 LOGV("GL Renderer %s", mGL.mRenderer); 586 //LOGV("GL Extensions %s", mGL.mExtensions); 587 588 const char *verptr = NULL; 589 if (strlen((const char *)mGL.mVersion) > 9) { 590 if (!memcmp(mGL.mVersion, "OpenGL ES-CM", 12)) { 591 verptr = (const char *)mGL.mVersion + 12; 592 } 593 if (!memcmp(mGL.mVersion, "OpenGL ES ", 10)) { 594 verptr = (const char *)mGL.mVersion + 9; 595 } 596 } 597 598 if (!verptr) { 599 LOGE("Error, OpenGL ES Lite not supported"); 600 } else { 601 sscanf(verptr, " %i.%i", &mGL.mMajorVersion, &mGL.mMinorVersion); 602 } 603 604 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &mGL.mMaxVertexAttribs); 605 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &mGL.mMaxVertexUniformVectors); 606 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGL.mMaxVertexTextureUnits); 607 608 glGetIntegerv(GL_MAX_VARYING_VECTORS, &mGL.mMaxVaryingVectors); 609 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGL.mMaxTextureImageUnits); 610 611 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mGL.mMaxFragmentTextureImageUnits); 612 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGL.mMaxFragmentUniformVectors); 613 614 mGL.OES_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_OES_texture_npot"); 615 } 616 617 } 618} 619 620void Context::pause() 621{ 622 rsAssert(mIsGraphicsContext); 623 mPaused = true; 624} 625 626void Context::resume() 627{ 628 rsAssert(mIsGraphicsContext); 629 mPaused = false; 630} 631 632void Context::setRootScript(Script *s) 633{ 634 rsAssert(mIsGraphicsContext); 635 mRootScript.set(s); 636} 637 638void Context::setFragmentStore(ProgramStore *pfs) 639{ 640 rsAssert(mIsGraphicsContext); 641 if (pfs == NULL) { 642 mFragmentStore.set(mStateFragmentStore.mDefault); 643 } else { 644 mFragmentStore.set(pfs); 645 } 646} 647 648void Context::setFragment(ProgramFragment *pf) 649{ 650 rsAssert(mIsGraphicsContext); 651 if (pf == NULL) { 652 mFragment.set(mStateFragment.mDefault); 653 } else { 654 mFragment.set(pf); 655 } 656} 657 658void Context::setRaster(ProgramRaster *pr) 659{ 660 rsAssert(mIsGraphicsContext); 661 if (pr == NULL) { 662 mRaster.set(mStateRaster.mDefault); 663 } else { 664 mRaster.set(pr); 665 } 666} 667 668void Context::setVertex(ProgramVertex *pv) 669{ 670 rsAssert(mIsGraphicsContext); 671 if (pv == NULL) { 672 mVertex.set(mStateVertex.mDefault); 673 } else { 674 mVertex.set(pv); 675 } 676} 677 678void Context::setFont(Font *f) 679{ 680 rsAssert(mIsGraphicsContext); 681 if (f == NULL) { 682 mFont.set(mStateFont.mDefault); 683 } else { 684 mFont.set(f); 685 } 686} 687 688void Context::assignName(ObjectBase *obj, const char *name, uint32_t len) 689{ 690 rsAssert(!obj->getName()); 691 obj->setName(name, len); 692 mNames.add(obj); 693} 694 695void Context::removeName(ObjectBase *obj) 696{ 697 for(size_t ct=0; ct < mNames.size(); ct++) { 698 if (obj == mNames[ct]) { 699 mNames.removeAt(ct); 700 return; 701 } 702 } 703} 704 705uint32_t Context::getMessageToClient(void *data, size_t *receiveLen, size_t bufferLen, bool wait) 706{ 707 //LOGE("getMessageToClient %i %i", bufferLen, wait); 708 *receiveLen = 0; 709 if (!wait) { 710 if (mIO.mToClient.isEmpty()) { 711 // No message to get and not going to wait for one. 712 return 0; 713 } 714 } 715 716 //LOGE("getMessageToClient 2 con=%p", this); 717 uint32_t bytesData = 0; 718 uint32_t commandID = 0; 719 const void *d = mIO.mToClient.get(&commandID, &bytesData); 720 //LOGE("getMessageToClient 3 %i %i", commandID, bytesData); 721 722 *receiveLen = bytesData; 723 if (bufferLen >= bytesData) { 724 memcpy(data, d, bytesData); 725 mIO.mToClient.next(); 726 return commandID; 727 } 728 return 0; 729} 730 731bool Context::sendMessageToClient(void *data, uint32_t cmdID, size_t len, bool waitForSpace) 732{ 733 //LOGE("sendMessageToClient %i %i %i", cmdID, len, waitForSpace); 734 if (cmdID == 0) { 735 LOGE("Attempting to send invalid command 0 to client."); 736 return false; 737 } 738 if (!waitForSpace) { 739 if (!mIO.mToClient.makeSpaceNonBlocking(len + 8)) { 740 // Not enough room, and not waiting. 741 return false; 742 } 743 } 744 //LOGE("sendMessageToClient 2"); 745 if (len > 0) { 746 void *p = mIO.mToClient.reserve(len); 747 memcpy(p, data, len); 748 mIO.mToClient.commit(cmdID, len); 749 } else { 750 mIO.mToClient.commit(cmdID, 0); 751 } 752 //LOGE("sendMessageToClient 3"); 753 return true; 754} 755 756void Context::initToClient() 757{ 758 while(!mRunning) { 759 usleep(100); 760 } 761} 762 763void Context::deinitToClient() 764{ 765 mIO.mToClient.shutdown(); 766} 767 768const char * Context::getError(RsError *err) 769{ 770 *err = mError; 771 mError = RS_ERROR_NONE; 772 if (*err != RS_ERROR_NONE) { 773 return mErrorMsg; 774 } 775 return NULL; 776} 777 778void Context::setError(RsError e, const char *msg) 779{ 780 mError = e; 781 mErrorMsg = msg; 782} 783 784 785void Context::dumpDebug() const 786{ 787 LOGE("RS Context debug %p", this); 788 LOGE("RS Context debug"); 789 790 LOGE(" EGL ver %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion); 791 LOGE(" EGL context %p surface %p, Display=%p", mEGL.mContext, mEGL.mSurface, mEGL.mDisplay); 792 LOGE(" GL vendor: %s", mGL.mVendor); 793 LOGE(" GL renderer: %s", mGL.mRenderer); 794 LOGE(" GL Version: %s", mGL.mVersion); 795 LOGE(" GL Extensions: %s", mGL.mExtensions); 796 LOGE(" GL int Versions %i %i", mGL.mMajorVersion, mGL.mMinorVersion); 797 LOGE(" RS width %i, height %i", mWidth, mHeight); 798 LOGE(" RS running %i, exit %i, useDepth %i, paused %i", mRunning, mExit, mUseDepth, mPaused); 799 LOGE(" RS pThreadID %li, nativeThreadID %i", mThreadId, mNativeThreadId); 800 801 LOGV("MAX Textures %i, %i %i", mGL.mMaxVertexTextureUnits, mGL.mMaxFragmentTextureImageUnits, mGL.mMaxTextureImageUnits); 802 LOGV("MAX Attribs %i", mGL.mMaxVertexAttribs); 803 LOGV("MAX Uniforms %i, %i", mGL.mMaxVertexUniformVectors, mGL.mMaxFragmentUniformVectors); 804 LOGV("MAX Varyings %i", mGL.mMaxVaryingVectors); 805} 806 807/////////////////////////////////////////////////////////////////////////////////////////// 808// 809 810namespace android { 811namespace renderscript { 812 813void rsi_ContextFinish(Context *rsc) 814{ 815} 816 817void rsi_ContextBindRootScript(Context *rsc, RsScript vs) 818{ 819 Script *s = static_cast<Script *>(vs); 820 rsc->setRootScript(s); 821} 822 823void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs) 824{ 825 Sampler *s = static_cast<Sampler *>(vs); 826 827 if (slot > RS_MAX_SAMPLER_SLOT) { 828 LOGE("Invalid sampler slot"); 829 return; 830 } 831 832 s->bindToContext(&rsc->mStateSampler, slot); 833} 834 835void rsi_ContextBindProgramStore(Context *rsc, RsProgramStore vpfs) 836{ 837 ProgramStore *pfs = static_cast<ProgramStore *>(vpfs); 838 rsc->setFragmentStore(pfs); 839} 840 841void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf) 842{ 843 ProgramFragment *pf = static_cast<ProgramFragment *>(vpf); 844 rsc->setFragment(pf); 845} 846 847void rsi_ContextBindProgramRaster(Context *rsc, RsProgramRaster vpr) 848{ 849 ProgramRaster *pr = static_cast<ProgramRaster *>(vpr); 850 rsc->setRaster(pr); 851} 852 853void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv) 854{ 855 ProgramVertex *pv = static_cast<ProgramVertex *>(vpv); 856 rsc->setVertex(pv); 857} 858 859void rsi_ContextBindFont(Context *rsc, RsFont vfont) 860{ 861 Font *font = static_cast<Font *>(vfont); 862 rsc->setFont(font); 863} 864 865void rsi_AssignName(Context *rsc, void * obj, const char *name, uint32_t len) 866{ 867 ObjectBase *ob = static_cast<ObjectBase *>(obj); 868 rsc->assignName(ob, name, len); 869} 870 871void rsi_GetName(Context *rsc, void * obj, const char **name) 872{ 873 ObjectBase *ob = static_cast<ObjectBase *>(obj); 874 (*name) = ob->getName(); 875} 876 877void rsi_ObjDestroy(Context *rsc, void *obj) 878{ 879 ObjectBase *ob = static_cast<ObjectBase *>(obj); 880 rsc->removeName(ob); 881 ob->decUserRef(); 882} 883 884void rsi_ContextPause(Context *rsc) 885{ 886 rsc->pause(); 887} 888 889void rsi_ContextResume(Context *rsc) 890{ 891 rsc->resume(); 892} 893 894void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, ANativeWindow *sur) 895{ 896 rsc->setSurface(w, h, sur); 897} 898 899void rsi_ContextSetPriority(Context *rsc, int32_t p) 900{ 901 rsc->setPriority(p); 902} 903 904void rsi_ContextDump(Context *rsc, int32_t bits) 905{ 906 ObjectBase::dumpAll(rsc); 907} 908 909const char * rsi_ContextGetError(Context *rsc, RsError *e) 910{ 911 const char *msg = rsc->getError(e); 912 if (*e != RS_ERROR_NONE) { 913 LOGE("RS Error %i %s", *e, msg); 914 } 915 return msg; 916} 917 918} 919} 920 921 922RsContext rsContextCreate(RsDevice vdev, uint32_t version) 923{ 924 LOGV("rsContextCreate %p", vdev); 925 Device * dev = static_cast<Device *>(vdev); 926 Context *rsc = new Context(dev, false, false); 927 return rsc; 928} 929 930RsContext rsContextCreateGL(RsDevice vdev, uint32_t version, bool useDepth) 931{ 932 LOGV("rsContextCreateGL %p, %i", vdev, useDepth); 933 Device * dev = static_cast<Device *>(vdev); 934 Context *rsc = new Context(dev, true, useDepth); 935 LOGV("rsContextCreateGL ret %p ", rsc); 936 return rsc; 937} 938 939void rsContextDestroy(RsContext vrsc) 940{ 941 Context * rsc = static_cast<Context *>(vrsc); 942 delete rsc; 943} 944 945uint32_t rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, size_t bufferLen, bool wait) 946{ 947 Context * rsc = static_cast<Context *>(vrsc); 948 return rsc->getMessageToClient(data, receiveLen, bufferLen, wait); 949} 950 951void rsContextInitToClient(RsContext vrsc) 952{ 953 Context * rsc = static_cast<Context *>(vrsc); 954 rsc->initToClient(); 955} 956 957void rsContextDeinitToClient(RsContext vrsc) 958{ 959 Context * rsc = static_cast<Context *>(vrsc); 960 rsc->deinitToClient(); 961} 962 963