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