diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 857524b34..2305b69e1 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -84,7 +84,7 @@ public: BOOL setSize(LLCoordScreen size); BOOL setSize(LLCoordWindow size); virtual void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true); - virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = NULL) = 0; + virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp = NULL) = 0; virtual BOOL setCursorPosition(LLCoordWindow position) = 0; virtual BOOL getCursorPosition(LLCoordWindow *position) = 0; virtual void showCursor() = 0; diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h index ae3cd90f2..0364c5340 100644 --- a/indra/llwindow/llwindowheadless.h +++ b/indra/llwindow/llwindowheadless.h @@ -48,7 +48,7 @@ public: /*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;}; /*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;}; /*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;}; - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = NULL) {return FALSE;}; + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp = NULL) {return FALSE;}; /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;}; /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;}; /*virtual*/ void showCursor() {}; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index dcde667e3..9be125958 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -659,7 +659,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits // We only support OS X 10.7's fullscreen app mode which is literally a full screen window that fills a virtual desktop. // This makes this method obsolete. -BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp) +BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp) { return FALSE; } diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index 292af641a..581a44563 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -61,7 +61,7 @@ public: /*virtual*/ BOOL setPosition(LLCoordScreen position); /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = nullptr); + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp = nullptr); /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); /*virtual*/ void showCursor(); diff --git a/indra/llwindow/llwindowmesaheadless.h b/indra/llwindow/llwindowmesaheadless.h index e85c27f87..e11622576 100644 --- a/indra/llwindow/llwindowmesaheadless.h +++ b/indra/llwindow/llwindowmesaheadless.h @@ -51,7 +51,7 @@ public: /*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;}; /*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;}; /*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;}; - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = NULL) {return FALSE;}; + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp = NULL) {return FALSE;}; /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;}; /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;}; /*virtual*/ void showCursor() {}; diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 2c02cd143..79c8f8420 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -734,7 +734,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B // changing fullscreen resolution, or switching between windowed and fullscreen mode. -BOOL LLWindowSDL::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp) +BOOL LLWindowSDL::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp) { const BOOL needsRebuild = TRUE; // Just nuke the context and start over. BOOL result = true; @@ -743,6 +743,7 @@ BOOL LLWindowSDL::switchContext(BOOL fullscreen, const LLCoordScreen &size, cons stop_glerror(); if(needsRebuild) { + if (stopFn) stopFn(); destroyContext(); result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, vsync_mode); if (result) @@ -751,6 +752,7 @@ BOOL LLWindowSDL::switchContext(BOOL fullscreen, const LLCoordScreen &size, cons initCursors(); setCursor( UI_CURSOR_ARROW ); } + if (restoreFn) restoreFn(true); } stop_glerror(); diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index 9a80856c5..311782180 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -65,7 +65,7 @@ public: /*virtual*/ BOOL setPosition(LLCoordScreen position); /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = NULL); + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp = NULL); /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); /*virtual*/ void showCursor(); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 219eb282c..ded2d827a 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -677,7 +677,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, initDPIAwareness(); - if (!switchContext(mFullscreen, windowSize, vsync_mode, &windowPos)) + + if (!switchContext(mFullscreen, windowSize, vsync_mode, nullptr, nullptr, &windowPos)) { return; } @@ -956,7 +957,7 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size) } // changing fullscreen resolution -BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp) +BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp) { GLuint pixel_format; DEVMODE dev_mode; @@ -986,20 +987,25 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, co } gGLManager.shutdownGL(); - //destroy gl context + class ContextHandle + { + public: + ContextHandle(HGLRC context) : mOldContext(context) + {} + ~ContextHandle() + { + wglDeleteContext(mOldContext); + } + operator HGLRC() const { return mOldContext; } + private: + HGLRC mOldContext; + } oldContext = mhRC; if (mhRC) { if (!wglMakeCurrent(NULL, NULL)) { LL_WARNS("Window") << "Release of DC and RC failed" << LL_ENDL; } - - if (!wglDeleteContext(mhRC)) - { - LL_WARNS("Window") << "Release of rendering context failed" << LL_ENDL; - } - - mhRC = NULL; } if (fullscreen) @@ -1509,6 +1515,7 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, co } mhRC = 0; + bool sharedContext = false; if (wglCreateContextAttribsARB) { //attempt to create a specific versioned context S32 attribs[] = @@ -1523,8 +1530,11 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, co bool done = false; while (!done) { - mhRC = wglCreateContextAttribsARB(mhDC, mhRC, attribs); - + sharedContext = oldContext && (mhRC = wglCreateContextAttribsARB(mhDC, oldContext, attribs)) != nullptr; + if (!sharedContext) + { + mhRC = wglCreateContextAttribsARB(mhDC, nullptr, attribs); + } if (!mhRC) { if (attribs[3] > 0) @@ -1555,7 +1565,11 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, co } } - if (!mhRC && !(mhRC = wglCreateContext(mhDC))) + bool abort = !mhRC && !(mhRC = wglCreateContext(mhDC)); + + if (!sharedContext && stopFn) stopFn(); + + if (abort) { close(); OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); @@ -1626,6 +1640,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, co glGetIntegerv(GL_SAMPLES, &buf); LL_INFOS() << "Acquired FSAA Samples = " << buf << LL_ENDL; + if(restoreFn) restoreFn(!sharedContext); + return TRUE; } diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 02466adde..63c31a4d5 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -57,7 +57,7 @@ public: /*virtual*/ BOOL setPosition(LLCoordScreen position); /*virtual*/ BOOL setSizeImpl(LLCoordScreen size); /*virtual*/ BOOL setSizeImpl(LLCoordWindow size); - /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, const LLCoordScreen * const posp = NULL); + /*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, const S32 vsync_mode, std::function stopFn, std::function restoreFn, const LLCoordScreen * const posp = NULL); /*virtual*/ BOOL setCursorPosition(LLCoordWindow position); /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position); /*virtual*/ void showCursor(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index d505395c2..5854038ab 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -5395,26 +5395,39 @@ void LLViewerWindow::stopGL(BOOL save_state) } } -void LLViewerWindow::restoreGL(const std::string& progress_message) +void LLViewerWindow::restoreGLState() +{ + gGL.init(); + stop_glerror(); + initGLDefaults(); + stop_glerror(); + gGL.refreshState(); //Singu Note: Call immediately. Cached states may have prevented initGLDefaults from actually applying changes. + stop_glerror(); + LLGLStateValidator::restoreGL(); + stop_glerror(); +} + +void LLViewerWindow::restoreGL(bool full_restore, const std::string& progress_message) { //Note: --bao //if not necessary, do not change the order of the function calls in this function. //if change something, make sure it will not break anything. //especially, be careful to put something before gTextureList.restoreGL(); + if (!gGLManager.mIsDisabled && !full_restore) + { + LL_INFOS() << "Restoring GL state..." << LL_ENDL; + restoreGLState(); + gPipeline.releaseOcclusionBuffers(); // Occlusion handles must be invalidated + return; + } if (gGLManager.mIsDisabled) { stop_glerror(); LL_INFOS() << "Restoring GL..." << LL_ENDL; gGLManager.mIsDisabled = FALSE; - gGL.init(); - stop_glerror(); - initGLDefaults(); - stop_glerror(); - gGL.refreshState(); //Singu Note: Call immediately. Cached states may have prevented initGLDefaults from actually applying changes. - stop_glerror(); - LLGLStateValidator::restoreGL(); - stop_glerror(); + restoreGLState(); + gTextureList.restoreGL(); stop_glerror(); @@ -5617,11 +5630,11 @@ void LLViewerWindow::restartDisplay(BOOL show_progress_bar) stopGL(); if (show_progress_bar) { - restoreGL(LLTrans::getString("ProgressChangingResolution")); + restoreGL(true, LLTrans::getString("ProgressChangingResolution")); } else { - restoreGL(); + restoreGL(true); } } @@ -5669,7 +5682,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); send_agent_pause(); LL_INFOS() << "Stopping GL during changeDisplaySettings" << LL_ENDL; - stopGL(); + //stopGL(); mIgnoreActivate = TRUE; LLCoordScreen old_size; LLCoordScreen old_pos; @@ -5695,12 +5708,18 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, mWindow->setFSAASamples(fsaa); mWindow->setVsyncMode(vsync_mode); - result_first_try = mWindow->switchContext(fullscreen, size, vsync_mode, &new_pos); + auto stopfn = [this]() { this->stopGL(); }; + auto restoreFn = [this, show_progress_bar](bool full_restore) { + LL_INFOS() << "Restoring GL during resolution change" << LL_ENDL; + this->restoreGL(full_restore, show_progress_bar ? LLTrans::getString("ProgressChangingResolution") : ""); + }; + + result_first_try = mWindow->switchContext(fullscreen, size, vsync_mode, stopfn, restoreFn, &new_pos); if (!result_first_try) { // try to switch back mWindow->setFSAASamples(old_fsaa); - result_second_try = mWindow->switchContext(old_fullscreen, old_size, vsync_mode, &new_pos); + result_second_try = mWindow->switchContext(old_fullscreen, old_size, vsync_mode, stopfn, restoreFn, &new_pos); if (!result_second_try) { @@ -5712,16 +5731,6 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, } send_agent_resume(); - LL_INFOS() << "Restoring GL during resolution change" << LL_ENDL; - if (show_progress_bar) - { - restoreGL(LLTrans::getString("ProgressChangingResolution")); - } - else - { - restoreGL(); - } - if (!result_first_try) { LLSD args; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index f444081a5..c47efb95c 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -414,11 +414,11 @@ private: bool shouldShowToolTipFor(LLMouseHandler *mh); static bool onAlert(const LLSD& notify); - void switchToolByMask(MASK mask); void destroyWindow(); void drawMouselookInstructions(); void stopGL(BOOL save_state = TRUE); - void restoreGL(const std::string& progress_message = LLStringUtil::null); + void restoreGLState(); + void restoreGL(bool full_restore, const std::string& progress_message = LLStringUtil::null); void initFonts(F32 zoom_factor = 1.f); void schedulePick(LLPickInfo& pick_info); S32 getChatConsoleBottomPad(); // Vertical padding for child console rect, varied by bottom clutter diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index fd8e2b686..2fc5c822f 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -978,6 +978,22 @@ void LLPipeline::refreshCachedSettings() && gGLManager.mHasOcclusionQuery) ? 2 : 0; } +void LLPipeline::releaseOcclusionBuffers() +{ + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + part->resetVertexBuffers(); + } + } + } +} void LLPipeline::releaseVertexBuffers() { mCubeVB = NULL; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 701053a35..09d438b83 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -117,6 +117,7 @@ public: void resetVertexBuffers(); void doResetVertexBuffers(bool forced = false); void resizeScreenTexture(); + void releaseOcclusionBuffers(); void releaseVertexBuffers(); void releaseGLBuffers(); void releaseLUTBuffers();