diff --git a/CHANGELOG.md b/CHANGELOG.md index 026a65c24..dfb6532f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Bug #4021: Attributes and skills are not stored as floats Bug #4055: Local scripts don't inherit variables from their base record Bug #4623: Corprus implementation is incorrect + Bug #4631: Setting MSAA level too high doesn't fall back to highest supported level Bug #4764: Data race in osg ParticleSystem Bug #4774: Guards are ignorant of an invisible player that tries to attack them Bug #5108: Savegame bloating due to inefficient fog textures format diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index f42dfe3f7..5f0884a9e 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -525,65 +525,80 @@ void OMW::Engine::createWindow(Settings::Manager& settings) checkSDLError(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing)); } - while (!mWindow) + osg::ref_ptr graphicsWindow; + while (!graphicsWindow || !graphicsWindow->valid()) { - mWindow = SDL_CreateWindow("OpenMW", pos_x, pos_y, width, height, flags); - if (!mWindow) + while (!mWindow) { - // Try with a lower AA - if (antialiasing > 0) + mWindow = SDL_CreateWindow("OpenMW", pos_x, pos_y, width, height, flags); + if (!mWindow) { - Log(Debug::Warning) << "Warning: " << antialiasing << "x antialiasing not supported, trying " << antialiasing/2; - antialiasing /= 2; - Settings::Manager::setInt("antialiasing", "Video", antialiasing); - checkSDLError(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing)); - continue; - } - else - { - std::stringstream error; - error << "Failed to create SDL window: " << SDL_GetError(); - throw std::runtime_error(error.str()); + // Try with a lower AA + if (antialiasing > 0) + { + Log(Debug::Warning) << "Warning: " << antialiasing << "x antialiasing not supported, trying " << antialiasing/2; + antialiasing /= 2; + Settings::Manager::setInt("antialiasing", "Video", antialiasing); + checkSDLError(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing)); + continue; + } + else + { + std::stringstream error; + error << "Failed to create SDL window: " << SDL_GetError(); + throw std::runtime_error(error.str()); + } } } - } - setWindowIcon(); - - osg::ref_ptr traits = new osg::GraphicsContext::Traits; - SDL_GetWindowPosition(mWindow, &traits->x, &traits->y); - SDL_GetWindowSize(mWindow, &traits->width, &traits->height); - traits->windowName = SDL_GetWindowTitle(mWindow); - traits->windowDecoration = !(SDL_GetWindowFlags(mWindow)&SDL_WINDOW_BORDERLESS); - traits->screenNum = SDL_GetWindowDisplayIndex(mWindow); - // We tried to get rid of the hardcoding but failed: https://github.com/OpenMW/openmw/pull/1771 - // Here goes kcat's quote: - // It's ultimately a chicken and egg problem, and the reason why the code is like it was in the first place. - // It needs a context to get the current attributes, but it needs the attributes to set up the context. - // So it just specifies the same values that were given to SDL in the hopes that it's good enough to what the window eventually gets. - traits->red = 8; - traits->green = 8; - traits->blue = 8; - traits->alpha = 0; // set to 0 to stop ScreenCaptureHandler reading the alpha channel - traits->depth = 24; - traits->stencil = 8; - traits->vsync = vsync; - traits->doubleBuffer = true; - traits->inheritedWindowData = new SDLUtil::GraphicsWindowSDL2::WindowData(mWindow); - - osg::ref_ptr graphicsWindow = new SDLUtil::GraphicsWindowSDL2(traits); - if(!graphicsWindow->valid()) throw std::runtime_error("Failed to create GraphicsContext"); + setWindowIcon(); + + osg::ref_ptr traits = new osg::GraphicsContext::Traits; + SDL_GetWindowPosition(mWindow, &traits->x, &traits->y); + SDL_GetWindowSize(mWindow, &traits->width, &traits->height); + traits->windowName = SDL_GetWindowTitle(mWindow); + traits->windowDecoration = !(SDL_GetWindowFlags(mWindow)&SDL_WINDOW_BORDERLESS); + traits->screenNum = SDL_GetWindowDisplayIndex(mWindow); + traits->vsync = vsync; + traits->inheritedWindowData = new SDLUtil::GraphicsWindowSDL2::WindowData(mWindow); + + graphicsWindow = new SDLUtil::GraphicsWindowSDL2(traits); + if (!graphicsWindow->valid()) throw std::runtime_error("Failed to create GraphicsContext"); + + if (traits->samples < antialiasing) + { + Log(Debug::Warning) << "Warning: Framebuffer MSAA level is only " << traits->samples << "x instead of " << antialiasing << "x. Trying " << antialiasing / 2 << "x instead."; + graphicsWindow->closeImplementation(); + SDL_DestroyWindow(mWindow); + mWindow = nullptr; + antialiasing /= 2; + Settings::Manager::setInt("antialiasing", "Video", antialiasing); + checkSDLError(SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing)); + continue; + } + + if (traits->red < 8) + Log(Debug::Warning) << "Warning: Framebuffer only has a " << traits->red << " bit red channel."; + if (traits->green < 8) + Log(Debug::Warning) << "Warning: Framebuffer only has a " << traits->green << " bit green channel."; + if (traits->blue < 8) + Log(Debug::Warning) << "Warning: Framebuffer only has a " << traits->blue << " bit blue channel."; + if (traits->depth < 8) + Log(Debug::Warning) << "Warning: Framebuffer only has " << traits->red << " bits of depth precision."; + + traits->alpha = 0; // set to 0 to stop ScreenCaptureHandler reading the alpha channel + } osg::ref_ptr camera = mViewer->getCamera(); camera->setGraphicsContext(graphicsWindow); - camera->setViewport(0, 0, traits->width, traits->height); + camera->setViewport(0, 0, graphicsWindow->getTraits()->width, graphicsWindow->getTraits()->height); if (Debug::shouldDebugOpenGL()) mViewer->setRealizeOperation(new Debug::EnableGLDebugOperation()); mViewer->realize(); - mViewer->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, traits->width, traits->height); + mViewer->getEventQueue()->getCurrentEventState()->setWindowRectangle(0, 0, graphicsWindow->getTraits()->width, graphicsWindow->getTraits()->height); } void OMW::Engine::setWindowIcon() diff --git a/components/sdlutil/sdlgraphicswindow.cpp b/components/sdlutil/sdlgraphicswindow.cpp index cd5e80c31..0a1951700 100644 --- a/components/sdlutil/sdlgraphicswindow.cpp +++ b/components/sdlutil/sdlgraphicswindow.cpp @@ -118,6 +118,29 @@ void GraphicsWindowSDL2::init() setSwapInterval(_traits->vsync); + // Update traits with what we've actually been given + // Use intermediate to avoid signed/unsigned mismatch + int intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &intermediateLocation); + _traits->red = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &intermediateLocation); + _traits->green = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &intermediateLocation); + _traits->blue = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &intermediateLocation); + _traits->alpha = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &intermediateLocation); + _traits->depth = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &intermediateLocation); + _traits->stencil = intermediateLocation; + + SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &intermediateLocation); + _traits->doubleBuffer = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &intermediateLocation); + _traits->sampleBuffers = intermediateLocation; + SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &intermediateLocation); + _traits->samples = intermediateLocation; + SDL_GL_MakeCurrent(oldWin, oldCtx); mValid = true;