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