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