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